2 /* UNIX SMBlib NetBIOS implementation
5 SMBlib File Access Routines
7 Copyright (C) Richard Sharpe 1996
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "rfcnb/rfcnb.h"
28 #include "smblib/smblib-priv.h"
34 /* Open a file with file_name using desired mode and search attr */
35 /* If File_Handle is null, then create and populate a file handle */
37 SMB_File
*SMB_Open(SMB_Tree_Handle Tree_Handle
,
38 SMB_File
*File_Handle
,
44 struct RFCNB_Pkt
*pkt
;
45 int pkt_len
, param_len
;
47 struct SMB_File_Def
*file_tmp
;
49 /* We allocate a file object and copy some things ... */
51 file_tmp
= File_Handle
;
53 if (File_Handle
== NULL
) {
55 if ((file_tmp
= (SMB_File
*)malloc(sizeof(SMB_File
))) == NULL
) {
58 fprintf(stderr
, "Could not allocate file handle space ...");
61 SMBlib_errno
= SMBlibE_NoSpace
;
68 strncpy(file_tmp
-> filename
, file_name
, sizeof(file_tmp
-> filename
) - 1);
69 file_tmp
-> tree
= Tree_Handle
;
70 file_tmp
-> fid
= 0xFFFF; /* Is this an invalid FID? */
72 param_len
= strlen(file_name
) + 2; /* 1 for null, 1 for ASCII marker */
74 pkt_len
= SMB_open_len
+ param_len
;
76 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(max(pkt_len
, SMB_openr_len
));
78 if (pkt
== NULL
) { /* Really should do some error handling */
80 if (File_Handle
== NULL
)
82 SMBlib_errno
= SMBlibE_NoSpace
;
87 /* Now plug in the bits we need */
89 memset(SMB_Hdr(pkt
), 0, SMB_open_len
);
90 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
91 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBopen
;
92 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, Tree_Handle
-> con
-> pid
);
93 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, Tree_Handle
-> tid
);
94 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, Tree_Handle
-> con
-> mid
);
95 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, Tree_Handle
-> con
-> uid
);
96 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 2;
98 SSVAL(SMB_Hdr(pkt
), SMB_open_mod_offset
, mode
);
99 SSVAL(SMB_Hdr(pkt
), SMB_open_atr_offset
, search
);
100 SSVAL(SMB_Hdr(pkt
), SMB_open_bcc_offset
, param_len
);
102 /* Now plug in the file name ... */
104 p
= (char *)(SMB_Hdr(pkt
) + SMB_open_buf_offset
);
106 strcpy(p
+1, file_name
);
107 p
= p
+ strlen(file_name
);
108 *(p
+1) = 0; /* plug in a null ... */
110 /* Now send the packet and get the response ... */
112 if (RFCNB_Send(Tree_Handle
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
115 fprintf(stderr
, "Error sending Open request\n");
118 if (File_Handle
== NULL
)
121 SMBlib_errno
= -SMBlibE_SendFailed
;
126 /* Now get the response ... */
129 fprintf(stderr
, "Pkt_Len for Open resp = %i\n", pkt_len
);
132 if (RFCNB_Recv(Tree_Handle
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
135 fprintf(stderr
, "Error receiving response to open request\n");
138 if (File_Handle
= NULL
)
141 SMBlib_errno
= -SMBlibE_RecvFailed
;
146 /* Now parse the response and pass back any error ... */
148 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
151 fprintf(stderr
, "SMB_Open failed with errorclass = %i, Error Code = %i\n",
152 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
153 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
156 if (File_Handle
= NULL
)
158 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
160 SMBlib_errno
= SMBlibE_Remote
;
161 return(NULL
); /* Should clean up ... */
165 file_tmp
-> fid
= SVAL(SMB_Hdr(pkt
), SMB_openr_fid_offset
);
166 file_tmp
-> lastmod
= IVAL(SMB_Hdr(pkt
), SMB_openr_tim_offset
);
167 file_tmp
-> size
= IVAL(SMB_Hdr(pkt
), SMB_openr_fsz_offset
);
168 file_tmp
-> access
= SVAL(SMB_Hdr(pkt
), SMB_openr_acc_offset
);
169 file_tmp
-> fileloc
= 0;
171 RFCNB_Free_Pkt(pkt
); /* Free up this space */
174 fprintf(stderr
, "SMB_Open succeeded, FID = %i\n", file_tmp
-> fid
);
183 /* Close the file referred to in File_Handle */
185 int SMB_Close(SMB_File
*File_Handle
)
188 struct SMB_Close_Prot_Def
*prot_pkt
;
189 struct SMB_Hdr_Def_LM12
*resp_pkt
;
190 struct RFCNB_Pkt
*pkt
;
193 if (File_Handle
== NULL
) { /* Error */
195 /*SMBLIB_errno = SMBLIBE_BadHandle; */
200 pkt_len
= SMB_clos_len
;
202 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
204 if (pkt
== NULL
) { /* Really should do some error handling */
206 SMBlib_errno
= SMBlibE_NoSpace
;
211 /* Now plug in the bits we need */
213 memset(SMB_Hdr(pkt
), 0, SMB_clos_len
);
214 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
215 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBclose
;
216 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, File_Handle
-> tree
-> con
-> pid
);
217 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, File_Handle
-> tree
-> tid
);
218 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, File_Handle
-> tree
-> con
-> mid
);
219 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, File_Handle
-> tree
-> con
-> uid
);
220 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 3;
222 SSVAL(SMB_Hdr(pkt
), SMB_clos_fid_offset
, File_Handle
-> fid
);
223 SIVAL(SMB_Hdr(pkt
), SMB_clos_tim_offset
, 0);
224 SSVAL(SMB_Hdr(pkt
), SMB_clos_bcc_offset
, 0);
226 /* Now send the packet and get the response ... */
228 if (RFCNB_Send(File_Handle
-> tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
231 fprintf(stderr
, "Error sending Open request\n");
235 SMBlib_errno
= SMBlibE_SendFailed
;
240 /* Now get the response ... */
242 if (RFCNB_Recv(File_Handle
-> tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
245 fprintf(stderr
, "Error receiving response to open request\n");
249 SMBlib_errno
= SMBlibE_RecvFailed
;
254 /* Now parse the response and pass back any error ... */
256 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
259 fprintf(stderr
, "SMB_Close failed with errorclass = %i, Error Code = %i\n",
260 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
261 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
264 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
266 SMBlib_errno
= SMBlibE_Remote
;
267 return(SMBlibE_BAD
); /* Should clean up ... */
272 fprintf(stderr
, "File %s closed successfully.\n", File_Handle
-> filename
);
275 /* We should deallocate the File_Handle now ... */
277 File_Handle
-> tree
= NULL
;
278 File_Handle
-> filename
[0] = 0;
279 File_Handle
-> fid
= 0xFFFF;
287 /* Read numbytes into data from the file pointed to by File_Handle from */
288 /* the offset in the File_Handle. */
290 int SMB_Read(SMB_File
*File_Handle
, char *data
, int numbytes
)
294 struct RFCNB_Pkt
*snd_pkt
, *recv_pkt
, *data_ptr
;
295 int snd_pkt_len
, recv_pkt_len
, this_read
, bytes_left
= numbytes
;
296 int max_read_data
, bytes_read
= 0;
298 /* We loop around, reading the data, accumulating it into the buffer */
299 /* We build an SMB packet, where the data is pointed to by a fragment*/
300 /* tagged onto the end */
302 data_ptr
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(0);
303 if (data_ptr
== NULL
) {
305 /* We should handle the error here */
307 SMBlib_errno
= SMBlibE_NoSpace
;
312 snd_pkt_len
= SMB_read_len
; /* size for the read SMB */
313 recv_pkt_len
= SMB_readr_len
+ 3; /* + 3 for the datablockID and blklen */
315 snd_pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(snd_pkt_len
);
317 if (snd_pkt
== NULL
) {
319 RFCNB_Free_Pkt(data_ptr
);
320 SMBlib_errno
= SMBlibE_NoSpace
;
325 recv_pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(recv_pkt_len
);
327 if (recv_pkt
== NULL
) {
329 RFCNB_Free_Pkt(snd_pkt
);
330 RFCNB_Free_Pkt(data_ptr
);
331 SMBlib_errno
= SMBlibE_NoSpace
;
336 /* Put the recv pkt together */
338 recv_pkt
-> next
= data_ptr
;
340 /* Now build the read request and the receive packet etc ... */
342 memset(SMB_Hdr(snd_pkt
), 0, SMB_read_len
);
343 SIVAL(SMB_Hdr(snd_pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
344 *(SMB_Hdr(snd_pkt
) + SMB_hdr_com_offset
) = SMBread
;
345 SSVAL(SMB_Hdr(snd_pkt
), SMB_hdr_pid_offset
, File_Handle
-> tree
-> con
-> pid
);
346 SSVAL(SMB_Hdr(snd_pkt
), SMB_hdr_tid_offset
, File_Handle
-> tree
-> tid
);
347 SSVAL(SMB_Hdr(snd_pkt
), SMB_hdr_mid_offset
, File_Handle
-> tree
-> con
-> mid
);
348 SSVAL(SMB_Hdr(snd_pkt
), SMB_hdr_uid_offset
, File_Handle
-> tree
-> con
-> uid
);
349 *(SMB_Hdr(snd_pkt
) + SMB_hdr_wct_offset
) = 5;
350 SSVAL(SMB_Hdr(snd_pkt
), SMB_read_fid_offset
, File_Handle
-> fid
);
352 max_read_data
= (File_Handle
-> tree
-> mbs
) - recv_pkt_len
;
354 while (bytes_left
> 0) {
356 this_read
= (bytes_left
> max_read_data
?max_read_data
: bytes_left
);
358 SSVAL(SMB_Hdr(snd_pkt
), SMB_read_cnt_offset
, this_read
);
359 SIVAL(SMB_Hdr(snd_pkt
), SMB_read_ofs_offset
, File_Handle
-> fileloc
);
360 SSVAL(SMB_Hdr(snd_pkt
), SMB_read_clf_offset
, 0x0);
361 SSVAL(SMB_Hdr(snd_pkt
), SMB_read_bcc_offset
, 0x0);
363 /* Now send the packet and wait for a response */
365 if (RFCNB_Send(File_Handle
-> tree
-> con
-> Trans_Connect
, snd_pkt
, snd_pkt_len
) < 0) {
368 fprintf(stderr
, "Error sending read request\n");
371 data_ptr
-> data
= NULL
;
373 RFCNB_Free_Pkt(recv_pkt
);
374 RFCNB_Free_Pkt(snd_pkt
);
375 SMBlib_errno
= SMBlibE_SendFailed
;
380 /* Now get the response ... first point the data portion to the right */
381 /* place in the read buffer ... what we are doing is ugly */
383 data_ptr
-> data
= (data
+ bytes_read
);
384 data_ptr
-> len
= this_read
;
386 if (RFCNB_Recv(File_Handle
-> tree
-> con
-> Trans_Connect
, recv_pkt
, recv_pkt_len
+ this_read
) < 0) {
389 fprintf(stderr
, "Error receiving response to write\n");
393 data_ptr
-> data
= NULL
;
394 RFCNB_Free_Pkt(recv_pkt
);
395 RFCNB_Free_Pkt(snd_pkt
);
396 SMBlib_errno
= SMBlibE_RecvFailed
;
401 if (CVAL(SMB_Hdr(recv_pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
404 fprintf(stderr
, "SMB_Read failed with errorclass = %i, Error Code = %i\n",
405 CVAL(SMB_Hdr(recv_pkt
), SMB_hdr_rcls_offset
),
406 SVAL(SMB_Hdr(recv_pkt
), SMB_hdr_err_offset
));
409 SMBlib_SMB_Error
= IVAL(SMB_Hdr(recv_pkt
), SMB_hdr_rcls_offset
);
410 data_ptr
-> data
= NULL
;
412 RFCNB_Free_Pkt(recv_pkt
);
413 RFCNB_Free_Pkt(snd_pkt
);
414 SMBlib_errno
= SMBlibE_Remote
;
419 /* Ok, that worked, so update some things here ... */
421 bytes_read
= bytes_read
+ SVAL(SMB_Hdr(recv_pkt
), SMB_readr_cnt_offset
);
422 bytes_left
= bytes_left
- SVAL(SMB_Hdr(recv_pkt
), SMB_readr_cnt_offset
);
426 /* Now free those packet headers that we allocated ... */
428 data_ptr
-> data
= NULL
; /* Since recv_pkt points to data_ptr */
429 data_ptr
-> len
= 0; /* it is freed too */
430 RFCNB_Free_Pkt(recv_pkt
);
431 RFCNB_Free_Pkt(snd_pkt
);
437 /* Lseek seeks just like the UNIX version does ... */
439 off_t
SMB_Lseek(SMB_File
*File_Handle
, off_t offset
, int whence
)
443 /* We should check that the file handle is kosher ... We may also blow up
444 if we get a 64 bit offset ... should avoid wrap-around ... */
449 File_Handle
-> fileloc
= offset
;
454 File_Handle
-> fileloc
= File_Handle
-> fileloc
+ offset
;
459 File_Handle
-> fileloc
= File_Handle
-> size
+ offset
;
467 return(File_Handle
-> fileloc
);
471 /* Write numbytes from data to the file pointed to by the File_Handle at */
472 /* the offset in the File_Handle. */
474 int SMB_Write(SMB_File
*File_Handle
, char *data
, int numbytes
)
478 struct RFCNB_Pkt
*pkt
, *data_ptr
;
479 int pkt_len
, i
, this_write
, max_write_data
, bytes_left
= numbytes
;
481 /* We loop around, writing the data, accumulating what was written */
482 /* We build an SMB packet, where the data is pointed to by a fragment */
483 /* tagged onto the end ... */
485 data_ptr
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(0);
486 if (data_ptr
== NULL
) {
488 SMBlib_errno
= SMBlibE_NoSpace
;
493 pkt_len
= SMB_write_len
+ 3; /* + 3 for the datablockID and blklen */
495 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
499 RFCNB_Free_Pkt(data_ptr
);
500 SMBlib_errno
= SMBlibE_NoSpace
;
505 /* Now init the things that will be the same across the possibly multiple
506 packets to write this data. */
508 memset(SMB_Hdr(pkt
), 0, SMB_write_len
);
509 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
510 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBwrite
;
511 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, File_Handle
-> tree
-> con
-> pid
);
512 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, File_Handle
-> tree
-> tid
);
513 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, File_Handle
-> tree
-> con
-> mid
);
514 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, File_Handle
-> tree
-> con
-> uid
);
515 SSVAL(SMB_Hdr(pkt
), SMB_write_fid_offset
, File_Handle
-> fid
);
517 /* We will program this as send/response for the moment, but if we could
518 only send the second block before getting the first, we could speed
519 things up a bit ... */
521 max_write_data
= (File_Handle
-> tree
-> mbs
) - pkt_len
;
523 /* the 3 is for the data block id and length that preceeds the data */
525 while (bytes_left
> 0) {
527 /* bytes to write? */
529 this_write
= (bytes_left
> max_write_data
?max_write_data
:bytes_left
);
531 data_ptr
-> next
= NULL
;
532 data_ptr
-> len
= this_write
;
533 data_ptr
-> data
= data
+ tot_written
;
535 pkt
-> next
= data_ptr
; /* link the data on the end */
537 SSVAL(SMB_Hdr(pkt
), SMB_hdr_flg_offset
, 0);
538 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 5;
539 SSVAL(SMB_Hdr(pkt
), SMB_write_fid_offset
, File_Handle
-> fid
);
540 SSVAL(SMB_Hdr(pkt
), SMB_write_cnt_offset
, this_write
);
541 SIVAL(SMB_Hdr(pkt
), SMB_write_ofs_offset
, File_Handle
-> fileloc
);
542 SSVAL(SMB_Hdr(pkt
), SMB_write_clf_offset
, 0);
543 SSVAL(SMB_Hdr(pkt
), SMB_write_bcc_offset
, (this_write
+ 3));
545 *(SMB_Hdr(pkt
) + SMB_write_buf_offset
) = SMBdatablockID
;
546 SSVAL(SMB_Hdr(pkt
), SMB_write_buf_offset
+ 1, this_write
);
548 /* Now send the packet and wait for a response */
550 if (RFCNB_Send(File_Handle
-> tree
-> con
-> Trans_Connect
, pkt
, pkt_len
+ this_write
) < 0) {
553 fprintf(stderr
, "Error sending write request\n");
556 data_ptr
-> next
= NULL
;
559 SMBlib_errno
= -SMBlibE_SendFailed
;
564 /* Now get the response ... */
566 if (RFCNB_Recv(File_Handle
-> tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
569 fprintf(stderr
, "Error receiving response to write\n");
572 data_ptr
-> next
= NULL
;
575 SMBlib_errno
= -SMBlibE_RecvFailed
;
580 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
583 fprintf(stderr
, "SMB_Write failed with errorclass = %i, Error Code = %i\n",
584 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
585 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
588 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
589 data_ptr
-> data
= NULL
;
592 SMBlib_errno
= SMBlibE_Remote
;
597 /* Ok, that worked, so update some things here ... */
599 tot_written
= tot_written
+ this_write
;
600 bytes_left
= bytes_left
- this_write
;
602 /* Assume that it is ok to update this now, but what about only part */
603 /* of the write succeeding? */
605 File_Handle
-> fileloc
= File_Handle
-> fileloc
+ this_write
;
608 fprintf(stderr
, "--This_write = %i, bytes_left = %i\n",
609 this_write
, bytes_left
);
614 /* Let's get rid of those packet headers we are using ... */
616 data_ptr
-> data
= NULL
;
625 /* Create file on the server with name file_name and attributes search */
627 SMB_File
*SMB_Create(SMB_Tree_Handle Tree_Handle
,
628 SMB_File
*File_Handle
,
633 struct RFCNB_Pkt
*pkt
;
634 int pkt_len
, param_len
;
636 struct SMB_File_Def
*file_tmp
;
638 /* We allocate a file object and copy some things ... */
640 file_tmp
= File_Handle
;
642 if (File_Handle
== NULL
) {
644 if ((file_tmp
= (SMB_File
*)malloc(sizeof(SMB_File
))) == NULL
) {
647 fprintf(stderr
, "Could not allocate file handle space ...");
650 SMBlib_errno
= SMBlibE_NoSpace
;
657 strncpy(file_tmp
-> filename
, file_name
, sizeof(file_tmp
-> filename
));
658 file_tmp
-> tree
= Tree_Handle
;
659 file_tmp
-> fid
= 0xFFFF; /* Is this an invalid FID? */
661 param_len
= strlen(file_name
) + 2; /* 1 for null, 1 for ASCII marker */
663 pkt_len
= SMB_creat_len
+ param_len
;
665 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
667 if (pkt
== NULL
) { /* Really should do some error handling */
669 if (File_Handle
== NULL
)
671 SMBlib_errno
= SMBlibE_NoSpace
;
676 /* Now plug in the bits we need */
678 memset(SMB_Hdr(pkt
), 0, SMB_creat_len
);
679 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
680 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBcreate
;
681 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, Tree_Handle
-> con
-> pid
);
682 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, Tree_Handle
-> tid
);
683 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, Tree_Handle
-> con
-> mid
);
684 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, Tree_Handle
-> con
-> uid
);
685 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 3;
687 SSVAL(SMB_Hdr(pkt
), SMB_creat_atr_offset
, search
);
688 SSVAL(SMB_Hdr(pkt
), SMB_creat_tim_offset
, 0);
689 SSVAL(SMB_Hdr(pkt
), SMB_creat_dat_offset
, 0);
690 SSVAL(SMB_Hdr(pkt
), SMB_creat_bcc_offset
, param_len
);
692 /* Now plug in the file name ... */
694 p
= (char *)(SMB_Hdr(pkt
) + SMB_creat_buf_offset
);
696 strcpy(p
+1, file_name
);
697 p
= p
+ strlen(file_name
);
698 *(p
+1) = 0; /* plug in a null ... */
700 /* Now send the packet and get the response ... */
702 if (RFCNB_Send(Tree_Handle
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
705 fprintf(stderr
, "Error sending Open request\n");
708 if (File_Handle
== NULL
)
711 SMBlib_errno
= -SMBlibE_SendFailed
;
716 /* Now get the response ... */
719 fprintf(stderr
, "Pkt_Len for Create resp = %i\n", pkt_len
);
722 if (RFCNB_Recv(Tree_Handle
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
725 fprintf(stderr
, "Error receiving response to create request\n");
728 if (File_Handle
== NULL
)
731 SMBlib_errno
= -SMBlibE_RecvFailed
;
736 /* Now parse the response and pass back any error ... */
738 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
741 fprintf(stderr
, "SMB_Create failed with errorclass = %i, Error Code = %i\n",
742 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
743 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
746 if (File_Handle
== NULL
)
748 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
750 SMBlib_errno
= SMBlibE_Remote
;
751 return(NULL
); /* Should clean up ... */
755 file_tmp
-> fid
= SVAL(SMB_Hdr(pkt
), SMB_creatr_fid_offset
);
756 file_tmp
-> lastmod
= 0;
757 file_tmp
-> size
= 0;
758 file_tmp
-> access
= SMB_AMODE_OPENRW
;
759 file_tmp
-> fileloc
= 0;
761 RFCNB_Free_Pkt(pkt
); /* Free up this space */
764 fprintf(stderr
, "SMB_Create succeeded, FID = %i\n", file_tmp
-> fid
);
771 /* Delete the file passed in as file_name. */
773 int SMB_Delete(SMB_Tree_Handle tree
, char *file_name
, WORD search
)
776 struct RFCNB_Pkt
*pkt
;
777 int pkt_len
, param_len
;
780 param_len
= strlen(file_name
) + 2;
781 pkt_len
= SMB_delet_len
+ param_len
;
783 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
785 if (pkt
== NULL
) { /* Really should do some error handling */
787 SMBlib_errno
= SMBlibE_NoSpace
;
792 /* Now plug in the bits we need */
794 memset(SMB_Hdr(pkt
), 0, SMB_delet_len
);
795 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
796 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBunlink
;
797 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
798 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
799 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
800 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
801 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 1;
803 SIVAL(SMB_Hdr(pkt
), SMB_delet_sat_offset
, search
);
804 SSVAL(SMB_Hdr(pkt
), SMB_delet_bcc_offset
, param_len
);
806 /* Now plug in the file name ... */
808 p
= (char *)(SMB_Hdr(pkt
) + SMB_delet_buf_offset
);
810 strcpy(p
+1, file_name
);
811 p
= p
+ strlen(file_name
);
812 *(p
+1) = 0; /* plug in a null ... */
814 /* Now send the packet and get the response ... */
816 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
819 fprintf(stderr
, "Error sending Delete request\n");
823 SMBlib_errno
= -SMBlibE_SendFailed
;
828 /* Now get the response ... */
830 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
833 fprintf(stderr
, "Error receiving response to delete request\n");
837 SMBlib_errno
= -SMBlibE_RecvFailed
;
842 /* Now parse the response and pass back any error ... */
844 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
847 fprintf(stderr
, "SMB_Delete failed with errorclass = %i, Error Code = %i\n",
848 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
849 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
852 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
854 SMBlib_errno
= SMBlibE_Remote
;
855 return(SMBlibE_BAD
); /* Should clean up ... */
860 fprintf(stderr
, "File %s deleted successfully.\n", file_name
);
868 /* Create the directory passed in as dir_name */
870 int SMB_Create_Dir(SMB_Tree_Handle tree
, char *dir_name
)
873 struct RFCNB_Pkt
*pkt
;
874 int pkt_len
, param_len
;
877 param_len
= strlen(dir_name
) + 2; /* + null and + asciiID */
878 pkt_len
= SMB_creatdir_len
+ param_len
;
880 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
882 if (pkt
== NULL
) { /* Really should do some error handling */
884 SMBlib_errno
= SMBlibE_NoSpace
;
889 /* Now plug in the bits we need */
891 memset(SMB_Hdr(pkt
), 0, SMB_creatdir_len
);
892 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
893 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBmkdir
;
894 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
895 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
896 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
897 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
898 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
900 SSVAL(SMB_Hdr(pkt
), SMB_creatdir_bcc_offset
, param_len
);
902 /* Now plug in the file name ... */
904 p
= (char *)(SMB_Hdr(pkt
) + SMB_creatdir_buf_offset
);
906 strcpy(p
+1, dir_name
);
907 p
= p
+ strlen(dir_name
);
908 *(p
+1) = 0; /* plug in a null ... */
910 /* Now send the packet and get the response ... */
912 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
915 fprintf(stderr
, "Error sending Create Dir request\n");
919 SMBlib_errno
= -SMBlibE_SendFailed
;
924 /* Now get the response ... */
926 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
929 fprintf(stderr
, "Error receiving response to Create Dir request\n");
933 SMBlib_errno
= -SMBlibE_RecvFailed
;
938 /* Now parse the response and pass back any error ... */
940 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
943 fprintf(stderr
, "SMB_Create_Dir failed with errorclass = %i, Error Code = %i\n",
944 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
945 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
948 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
950 SMBlib_errno
= SMBlibE_Remote
;
951 return(SMBlibE_BAD
); /* Should clean up ... */
956 fprintf(stderr
, "Directory %s created successfully.\n", dir_name
);
964 /* Delete the directory passed as dir_name, as long as it is empty ... */
966 int SMB_Delete_Dir(SMB_Tree_Handle tree
, char *dir_name
)
969 struct RFCNB_Pkt
*pkt
;
970 int pkt_len
, param_len
;
973 param_len
= strlen(dir_name
) + 2; /* + null and + asciiID */
974 pkt_len
= SMB_deletdir_len
+ param_len
;
976 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
978 if (pkt
== NULL
) { /* Really should do some error handling */
980 SMBlib_errno
= SMBlibE_NoSpace
;
985 /* Now plug in the bits we need */
987 memset(SMB_Hdr(pkt
), 0, SMB_deletdir_len
);
988 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
989 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBrmdir
;
990 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
991 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
992 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
993 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
994 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
996 SSVAL(SMB_Hdr(pkt
), SMB_deletdir_bcc_offset
, param_len
);
998 /* Now plug in the file name ... */
1000 p
= (char *)(SMB_Hdr(pkt
) + SMB_deletdir_buf_offset
);
1002 strcpy(p
+1, dir_name
);
1003 p
= p
+ strlen(dir_name
);
1004 *(p
+1) = 0; /* plug in a null ... */
1006 /* Now send the packet and get the response ... */
1008 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
1011 fprintf(stderr
, "Error sending Delete Dir request\n");
1014 RFCNB_Free_Pkt(pkt
);
1015 SMBlib_errno
= -SMBlibE_SendFailed
;
1016 return(SMBlibE_BAD
);
1020 /* Now get the response ... */
1022 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
1025 fprintf(stderr
, "Error receiving response to Delete Dir request\n");
1028 RFCNB_Free_Pkt(pkt
);
1029 SMBlib_errno
= -SMBlibE_RecvFailed
;
1030 return(SMBlibE_BAD
);
1034 /* Now parse the response and pass back any error ... */
1036 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
1039 fprintf(stderr
, "SMB_Delete_Dir failed with errorclass = %i, Error Code = %i\n",
1040 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
1041 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
1044 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
1045 RFCNB_Free_Pkt(pkt
);
1046 SMBlib_errno
= SMBlibE_Remote
;
1047 return(SMBlibE_BAD
); /* Should clean up ... */
1052 fprintf(stderr
, "Directory %s deleted successfully.\n", dir_name
);
1055 RFCNB_Free_Pkt(pkt
);
1060 /* Check for the existence of the directory in dir_name */
1062 int SMB_Check_Dir(SMB_Tree_Handle tree
, char *dir_name
)
1065 struct RFCNB_Pkt
*pkt
;
1066 int pkt_len
, param_len
;
1069 param_len
= strlen(dir_name
) + 2; /* + null and + asciiID */
1070 pkt_len
= SMB_checkdir_len
+ param_len
;
1072 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
1074 if (pkt
== NULL
) { /* Really should do some error handling */
1076 SMBlib_errno
= SMBlibE_NoSpace
;
1077 return(SMBlibE_BAD
);
1081 /* Now plug in the bits we need */
1083 memset(SMB_Hdr(pkt
), 0, SMB_checkdir_len
);
1084 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
1085 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBchkpth
;
1086 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
1087 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
1088 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
1089 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
1090 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
1092 SSVAL(SMB_Hdr(pkt
), SMB_checkdir_bcc_offset
, param_len
);
1094 /* Now plug in the file name ... */
1096 p
= (char *)(SMB_Hdr(pkt
) + SMB_checkdir_buf_offset
);
1098 strcpy(p
+1, dir_name
);
1099 p
= p
+ strlen(dir_name
);
1100 *(p
+1) = 0; /* plug in a null ... */
1102 /* Now send the packet and get the response ... */
1104 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
1107 fprintf(stderr
, "Error sending Check Dir Path request\n");
1110 RFCNB_Free_Pkt(pkt
);
1111 SMBlib_errno
= -SMBlibE_SendFailed
;
1112 return(SMBlibE_BAD
);
1116 /* Now get the response ... */
1118 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
1121 fprintf(stderr
, "Error receiving response to Check Dir request\n");
1124 RFCNB_Free_Pkt(pkt
);
1125 SMBlib_errno
= -SMBlibE_RecvFailed
;
1126 return(SMBlibE_BAD
);
1130 /* Now parse the response and pass back any error ... */
1132 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
1135 fprintf(stderr
, "SMB_Check_Dir failed with errorclass = %i, Error Code = %i\n",
1136 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
1137 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
1140 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
1141 RFCNB_Free_Pkt(pkt
);
1142 SMBlib_errno
= SMBlibE_Remote
;
1143 return(SMBlibE_BAD
); /* Should clean up ... */
1148 fprintf(stderr
, "Directory %s checked successfully.\n", dir_name
);
1151 RFCNB_Free_Pkt(pkt
);
1156 /* Search directory for the files listed ... Relative to the TID in the */
1157 /* Con Handle. Return number of Dir Ents returned as the result. */
1159 int SMB_Search(SMB_Tree_Handle tree
,
1162 SMB_CP_dirent
*dirents
,
1168 struct RFCNB_Pkt
*pkt
, *recv_pkt
;
1169 int pkt_len
, param_len
, recv_param_len
, recv_pkt_len
, ret_count
, i
;
1172 param_len
= strlen(dir_name
) + 2 + resumekey_len
+ 3; /* You have to know */
1173 pkt_len
= SMB_search_len
+ param_len
;
1175 recv_param_len
= direntc
* SMB_searchr_dirent_len
+ 3;
1176 recv_pkt_len
= SMB_searchr_len
+ recv_param_len
;
1178 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
1180 if (pkt
== NULL
) { /* Really should do some error handling */
1182 SMBlib_errno
= SMBlibE_NoSpace
;
1183 return(SMBlibE_BAD
);
1187 recv_pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(recv_pkt_len
);
1189 if (recv_pkt
== NULL
) { /* Really should do some error handling */
1191 RFCNB_Free_Pkt(pkt
);
1192 SMBlib_errno
= SMBlibE_NoSpace
;
1193 return(SMBlibE_BAD
);
1197 /* Now plug in the bits we need */
1199 memset(SMB_Hdr(pkt
), 0, SMB_search_len
);
1200 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
1201 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBsearch
;
1202 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
1203 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
1204 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
1205 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
1207 /* Tell server we known about non-dos names and extended attibutes */
1209 SSVAL(SMB_Hdr(pkt
), SMB_hdr_flg2_offset
,
1210 (SMB_FLG2_NON_DOS
| SMB_FLG2_EXT_ATR
));
1212 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 2;
1214 SSVAL(SMB_Hdr(pkt
), SMB_search_mdc_offset
, direntc
); /* How many we want */
1215 SSVAL(SMB_Hdr(pkt
), SMB_search_atr_offset
, search
);
1216 SSVAL(SMB_Hdr(pkt
), SMB_search_bcc_offset
, param_len
);
1218 /* Now plug in the file name ... */
1220 p
= (char *)(SMB_Hdr(pkt
) + SMB_search_buf_offset
);
1222 strcpy(p
+1, dir_name
);
1223 p
= p
+ strlen(dir_name
) + 2; /* Skip the null */
1225 *p
= SMBvariableblockID
;
1228 /* And now the resume key */
1230 SSVAL(p
, 0, resumekey_len
);
1234 bcopy(resumekey
, p
, resumekey_len
);
1236 /* Now send the packet and get the response ... */
1238 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
1241 fprintf(stderr
, "Error sending search request\n");
1244 RFCNB_Free_Pkt(pkt
);
1245 RFCNB_Free_Pkt(recv_pkt
);
1246 SMBlib_errno
= -SMBlibE_SendFailed
;
1247 return(SMBlibE_BAD
);
1251 /* Now get the response ... */
1253 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, recv_pkt
, recv_pkt_len
) < 0) {
1256 fprintf(stderr
, "Error receiving response to Check Dir request\n");
1259 RFCNB_Free_Pkt(pkt
);
1260 RFCNB_Free_Pkt(recv_pkt
);
1261 SMBlib_errno
= -SMBlibE_RecvFailed
;
1262 return(SMBlibE_BAD
);
1266 /* Now parse the response and pass back any error ... */
1268 if (CVAL(SMB_Hdr(recv_pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
1271 fprintf(stderr
, "SMB_Check_Dir failed with errorclass = %i, Error Code = %i\n",
1272 CVAL(SMB_Hdr(recv_pkt
), SMB_hdr_rcls_offset
),
1273 SVAL(SMB_Hdr(recv_pkt
), SMB_hdr_err_offset
));
1276 SMBlib_SMB_Error
= IVAL(SMB_Hdr(recv_pkt
), SMB_hdr_rcls_offset
);
1277 RFCNB_Free_Pkt(pkt
);
1278 RFCNB_Free_Pkt(recv_pkt
);
1279 SMBlib_errno
= SMBlibE_Remote
;
1280 return(SMBlibE_BAD
); /* Should clean up ... */
1284 /* Now copy the results into the user's structure */
1286 ret_count
= SVAL(SMB_Hdr(recv_pkt
), SMB_searchr_dec_offset
);
1288 p
= SMB_Hdr(recv_pkt
) + SMB_searchr_buf_offset
+ 3;
1290 /* Hmmm, should check that we have the right number of bytes ... */
1292 for (i
= 0; i
< ret_count
; i
++) {
1294 bcopy(p
, dirents
[i
].resume_key
, 21);
1298 dirents
[i
].file_attributes
= (unsigned char)*p
;
1302 dirents
[i
].date_time
= IVAL(p
, 0); /* Should this be IVAL? */
1306 dirents
[i
].size
= IVAL(p
, 0);
1310 bcopy(p
, dirents
[i
].filename
, 13); /* Copy in file name */