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 "smblib/smblib-priv.h"
28 #include "rfcnb/rfcnb.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
);
472 /* Write numbytes from data to the file pointed to by the File_Handle at */
473 /* the offset in the File_Handle. */
475 int SMB_Write(SMB_File
*File_Handle
, char *data
, int numbytes
)
479 struct RFCNB_Pkt
*pkt
, *data_ptr
;
480 int pkt_len
, i
, this_write
, max_write_data
, bytes_left
= numbytes
;
482 /* We loop around, writing the data, accumulating what was written */
483 /* We build an SMB packet, where the data is pointed to by a fragment */
484 /* tagged onto the end ... */
486 data_ptr
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(0);
487 if (data_ptr
== NULL
) {
489 SMBlib_errno
= SMBlibE_NoSpace
;
494 pkt_len
= SMB_write_len
+ 3; /* + 3 for the datablockID and blklen */
496 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
500 RFCNB_Free_Pkt(data_ptr
);
501 SMBlib_errno
= SMBlibE_NoSpace
;
506 /* Now init the things that will be the same across the possibly multiple
507 packets to write this data. */
509 memset(SMB_Hdr(pkt
), 0, SMB_write_len
);
510 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
511 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBwrite
;
512 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, File_Handle
-> tree
-> con
-> pid
);
513 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, File_Handle
-> tree
-> tid
);
514 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, File_Handle
-> tree
-> con
-> mid
);
515 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, File_Handle
-> tree
-> con
-> uid
);
516 SSVAL(SMB_Hdr(pkt
), SMB_write_fid_offset
, File_Handle
-> fid
);
518 /* We will program this as send/response for the moment, but if we could
519 only send the second block before getting the first, we could speed
520 things up a bit ... */
522 max_write_data
= (File_Handle
-> tree
-> mbs
) - pkt_len
;
524 /* the 3 is for the data block id and length that preceeds the data */
526 while (bytes_left
> 0) {
528 /* bytes to write? */
530 this_write
= (bytes_left
> max_write_data
?max_write_data
:bytes_left
);
532 data_ptr
-> next
= NULL
;
533 data_ptr
-> len
= this_write
;
534 data_ptr
-> data
= data
+ tot_written
;
536 pkt
-> next
= data_ptr
; /* link the data on the end */
538 SSVAL(SMB_Hdr(pkt
), SMB_hdr_flg_offset
, 0);
539 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 5;
540 SSVAL(SMB_Hdr(pkt
), SMB_write_fid_offset
, File_Handle
-> fid
);
541 SSVAL(SMB_Hdr(pkt
), SMB_write_cnt_offset
, this_write
);
542 SIVAL(SMB_Hdr(pkt
), SMB_write_ofs_offset
, File_Handle
-> fileloc
);
543 SSVAL(SMB_Hdr(pkt
), SMB_write_clf_offset
, 0);
544 SSVAL(SMB_Hdr(pkt
), SMB_write_bcc_offset
, (this_write
+ 3));
546 *(SMB_Hdr(pkt
) + SMB_write_buf_offset
) = SMBdatablockID
;
547 SSVAL(SMB_Hdr(pkt
), SMB_write_buf_offset
+ 1, this_write
);
549 /* Now send the packet and wait for a response */
551 if (RFCNB_Send(File_Handle
-> tree
-> con
-> Trans_Connect
, pkt
, pkt_len
+ this_write
) < 0) {
554 fprintf(stderr
, "Error sending write request\n");
557 data_ptr
-> next
= NULL
;
560 SMBlib_errno
= -SMBlibE_SendFailed
;
565 /* Now get the response ... */
567 if (RFCNB_Recv(File_Handle
-> tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
570 fprintf(stderr
, "Error receiving response to write\n");
573 data_ptr
-> next
= NULL
;
576 SMBlib_errno
= -SMBlibE_RecvFailed
;
581 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
584 fprintf(stderr
, "SMB_Write failed with errorclass = %i, Error Code = %i\n",
585 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
586 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
589 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
590 data_ptr
-> data
= NULL
;
593 SMBlib_errno
= SMBlibE_Remote
;
598 /* Ok, that worked, so update some things here ... */
600 tot_written
= tot_written
+ this_write
;
601 bytes_left
= bytes_left
- this_write
;
603 /* Assume that it is ok to update this now, but what about only part */
604 /* of the write succeeding? */
606 File_Handle
-> fileloc
= File_Handle
-> fileloc
+ this_write
;
609 fprintf(stderr
, "--This_write = %i, bytes_left = %i\n",
610 this_write
, bytes_left
);
615 /* Let's get rid of those packet headers we are using ... */
617 data_ptr
-> data
= NULL
;
626 /* Create file on the server with name file_name and attributes search */
628 SMB_File
*SMB_Create(SMB_Tree_Handle Tree_Handle
,
629 SMB_File
*File_Handle
,
634 struct RFCNB_Pkt
*pkt
;
635 int pkt_len
, param_len
;
637 struct SMB_File_Def
*file_tmp
;
639 /* We allocate a file object and copy some things ... */
641 file_tmp
= File_Handle
;
643 if (File_Handle
== NULL
) {
645 if ((file_tmp
= (SMB_File
*)malloc(sizeof(SMB_File
))) == NULL
) {
648 fprintf(stderr
, "Could not allocate file handle space ...");
651 SMBlib_errno
= SMBlibE_NoSpace
;
658 strncpy(file_tmp
-> filename
, file_name
, sizeof(file_tmp
-> filename
));
659 file_tmp
-> tree
= Tree_Handle
;
660 file_tmp
-> fid
= 0xFFFF; /* Is this an invalid FID? */
662 param_len
= strlen(file_name
) + 2; /* 1 for null, 1 for ASCII marker */
664 pkt_len
= SMB_creat_len
+ param_len
;
666 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
668 if (pkt
== NULL
) { /* Really should do some error handling */
670 if (File_Handle
== NULL
)
672 SMBlib_errno
= SMBlibE_NoSpace
;
677 /* Now plug in the bits we need */
679 memset(SMB_Hdr(pkt
), 0, SMB_creat_len
);
680 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
681 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBcreate
;
682 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, Tree_Handle
-> con
-> pid
);
683 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, Tree_Handle
-> tid
);
684 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, Tree_Handle
-> con
-> mid
);
685 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, Tree_Handle
-> con
-> uid
);
686 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 3;
688 SSVAL(SMB_Hdr(pkt
), SMB_creat_atr_offset
, search
);
689 SSVAL(SMB_Hdr(pkt
), SMB_creat_tim_offset
, 0);
690 SSVAL(SMB_Hdr(pkt
), SMB_creat_dat_offset
, 0);
691 SSVAL(SMB_Hdr(pkt
), SMB_creat_bcc_offset
, param_len
);
693 /* Now plug in the file name ... */
695 p
= (char *)(SMB_Hdr(pkt
) + SMB_creat_buf_offset
);
697 strcpy(p
+1, file_name
);
698 p
= p
+ strlen(file_name
);
699 *(p
+1) = 0; /* plug in a null ... */
701 /* Now send the packet and get the response ... */
703 if (RFCNB_Send(Tree_Handle
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
706 fprintf(stderr
, "Error sending Open request\n");
709 if (File_Handle
== NULL
)
712 SMBlib_errno
= -SMBlibE_SendFailed
;
717 /* Now get the response ... */
720 fprintf(stderr
, "Pkt_Len for Create resp = %i\n", pkt_len
);
723 if (RFCNB_Recv(Tree_Handle
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
726 fprintf(stderr
, "Error receiving response to create request\n");
729 if (File_Handle
== NULL
)
732 SMBlib_errno
= -SMBlibE_RecvFailed
;
737 /* Now parse the response and pass back any error ... */
739 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
742 fprintf(stderr
, "SMB_Create failed with errorclass = %i, Error Code = %i\n",
743 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
744 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
747 if (File_Handle
== NULL
)
749 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
751 SMBlib_errno
= SMBlibE_Remote
;
752 return(NULL
); /* Should clean up ... */
756 file_tmp
-> fid
= SVAL(SMB_Hdr(pkt
), SMB_creatr_fid_offset
);
757 file_tmp
-> lastmod
= 0;
758 file_tmp
-> size
= 0;
759 file_tmp
-> access
= SMB_AMODE_OPENRW
;
760 file_tmp
-> fileloc
= 0;
762 RFCNB_Free_Pkt(pkt
); /* Free up this space */
765 fprintf(stderr
, "SMB_Create succeeded, FID = %i\n", file_tmp
-> fid
);
772 /* Delete the file passed in as file_name. */
774 int SMB_Delete(SMB_Tree_Handle tree
, char *file_name
, WORD search
)
777 struct RFCNB_Pkt
*pkt
;
778 int pkt_len
, param_len
;
781 param_len
= strlen(file_name
) + 2;
782 pkt_len
= SMB_delet_len
+ param_len
;
784 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
786 if (pkt
== NULL
) { /* Really should do some error handling */
788 SMBlib_errno
= SMBlibE_NoSpace
;
793 /* Now plug in the bits we need */
795 memset(SMB_Hdr(pkt
), 0, SMB_delet_len
);
796 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
797 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBunlink
;
798 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
799 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
800 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
801 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
802 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 1;
804 SIVAL(SMB_Hdr(pkt
), SMB_delet_sat_offset
, search
);
805 SSVAL(SMB_Hdr(pkt
), SMB_delet_bcc_offset
, param_len
);
807 /* Now plug in the file name ... */
809 p
= (char *)(SMB_Hdr(pkt
) + SMB_delet_buf_offset
);
811 strcpy(p
+1, file_name
);
812 p
= p
+ strlen(file_name
);
813 *(p
+1) = 0; /* plug in a null ... */
815 /* Now send the packet and get the response ... */
817 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
820 fprintf(stderr
, "Error sending Delete request\n");
824 SMBlib_errno
= -SMBlibE_SendFailed
;
829 /* Now get the response ... */
831 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
834 fprintf(stderr
, "Error receiving response to delete request\n");
838 SMBlib_errno
= -SMBlibE_RecvFailed
;
843 /* Now parse the response and pass back any error ... */
845 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
848 fprintf(stderr
, "SMB_Delete failed with errorclass = %i, Error Code = %i\n",
849 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
850 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
853 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
855 SMBlib_errno
= SMBlibE_Remote
;
856 return(SMBlibE_BAD
); /* Should clean up ... */
861 fprintf(stderr
, "File %s deleted successfully.\n", file_name
);
869 /* Create the directory passed in as dir_name */
871 int SMB_Create_Dir(SMB_Tree_Handle tree
, char *dir_name
)
874 struct RFCNB_Pkt
*pkt
;
875 int pkt_len
, param_len
;
878 param_len
= strlen(dir_name
) + 2; /* + null and + asciiID */
879 pkt_len
= SMB_creatdir_len
+ param_len
;
881 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
883 if (pkt
== NULL
) { /* Really should do some error handling */
885 SMBlib_errno
= SMBlibE_NoSpace
;
890 /* Now plug in the bits we need */
892 memset(SMB_Hdr(pkt
), 0, SMB_creatdir_len
);
893 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
894 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBmkdir
;
895 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
896 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
897 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
898 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
899 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
901 SSVAL(SMB_Hdr(pkt
), SMB_creatdir_bcc_offset
, param_len
);
903 /* Now plug in the file name ... */
905 p
= (char *)(SMB_Hdr(pkt
) + SMB_creatdir_buf_offset
);
907 strcpy(p
+1, dir_name
);
908 p
= p
+ strlen(dir_name
);
909 *(p
+1) = 0; /* plug in a null ... */
911 /* Now send the packet and get the response ... */
913 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
916 fprintf(stderr
, "Error sending Create Dir request\n");
920 SMBlib_errno
= -SMBlibE_SendFailed
;
925 /* Now get the response ... */
927 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
930 fprintf(stderr
, "Error receiving response to Create Dir request\n");
934 SMBlib_errno
= -SMBlibE_RecvFailed
;
939 /* Now parse the response and pass back any error ... */
941 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
944 fprintf(stderr
, "SMB_Create_Dir failed with errorclass = %i, Error Code = %i\n",
945 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
946 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
949 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
951 SMBlib_errno
= SMBlibE_Remote
;
952 return(SMBlibE_BAD
); /* Should clean up ... */
957 fprintf(stderr
, "Directory %s created successfully.\n", dir_name
);
965 /* Delete the directory passed as dir_name, as long as it is empty ... */
967 int SMB_Delete_Dir(SMB_Tree_Handle tree
, char *dir_name
)
970 struct RFCNB_Pkt
*pkt
;
971 int pkt_len
, param_len
;
974 param_len
= strlen(dir_name
) + 2; /* + null and + asciiID */
975 pkt_len
= SMB_deletdir_len
+ param_len
;
977 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
979 if (pkt
== NULL
) { /* Really should do some error handling */
981 SMBlib_errno
= SMBlibE_NoSpace
;
986 /* Now plug in the bits we need */
988 memset(SMB_Hdr(pkt
), 0, SMB_deletdir_len
);
989 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
990 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBrmdir
;
991 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
992 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
993 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
994 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
995 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
997 SSVAL(SMB_Hdr(pkt
), SMB_deletdir_bcc_offset
, param_len
);
999 /* Now plug in the file name ... */
1001 p
= (char *)(SMB_Hdr(pkt
) + SMB_deletdir_buf_offset
);
1003 strcpy(p
+1, dir_name
);
1004 p
= p
+ strlen(dir_name
);
1005 *(p
+1) = 0; /* plug in a null ... */
1007 /* Now send the packet and get the response ... */
1009 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
1012 fprintf(stderr
, "Error sending Delete Dir request\n");
1015 RFCNB_Free_Pkt(pkt
);
1016 SMBlib_errno
= -SMBlibE_SendFailed
;
1017 return(SMBlibE_BAD
);
1021 /* Now get the response ... */
1023 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
1026 fprintf(stderr
, "Error receiving response to Delete Dir request\n");
1029 RFCNB_Free_Pkt(pkt
);
1030 SMBlib_errno
= -SMBlibE_RecvFailed
;
1031 return(SMBlibE_BAD
);
1035 /* Now parse the response and pass back any error ... */
1037 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
1040 fprintf(stderr
, "SMB_Delete_Dir failed with errorclass = %i, Error Code = %i\n",
1041 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
1042 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
1045 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
1046 RFCNB_Free_Pkt(pkt
);
1047 SMBlib_errno
= SMBlibE_Remote
;
1048 return(SMBlibE_BAD
); /* Should clean up ... */
1053 fprintf(stderr
, "Directory %s deleted successfully.\n", dir_name
);
1056 RFCNB_Free_Pkt(pkt
);
1061 /* Check for the existence of the directory in dir_name */
1063 int SMB_Check_Dir(SMB_Tree_Handle tree
, char *dir_name
)
1066 struct RFCNB_Pkt
*pkt
;
1067 int pkt_len
, param_len
;
1070 param_len
= strlen(dir_name
) + 2; /* + null and + asciiID */
1071 pkt_len
= SMB_checkdir_len
+ param_len
;
1073 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
1075 if (pkt
== NULL
) { /* Really should do some error handling */
1077 SMBlib_errno
= SMBlibE_NoSpace
;
1078 return(SMBlibE_BAD
);
1082 /* Now plug in the bits we need */
1084 memset(SMB_Hdr(pkt
), 0, SMB_checkdir_len
);
1085 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
1086 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBchkpth
;
1087 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
1088 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
1089 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
1090 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
1091 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
1093 SSVAL(SMB_Hdr(pkt
), SMB_checkdir_bcc_offset
, param_len
);
1095 /* Now plug in the file name ... */
1097 p
= (char *)(SMB_Hdr(pkt
) + SMB_checkdir_buf_offset
);
1099 strcpy(p
+1, dir_name
);
1100 p
= p
+ strlen(dir_name
);
1101 *(p
+1) = 0; /* plug in a null ... */
1103 /* Now send the packet and get the response ... */
1105 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
1108 fprintf(stderr
, "Error sending Check Dir Path request\n");
1111 RFCNB_Free_Pkt(pkt
);
1112 SMBlib_errno
= -SMBlibE_SendFailed
;
1113 return(SMBlibE_BAD
);
1117 /* Now get the response ... */
1119 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
1122 fprintf(stderr
, "Error receiving response to Check Dir request\n");
1125 RFCNB_Free_Pkt(pkt
);
1126 SMBlib_errno
= -SMBlibE_RecvFailed
;
1127 return(SMBlibE_BAD
);
1131 /* Now parse the response and pass back any error ... */
1133 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
1136 fprintf(stderr
, "SMB_Check_Dir failed with errorclass = %i, Error Code = %i\n",
1137 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
1138 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
1141 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
1142 RFCNB_Free_Pkt(pkt
);
1143 SMBlib_errno
= SMBlibE_Remote
;
1144 return(SMBlibE_BAD
); /* Should clean up ... */
1149 fprintf(stderr
, "Directory %s checked successfully.\n", dir_name
);
1152 RFCNB_Free_Pkt(pkt
);
1157 /* Search directory for the files listed ... Relative to the TID in the */
1158 /* Con Handle. Return number of Dir Ents returned as the result. */
1160 int SMB_Search(SMB_Tree_Handle tree
,
1163 SMB_CP_dirent
*dirents
,
1169 struct RFCNB_Pkt
*pkt
, *recv_pkt
;
1170 int pkt_len
, param_len
, recv_param_len
, recv_pkt_len
, ret_count
, i
;
1173 param_len
= strlen(dir_name
) + 2 + resumekey_len
+ 3; /* You have to know */
1174 pkt_len
= SMB_search_len
+ param_len
;
1176 recv_param_len
= direntc
* SMB_searchr_dirent_len
+ 3;
1177 recv_pkt_len
= SMB_searchr_len
+ recv_param_len
;
1179 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
1181 if (pkt
== NULL
) { /* Really should do some error handling */
1183 SMBlib_errno
= SMBlibE_NoSpace
;
1184 return(SMBlibE_BAD
);
1188 recv_pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(recv_pkt_len
);
1190 if (recv_pkt
== NULL
) { /* Really should do some error handling */
1192 RFCNB_Free_Pkt(pkt
);
1193 SMBlib_errno
= SMBlibE_NoSpace
;
1194 return(SMBlibE_BAD
);
1199 /* Now plug in the bits we need */
1201 memset(SMB_Hdr(pkt
), 0, SMB_search_len
);
1202 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
1203 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBsearch
;
1204 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
1205 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
1206 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
1207 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
1209 /* Tell server we known about non-dos names and extended attibutes */
1211 SSVAL(SMB_Hdr(pkt
), SMB_hdr_flg2_offset
,
1212 (SMB_FLG2_NON_DOS
| SMB_FLG2_EXT_ATR
));
1214 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 2;
1216 SSVAL(SMB_Hdr(pkt
), SMB_search_mdc_offset
, direntc
); /* How many we want */
1217 SSVAL(SMB_Hdr(pkt
), SMB_search_atr_offset
, search
);
1218 SSVAL(SMB_Hdr(pkt
), SMB_search_bcc_offset
, param_len
);
1220 /* Now plug in the file name ... */
1222 p
= (char *)(SMB_Hdr(pkt
) + SMB_search_buf_offset
);
1224 strcpy(p
+1, dir_name
);
1225 p
= p
+ strlen(dir_name
) + 2; /* Skip the null */
1229 *p
= SMBvariableblockID
;
1232 /* And now the resume key */
1234 SSVAL(p
, 0, resumekey_len
);
1238 bcopy(resumekey
, p
, resumekey_len
);
1240 /* Now send the packet and get the response ... */
1242 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
1245 fprintf(stderr
, "Error sending search request\n");
1248 RFCNB_Free_Pkt(pkt
);
1249 RFCNB_Free_Pkt(recv_pkt
);
1250 SMBlib_errno
= -SMBlibE_SendFailed
;
1251 return(SMBlibE_BAD
);
1255 /* Now get the response ... */
1257 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, recv_pkt
, recv_pkt_len
) < 0) {
1260 fprintf(stderr
, "Error receiving response to Check Dir request\n");
1263 RFCNB_Free_Pkt(pkt
);
1264 RFCNB_Free_Pkt(recv_pkt
);
1265 SMBlib_errno
= -SMBlibE_RecvFailed
;
1266 return(SMBlibE_BAD
);
1270 /* Now parse the response and pass back any error ... */
1272 if (CVAL(SMB_Hdr(recv_pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
1275 fprintf(stderr
, "SMB_Check_Dir failed with errorclass = %i, Error Code = %i\n",
1276 CVAL(SMB_Hdr(recv_pkt
), SMB_hdr_rcls_offset
),
1277 SVAL(SMB_Hdr(recv_pkt
), SMB_hdr_err_offset
));
1280 SMBlib_SMB_Error
= IVAL(SMB_Hdr(recv_pkt
), SMB_hdr_rcls_offset
);
1281 RFCNB_Free_Pkt(pkt
);
1282 RFCNB_Free_Pkt(recv_pkt
);
1283 SMBlib_errno
= SMBlibE_Remote
;
1284 return(SMBlibE_BAD
); /* Should clean up ... */
1288 /* Now copy the results into the user's structure */
1290 ret_count
= SVAL(SMB_Hdr(recv_pkt
), SMB_searchr_dec_offset
);
1292 p
= SMB_Hdr(recv_pkt
) + SMB_searchr_buf_offset
+ 3;
1294 /* Hmmm, should check that we have the right number of bytes ... */
1296 for (i
= 0; i
< ret_count
; i
++) {
1298 bcopy(p
, dirents
[i
].resume_key
, 21);
1302 dirents
[i
].file_attributes
= (unsigned char)*p
;
1306 dirents
[i
].date_time
= IVAL(p
, 0); /* Should this be IVAL? */
1310 dirents
[i
].size
= IVAL(p
, 0);
1314 bcopy(p
, dirents
[i
].filename
, 13); /* Copy in file name */