]>
Commit | Line | Data |
---|---|---|
f7f3304a | 1 | #include "squid.h" |
7c16470c AJ |
2 | /* UNIX SMBlib NetBIOS implementation |
3 | ||
4 | Version 1.0 | |
5 | SMBlib File Access Routines | |
6 | ||
7 | Copyright (C) Richard Sharpe 1996 | |
8 | ||
9 | */ | |
10 | ||
11 | /* | |
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. | |
16 | ||
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. | |
21 | ||
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. | |
25 | */ | |
26 | ||
0ab648c9 AJ |
27 | #include "smblib/smblib-priv.h" |
28 | #include "rfcnb/rfcnb.h" | |
7c16470c | 29 | |
0ab648c9 AJ |
30 | #if HAVE_STRING_H |
31 | #include <string.h> | |
32 | #endif | |
7c16470c AJ |
33 | |
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 */ | |
36 | ||
37 | SMB_File *SMB_Open(SMB_Tree_Handle Tree_Handle, | |
38 | SMB_File *File_Handle, | |
39 | char *file_name, | |
40 | WORD mode, | |
41 | WORD search) | |
42 | ||
43 | { | |
44 | struct RFCNB_Pkt *pkt; | |
45 | int pkt_len, param_len; | |
46 | char *p; | |
47 | struct SMB_File_Def *file_tmp; | |
48 | ||
49 | /* We allocate a file object and copy some things ... */ | |
50 | ||
51 | file_tmp = File_Handle; | |
52 | ||
53 | if (File_Handle == NULL) { | |
54 | ||
55 | if ((file_tmp = (SMB_File *)malloc(sizeof(SMB_File))) == NULL) { | |
56 | ||
57 | #ifdef DEBUG | |
58 | fprintf(stderr, "Could not allocate file handle space ..."); | |
59 | #endif | |
60 | ||
61 | SMBlib_errno = SMBlibE_NoSpace; | |
62 | return(NULL); | |
63 | ||
64 | } | |
65 | ||
66 | } | |
67 | ||
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? */ | |
71 | ||
72 | param_len = strlen(file_name) + 2; /* 1 for null, 1 for ASCII marker */ | |
73 | ||
74 | pkt_len = SMB_open_len + param_len; | |
75 | ||
76 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(max(pkt_len, SMB_openr_len)); | |
77 | ||
78 | if (pkt == NULL) { /* Really should do some error handling */ | |
79 | ||
80 | if (File_Handle == NULL) | |
81 | free(file_tmp); | |
82 | SMBlib_errno = SMBlibE_NoSpace; | |
83 | return(NULL); | |
84 | ||
85 | } | |
86 | ||
87 | /* Now plug in the bits we need */ | |
88 | ||
0ab648c9 | 89 | memset(SMB_Hdr(pkt), 0, SMB_open_len); |
7c16470c AJ |
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; | |
97 | ||
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); | |
101 | ||
102 | /* Now plug in the file name ... */ | |
103 | ||
104 | p = (char *)(SMB_Hdr(pkt) + SMB_open_buf_offset); | |
105 | *p = SMBasciiID; | |
106 | strcpy(p+1, file_name); | |
107 | p = p + strlen(file_name); | |
108 | *(p+1) = 0; /* plug in a null ... */ | |
109 | ||
110 | /* Now send the packet and get the response ... */ | |
111 | ||
112 | if (RFCNB_Send(Tree_Handle -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
113 | ||
114 | #ifdef DEBUG | |
115 | fprintf(stderr, "Error sending Open request\n"); | |
116 | #endif | |
117 | ||
118 | if (File_Handle == NULL) | |
119 | free(file_tmp); | |
120 | RFCNB_Free_Pkt(pkt); | |
121 | SMBlib_errno = -SMBlibE_SendFailed; | |
122 | return(NULL); | |
123 | ||
124 | } | |
125 | ||
126 | /* Now get the response ... */ | |
127 | ||
128 | #ifdef DEBUG | |
129 | fprintf(stderr, "Pkt_Len for Open resp = %i\n", pkt_len); | |
130 | #endif | |
131 | ||
132 | if (RFCNB_Recv(Tree_Handle -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
133 | ||
134 | #ifdef DEBUG | |
135 | fprintf(stderr, "Error receiving response to open request\n"); | |
136 | #endif | |
137 | ||
138 | if (File_Handle = NULL) | |
139 | free(file_tmp); | |
140 | RFCNB_Free_Pkt(pkt); | |
141 | SMBlib_errno = -SMBlibE_RecvFailed; | |
142 | return(NULL); | |
143 | ||
144 | } | |
145 | ||
146 | /* Now parse the response and pass back any error ... */ | |
147 | ||
148 | if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
149 | ||
150 | #ifdef DEBUG | |
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)); | |
154 | #endif | |
155 | ||
156 | if (File_Handle = NULL) | |
157 | free(file_tmp); | |
158 | SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); | |
159 | RFCNB_Free_Pkt(pkt); | |
160 | SMBlib_errno = SMBlibE_Remote; | |
161 | return(NULL); /* Should clean up ... */ | |
162 | ||
163 | } | |
164 | ||
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; | |
170 | ||
171 | RFCNB_Free_Pkt(pkt); /* Free up this space */ | |
172 | ||
173 | #ifdef DEBUG | |
174 | fprintf(stderr, "SMB_Open succeeded, FID = %i\n", file_tmp -> fid); | |
175 | #endif | |
176 | ||
177 | RFCNB_Free_Pkt(pkt); | |
178 | ||
179 | return(file_tmp); | |
180 | ||
181 | } | |
182 | ||
183 | /* Close the file referred to in File_Handle */ | |
184 | ||
185 | int SMB_Close(SMB_File *File_Handle) | |
186 | ||
187 | { | |
188 | struct SMB_Close_Prot_Def *prot_pkt; | |
189 | struct SMB_Hdr_Def_LM12 *resp_pkt; | |
190 | struct RFCNB_Pkt *pkt; | |
191 | int pkt_len; | |
192 | ||
193 | if (File_Handle == NULL) { /* Error */ | |
194 | ||
195 | /*SMBLIB_errno = SMBLIBE_BadHandle; */ | |
196 | return(-1); | |
197 | ||
198 | } | |
199 | ||
200 | pkt_len = SMB_clos_len; | |
201 | ||
202 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
203 | ||
204 | if (pkt == NULL) { /* Really should do some error handling */ | |
205 | ||
206 | SMBlib_errno = SMBlibE_NoSpace; | |
207 | return(SMBlibE_BAD); | |
208 | ||
209 | } | |
210 | ||
211 | /* Now plug in the bits we need */ | |
212 | ||
0ab648c9 | 213 | memset(SMB_Hdr(pkt), 0, SMB_clos_len); |
7c16470c AJ |
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; | |
221 | ||
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); | |
225 | ||
226 | /* Now send the packet and get the response ... */ | |
227 | ||
228 | if (RFCNB_Send(File_Handle -> tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
229 | ||
230 | #ifdef DEBUG | |
231 | fprintf(stderr, "Error sending Open request\n"); | |
232 | #endif | |
233 | ||
234 | RFCNB_Free_Pkt(pkt); | |
235 | SMBlib_errno = SMBlibE_SendFailed; | |
236 | return(SMBlibE_BAD); | |
237 | ||
238 | } | |
239 | ||
240 | /* Now get the response ... */ | |
241 | ||
242 | if (RFCNB_Recv(File_Handle -> tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
243 | ||
244 | #ifdef DEBUG | |
245 | fprintf(stderr, "Error receiving response to open request\n"); | |
246 | #endif | |
247 | ||
248 | RFCNB_Free_Pkt(pkt); | |
249 | SMBlib_errno = SMBlibE_RecvFailed; | |
250 | return(SMBlibE_BAD); | |
251 | ||
252 | } | |
253 | ||
254 | /* Now parse the response and pass back any error ... */ | |
255 | ||
256 | if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
257 | ||
258 | #ifdef DEBUG | |
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)); | |
262 | #endif | |
263 | ||
264 | SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); | |
265 | RFCNB_Free_Pkt(pkt); | |
266 | SMBlib_errno = SMBlibE_Remote; | |
267 | return(SMBlibE_BAD); /* Should clean up ... */ | |
268 | ||
269 | } | |
270 | ||
271 | #ifdef DEBUG | |
272 | fprintf(stderr, "File %s closed successfully.\n", File_Handle -> filename); | |
273 | #endif DEBUG | |
274 | ||
275 | /* We should deallocate the File_Handle now ... */ | |
276 | ||
277 | File_Handle -> tree = NULL; | |
278 | File_Handle -> filename[0] = 0; | |
279 | File_Handle -> fid = 0xFFFF; | |
280 | ||
281 | RFCNB_Free_Pkt(pkt); | |
282 | free(File_Handle); | |
283 | ||
284 | return(0); | |
285 | } | |
286 | ||
287 | /* Read numbytes into data from the file pointed to by File_Handle from */ | |
288 | /* the offset in the File_Handle. */ | |
289 | ||
290 | int SMB_Read(SMB_File *File_Handle, char *data, int numbytes) | |
291 | ||
292 | { | |
293 | int tot_read; | |
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; | |
297 | ||
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 */ | |
301 | ||
302 | data_ptr = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(0); | |
303 | if (data_ptr == NULL) { | |
304 | ||
305 | /* We should handle the error here */ | |
306 | ||
307 | SMBlib_errno = SMBlibE_NoSpace; | |
308 | return(SMBlibE_BAD); | |
309 | ||
310 | } | |
311 | ||
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 */ | |
314 | ||
315 | snd_pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(snd_pkt_len); | |
316 | ||
317 | if (snd_pkt == NULL) { | |
318 | ||
319 | RFCNB_Free_Pkt(data_ptr); | |
320 | SMBlib_errno = SMBlibE_NoSpace; | |
321 | return(SMBlibE_BAD); | |
322 | ||
323 | } | |
324 | ||
325 | recv_pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(recv_pkt_len); | |
326 | ||
327 | if (recv_pkt == NULL) { | |
328 | ||
329 | RFCNB_Free_Pkt(snd_pkt); | |
330 | RFCNB_Free_Pkt(data_ptr); | |
331 | SMBlib_errno = SMBlibE_NoSpace; | |
332 | return(SMBlibE_BAD); | |
333 | ||
334 | } | |
335 | ||
336 | /* Put the recv pkt together */ | |
337 | ||
338 | recv_pkt -> next = data_ptr; | |
339 | ||
340 | /* Now build the read request and the receive packet etc ... */ | |
341 | ||
0ab648c9 | 342 | memset(SMB_Hdr(snd_pkt), 0, SMB_read_len); |
7c16470c AJ |
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); | |
351 | ||
352 | max_read_data = (File_Handle -> tree -> mbs) - recv_pkt_len; | |
353 | ||
354 | while (bytes_left > 0) { | |
355 | ||
356 | this_read = (bytes_left > max_read_data?max_read_data: bytes_left); | |
357 | ||
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); | |
362 | ||
363 | /* Now send the packet and wait for a response */ | |
364 | ||
365 | if (RFCNB_Send(File_Handle -> tree -> con -> Trans_Connect, snd_pkt, snd_pkt_len) < 0) { | |
366 | ||
367 | #ifdef DEBUG | |
368 | fprintf(stderr, "Error sending read request\n"); | |
369 | #endif | |
370 | ||
371 | data_ptr -> data = NULL; | |
372 | data_ptr -> len = 0; | |
373 | RFCNB_Free_Pkt(recv_pkt); | |
374 | RFCNB_Free_Pkt(snd_pkt); | |
375 | SMBlib_errno = SMBlibE_SendFailed; | |
376 | return(SMBlibE_BAD); | |
377 | ||
378 | } | |
379 | ||
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 */ | |
382 | ||
383 | data_ptr -> data = (data + bytes_read); | |
384 | data_ptr -> len = this_read; | |
385 | ||
386 | if (RFCNB_Recv(File_Handle -> tree -> con -> Trans_Connect, recv_pkt, recv_pkt_len + this_read) < 0) { | |
387 | ||
388 | #ifdef DEBUG | |
389 | fprintf(stderr, "Error receiving response to write\n"); | |
390 | #endif | |
391 | ||
392 | data_ptr -> len = 0; | |
393 | data_ptr -> data = NULL; | |
394 | RFCNB_Free_Pkt(recv_pkt); | |
395 | RFCNB_Free_Pkt(snd_pkt); | |
396 | SMBlib_errno = SMBlibE_RecvFailed; | |
397 | return(SMBlibE_BAD); | |
398 | ||
399 | } | |
400 | ||
401 | if (CVAL(SMB_Hdr(recv_pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
402 | ||
403 | #ifdef DEBUG | |
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)); | |
407 | #endif | |
408 | ||
409 | SMBlib_SMB_Error = IVAL(SMB_Hdr(recv_pkt), SMB_hdr_rcls_offset); | |
410 | data_ptr -> data = NULL; | |
411 | data_ptr -> len = 0; | |
412 | RFCNB_Free_Pkt(recv_pkt); | |
413 | RFCNB_Free_Pkt(snd_pkt); | |
414 | SMBlib_errno = SMBlibE_Remote; | |
415 | return(-1); | |
416 | ||
417 | } | |
418 | ||
419 | /* Ok, that worked, so update some things here ... */ | |
420 | ||
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); | |
423 | ||
424 | } | |
425 | ||
426 | /* Now free those packet headers that we allocated ... */ | |
427 | ||
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); | |
432 | ||
433 | return(bytes_read); | |
434 | ||
435 | } | |
436 | ||
437 | /* Lseek seeks just like the UNIX version does ... */ | |
438 | ||
439 | off_t SMB_Lseek(SMB_File *File_Handle, off_t offset, int whence) | |
440 | ||
441 | { | |
442 | ||
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 ... */ | |
445 | ||
446 | switch (whence) { | |
447 | case SEEK_SET: | |
448 | ||
449 | File_Handle -> fileloc = offset; | |
450 | break; | |
451 | ||
452 | case SEEK_CUR: | |
453 | ||
454 | File_Handle -> fileloc = File_Handle -> fileloc + offset; | |
455 | break; | |
456 | ||
457 | case SEEK_END: | |
458 | ||
459 | File_Handle -> fileloc = File_Handle -> size + offset; | |
460 | break; | |
461 | ||
462 | default: | |
463 | return(-1); | |
464 | ||
465 | } | |
466 | ||
467 | return(File_Handle -> fileloc); | |
468 | ||
469 | } | |
470 | ||
7c16470c AJ |
471 | /* Write numbytes from data to the file pointed to by the File_Handle at */ |
472 | /* the offset in the File_Handle. */ | |
473 | ||
474 | int SMB_Write(SMB_File *File_Handle, char *data, int numbytes) | |
475 | ||
476 | { | |
477 | int tot_written = 0; | |
478 | struct RFCNB_Pkt *pkt, *data_ptr; | |
479 | int pkt_len, i, this_write, max_write_data, bytes_left = numbytes; | |
480 | ||
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 ... */ | |
484 | ||
485 | data_ptr = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(0); | |
486 | if (data_ptr == NULL) { | |
487 | ||
488 | SMBlib_errno = SMBlibE_NoSpace; | |
489 | return(SMBlibE_BAD); | |
490 | ||
491 | } | |
492 | ||
493 | pkt_len = SMB_write_len + 3; /* + 3 for the datablockID and blklen */ | |
494 | ||
495 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
496 | ||
497 | if (pkt == NULL) { | |
498 | ||
499 | RFCNB_Free_Pkt(data_ptr); | |
500 | SMBlib_errno = SMBlibE_NoSpace; | |
501 | return(SMBlibE_BAD); | |
502 | ||
503 | } | |
504 | ||
505 | /* Now init the things that will be the same across the possibly multiple | |
506 | packets to write this data. */ | |
507 | ||
0ab648c9 | 508 | memset(SMB_Hdr(pkt), 0, SMB_write_len); |
7c16470c AJ |
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); | |
516 | ||
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 ... */ | |
520 | ||
521 | max_write_data = (File_Handle -> tree -> mbs) - pkt_len; | |
522 | ||
523 | /* the 3 is for the data block id and length that preceeds the data */ | |
524 | ||
525 | while (bytes_left > 0) { | |
526 | ||
527 | /* bytes to write? */ | |
528 | ||
529 | this_write = (bytes_left > max_write_data?max_write_data:bytes_left); | |
530 | ||
531 | data_ptr -> next = NULL; | |
532 | data_ptr -> len = this_write; | |
533 | data_ptr -> data = data + tot_written; | |
534 | ||
535 | pkt -> next = data_ptr; /* link the data on the end */ | |
536 | ||
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)); | |
544 | ||
545 | *(SMB_Hdr(pkt) + SMB_write_buf_offset) = SMBdatablockID; | |
546 | SSVAL(SMB_Hdr(pkt), SMB_write_buf_offset + 1, this_write); | |
547 | ||
548 | /* Now send the packet and wait for a response */ | |
549 | ||
550 | if (RFCNB_Send(File_Handle -> tree -> con -> Trans_Connect, pkt, pkt_len + this_write) < 0) { | |
551 | ||
552 | #ifdef DEBUG | |
553 | fprintf(stderr, "Error sending write request\n"); | |
554 | #endif | |
555 | ||
556 | data_ptr -> next = NULL; | |
557 | data_ptr -> len = 0; | |
558 | RFCNB_Free_Pkt(pkt); | |
559 | SMBlib_errno = -SMBlibE_SendFailed; | |
560 | return(-1); | |
561 | ||
562 | } | |
563 | ||
564 | /* Now get the response ... */ | |
565 | ||
566 | if (RFCNB_Recv(File_Handle -> tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
567 | ||
568 | #ifdef DEBUG | |
569 | fprintf(stderr, "Error receiving response to write\n"); | |
570 | #endif | |
571 | ||
572 | data_ptr -> next = NULL; | |
573 | data_ptr -> len = 0; | |
574 | RFCNB_Free_Pkt(pkt); | |
575 | SMBlib_errno = -SMBlibE_RecvFailed; | |
576 | return(-1); | |
577 | ||
578 | } | |
579 | ||
580 | if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
581 | ||
582 | #ifdef DEBUG | |
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)); | |
586 | #endif | |
587 | ||
588 | SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); | |
589 | data_ptr -> data = NULL; | |
590 | data_ptr -> len = 0; | |
591 | RFCNB_Free_Pkt(pkt); | |
592 | SMBlib_errno = SMBlibE_Remote; | |
593 | return(SMBlibE_BAD); | |
594 | ||
595 | } | |
596 | ||
597 | /* Ok, that worked, so update some things here ... */ | |
598 | ||
599 | tot_written = tot_written + this_write; | |
600 | bytes_left = bytes_left - this_write; | |
601 | ||
602 | /* Assume that it is ok to update this now, but what about only part */ | |
603 | /* of the write succeeding? */ | |
604 | ||
605 | File_Handle -> fileloc = File_Handle -> fileloc + this_write; | |
606 | ||
607 | #ifdef DEBUG | |
608 | fprintf(stderr, "--This_write = %i, bytes_left = %i\n", | |
609 | this_write, bytes_left); | |
610 | #endif | |
611 | ||
612 | } | |
613 | ||
614 | /* Let's get rid of those packet headers we are using ... */ | |
615 | ||
616 | data_ptr -> data = NULL; | |
617 | pkt -> next = NULL; | |
618 | ||
619 | RFCNB_Free_Pkt(pkt); | |
620 | ||
621 | return(tot_written); | |
622 | ||
623 | } | |
624 | ||
625 | /* Create file on the server with name file_name and attributes search */ | |
626 | ||
627 | SMB_File *SMB_Create(SMB_Tree_Handle Tree_Handle, | |
628 | SMB_File *File_Handle, | |
629 | char *file_name, | |
630 | WORD search) | |
631 | ||
632 | { | |
633 | struct RFCNB_Pkt *pkt; | |
634 | int pkt_len, param_len; | |
635 | char *p; | |
636 | struct SMB_File_Def *file_tmp; | |
637 | ||
638 | /* We allocate a file object and copy some things ... */ | |
639 | ||
640 | file_tmp = File_Handle; | |
641 | ||
642 | if (File_Handle == NULL) { | |
643 | ||
644 | if ((file_tmp = (SMB_File *)malloc(sizeof(SMB_File))) == NULL) { | |
645 | ||
646 | #ifdef DEBUG | |
647 | fprintf(stderr, "Could not allocate file handle space ..."); | |
648 | #endif | |
649 | ||
650 | SMBlib_errno = SMBlibE_NoSpace; | |
651 | return(NULL); | |
652 | ||
653 | } | |
654 | ||
655 | } | |
656 | ||
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? */ | |
660 | ||
661 | param_len = strlen(file_name) + 2; /* 1 for null, 1 for ASCII marker */ | |
662 | ||
663 | pkt_len = SMB_creat_len + param_len; | |
664 | ||
665 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
666 | ||
667 | if (pkt == NULL) { /* Really should do some error handling */ | |
668 | ||
669 | if (File_Handle == NULL) | |
670 | free(file_tmp); | |
671 | SMBlib_errno = SMBlibE_NoSpace; | |
672 | return(NULL); | |
673 | ||
674 | } | |
675 | ||
676 | /* Now plug in the bits we need */ | |
677 | ||
0ab648c9 | 678 | memset(SMB_Hdr(pkt), 0, SMB_creat_len); |
7c16470c AJ |
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; | |
686 | ||
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); | |
691 | ||
692 | /* Now plug in the file name ... */ | |
693 | ||
694 | p = (char *)(SMB_Hdr(pkt) + SMB_creat_buf_offset); | |
695 | *p = SMBasciiID; | |
696 | strcpy(p+1, file_name); | |
697 | p = p + strlen(file_name); | |
698 | *(p+1) = 0; /* plug in a null ... */ | |
699 | ||
700 | /* Now send the packet and get the response ... */ | |
701 | ||
702 | if (RFCNB_Send(Tree_Handle -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
703 | ||
704 | #ifdef DEBUG | |
705 | fprintf(stderr, "Error sending Open request\n"); | |
706 | #endif | |
707 | ||
708 | if (File_Handle == NULL) | |
709 | free(file_tmp); | |
710 | RFCNB_Free_Pkt(pkt); | |
711 | SMBlib_errno = -SMBlibE_SendFailed; | |
712 | return(NULL); | |
713 | ||
714 | } | |
715 | ||
716 | /* Now get the response ... */ | |
717 | ||
718 | #ifdef DEBUG | |
719 | fprintf(stderr, "Pkt_Len for Create resp = %i\n", pkt_len); | |
720 | #endif | |
721 | ||
722 | if (RFCNB_Recv(Tree_Handle -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
723 | ||
724 | #ifdef DEBUG | |
725 | fprintf(stderr, "Error receiving response to create request\n"); | |
726 | #endif | |
727 | ||
728 | if (File_Handle == NULL) | |
729 | free(file_tmp); | |
730 | RFCNB_Free_Pkt(pkt); | |
731 | SMBlib_errno = -SMBlibE_RecvFailed; | |
732 | return(NULL); | |
733 | ||
734 | } | |
735 | ||
736 | /* Now parse the response and pass back any error ... */ | |
737 | ||
738 | if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
739 | ||
740 | #ifdef DEBUG | |
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)); | |
744 | #endif | |
745 | ||
746 | if (File_Handle == NULL) | |
747 | free(file_tmp); | |
748 | SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); | |
749 | RFCNB_Free_Pkt(pkt); | |
750 | SMBlib_errno = SMBlibE_Remote; | |
751 | return(NULL); /* Should clean up ... */ | |
752 | ||
753 | } | |
754 | ||
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; | |
760 | ||
761 | RFCNB_Free_Pkt(pkt); /* Free up this space */ | |
762 | ||
763 | #ifdef DEBUG | |
764 | fprintf(stderr, "SMB_Create succeeded, FID = %i\n", file_tmp -> fid); | |
765 | #endif | |
766 | ||
767 | return(file_tmp); | |
768 | ||
769 | } | |
770 | ||
771 | /* Delete the file passed in as file_name. */ | |
772 | ||
773 | int SMB_Delete(SMB_Tree_Handle tree, char *file_name, WORD search) | |
774 | ||
775 | { | |
776 | struct RFCNB_Pkt *pkt; | |
777 | int pkt_len, param_len; | |
778 | char *p; | |
779 | ||
780 | param_len = strlen(file_name) + 2; | |
781 | pkt_len = SMB_delet_len + param_len; | |
782 | ||
783 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
784 | ||
785 | if (pkt == NULL) { /* Really should do some error handling */ | |
786 | ||
787 | SMBlib_errno = SMBlibE_NoSpace; | |
788 | return(SMBlibE_BAD); | |
789 | ||
790 | } | |
791 | ||
792 | /* Now plug in the bits we need */ | |
793 | ||
0ab648c9 | 794 | memset(SMB_Hdr(pkt), 0, SMB_delet_len); |
7c16470c AJ |
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; | |
802 | ||
803 | SIVAL(SMB_Hdr(pkt), SMB_delet_sat_offset, search); | |
804 | SSVAL(SMB_Hdr(pkt), SMB_delet_bcc_offset, param_len); | |
805 | ||
806 | /* Now plug in the file name ... */ | |
807 | ||
808 | p = (char *)(SMB_Hdr(pkt) + SMB_delet_buf_offset); | |
809 | *p = SMBasciiID; | |
810 | strcpy(p+1, file_name); | |
811 | p = p + strlen(file_name); | |
812 | *(p+1) = 0; /* plug in a null ... */ | |
813 | ||
814 | /* Now send the packet and get the response ... */ | |
815 | ||
816 | if (RFCNB_Send(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
817 | ||
818 | #ifdef DEBUG | |
819 | fprintf(stderr, "Error sending Delete request\n"); | |
820 | #endif | |
821 | ||
822 | RFCNB_Free_Pkt(pkt); | |
823 | SMBlib_errno = -SMBlibE_SendFailed; | |
824 | return(SMBlibE_BAD); | |
825 | ||
826 | } | |
827 | ||
828 | /* Now get the response ... */ | |
829 | ||
830 | if (RFCNB_Recv(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
831 | ||
832 | #ifdef DEBUG | |
833 | fprintf(stderr, "Error receiving response to delete request\n"); | |
834 | #endif | |
835 | ||
836 | RFCNB_Free_Pkt(pkt); | |
837 | SMBlib_errno = -SMBlibE_RecvFailed; | |
838 | return(SMBlibE_BAD); | |
839 | ||
840 | } | |
841 | ||
842 | /* Now parse the response and pass back any error ... */ | |
843 | ||
844 | if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
845 | ||
846 | #ifdef DEBUG | |
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)); | |
850 | #endif | |
851 | ||
852 | SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); | |
853 | RFCNB_Free_Pkt(pkt); | |
854 | SMBlib_errno = SMBlibE_Remote; | |
855 | return(SMBlibE_BAD); /* Should clean up ... */ | |
856 | ||
857 | } | |
858 | ||
859 | #ifdef DEBUG | |
860 | fprintf(stderr, "File %s deleted successfully.\n", file_name); | |
861 | #endif DEBUG | |
862 | ||
863 | RFCNB_Free_Pkt(pkt); | |
864 | ||
865 | return(0); | |
866 | } | |
867 | ||
868 | /* Create the directory passed in as dir_name */ | |
869 | ||
870 | int SMB_Create_Dir(SMB_Tree_Handle tree, char *dir_name) | |
871 | ||
872 | { | |
873 | struct RFCNB_Pkt *pkt; | |
874 | int pkt_len, param_len; | |
875 | char *p; | |
876 | ||
877 | param_len = strlen(dir_name) + 2; /* + null and + asciiID */ | |
878 | pkt_len = SMB_creatdir_len + param_len; | |
879 | ||
880 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
881 | ||
882 | if (pkt == NULL) { /* Really should do some error handling */ | |
883 | ||
884 | SMBlib_errno = SMBlibE_NoSpace; | |
885 | return(SMBlibE_BAD); | |
886 | ||
887 | } | |
888 | ||
889 | /* Now plug in the bits we need */ | |
890 | ||
0ab648c9 | 891 | memset(SMB_Hdr(pkt), 0, SMB_creatdir_len); |
7c16470c AJ |
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; | |
899 | ||
900 | SSVAL(SMB_Hdr(pkt), SMB_creatdir_bcc_offset, param_len); | |
901 | ||
902 | /* Now plug in the file name ... */ | |
903 | ||
904 | p = (char *)(SMB_Hdr(pkt) + SMB_creatdir_buf_offset); | |
905 | *p = SMBasciiID; | |
906 | strcpy(p+1, dir_name); | |
907 | p = p + strlen(dir_name); | |
908 | *(p+1) = 0; /* plug in a null ... */ | |
909 | ||
910 | /* Now send the packet and get the response ... */ | |
911 | ||
912 | if (RFCNB_Send(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
913 | ||
914 | #ifdef DEBUG | |
915 | fprintf(stderr, "Error sending Create Dir request\n"); | |
916 | #endif | |
917 | ||
918 | RFCNB_Free_Pkt(pkt); | |
919 | SMBlib_errno = -SMBlibE_SendFailed; | |
920 | return(SMBlibE_BAD); | |
921 | ||
922 | } | |
923 | ||
924 | /* Now get the response ... */ | |
925 | ||
926 | if (RFCNB_Recv(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
927 | ||
928 | #ifdef DEBUG | |
929 | fprintf(stderr, "Error receiving response to Create Dir request\n"); | |
930 | #endif | |
931 | ||
932 | RFCNB_Free_Pkt(pkt); | |
933 | SMBlib_errno = -SMBlibE_RecvFailed; | |
934 | return(SMBlibE_BAD); | |
935 | ||
936 | } | |
937 | ||
938 | /* Now parse the response and pass back any error ... */ | |
939 | ||
940 | if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
941 | ||
942 | #ifdef DEBUG | |
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)); | |
946 | #endif | |
947 | ||
948 | SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); | |
949 | RFCNB_Free_Pkt(pkt); | |
950 | SMBlib_errno = SMBlibE_Remote; | |
951 | return(SMBlibE_BAD); /* Should clean up ... */ | |
952 | ||
953 | } | |
954 | ||
955 | #ifdef DEBUG | |
956 | fprintf(stderr, "Directory %s created successfully.\n", dir_name); | |
957 | #endif DEBUG | |
958 | ||
959 | RFCNB_Free_Pkt(pkt); | |
960 | ||
961 | return(0); | |
962 | } | |
963 | ||
964 | /* Delete the directory passed as dir_name, as long as it is empty ... */ | |
965 | ||
966 | int SMB_Delete_Dir(SMB_Tree_Handle tree, char *dir_name) | |
967 | ||
968 | { | |
969 | struct RFCNB_Pkt *pkt; | |
970 | int pkt_len, param_len; | |
971 | char *p; | |
972 | ||
973 | param_len = strlen(dir_name) + 2; /* + null and + asciiID */ | |
974 | pkt_len = SMB_deletdir_len + param_len; | |
975 | ||
976 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
977 | ||
978 | if (pkt == NULL) { /* Really should do some error handling */ | |
979 | ||
980 | SMBlib_errno = SMBlibE_NoSpace; | |
981 | return(SMBlibE_BAD); | |
982 | ||
983 | } | |
984 | ||
985 | /* Now plug in the bits we need */ | |
986 | ||
0ab648c9 | 987 | memset(SMB_Hdr(pkt), 0, SMB_deletdir_len); |
7c16470c AJ |
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; | |
995 | ||
996 | SSVAL(SMB_Hdr(pkt), SMB_deletdir_bcc_offset, param_len); | |
997 | ||
998 | /* Now plug in the file name ... */ | |
999 | ||
1000 | p = (char *)(SMB_Hdr(pkt) + SMB_deletdir_buf_offset); | |
1001 | *p = SMBasciiID; | |
1002 | strcpy(p+1, dir_name); | |
1003 | p = p + strlen(dir_name); | |
1004 | *(p+1) = 0; /* plug in a null ... */ | |
1005 | ||
1006 | /* Now send the packet and get the response ... */ | |
1007 | ||
1008 | if (RFCNB_Send(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
1009 | ||
1010 | #ifdef DEBUG | |
1011 | fprintf(stderr, "Error sending Delete Dir request\n"); | |
1012 | #endif | |
1013 | ||
1014 | RFCNB_Free_Pkt(pkt); | |
1015 | SMBlib_errno = -SMBlibE_SendFailed; | |
1016 | return(SMBlibE_BAD); | |
1017 | ||
1018 | } | |
1019 | ||
1020 | /* Now get the response ... */ | |
1021 | ||
1022 | if (RFCNB_Recv(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
1023 | ||
1024 | #ifdef DEBUG | |
1025 | fprintf(stderr, "Error receiving response to Delete Dir request\n"); | |
1026 | #endif | |
1027 | ||
1028 | RFCNB_Free_Pkt(pkt); | |
1029 | SMBlib_errno = -SMBlibE_RecvFailed; | |
1030 | return(SMBlibE_BAD); | |
1031 | ||
1032 | } | |
1033 | ||
1034 | /* Now parse the response and pass back any error ... */ | |
1035 | ||
1036 | if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
1037 | ||
1038 | #ifdef DEBUG | |
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)); | |
1042 | #endif | |
1043 | ||
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 ... */ | |
1048 | ||
1049 | } | |
1050 | ||
1051 | #ifdef DEBUG | |
1052 | fprintf(stderr, "Directory %s deleted successfully.\n", dir_name); | |
1053 | #endif DEBUG | |
1054 | ||
1055 | RFCNB_Free_Pkt(pkt); | |
1056 | ||
1057 | return(0); | |
1058 | } | |
1059 | ||
1060 | /* Check for the existence of the directory in dir_name */ | |
1061 | ||
1062 | int SMB_Check_Dir(SMB_Tree_Handle tree, char *dir_name) | |
1063 | ||
1064 | { | |
1065 | struct RFCNB_Pkt *pkt; | |
1066 | int pkt_len, param_len; | |
1067 | char *p; | |
1068 | ||
1069 | param_len = strlen(dir_name) + 2; /* + null and + asciiID */ | |
1070 | pkt_len = SMB_checkdir_len + param_len; | |
1071 | ||
1072 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
1073 | ||
1074 | if (pkt == NULL) { /* Really should do some error handling */ | |
1075 | ||
1076 | SMBlib_errno = SMBlibE_NoSpace; | |
1077 | return(SMBlibE_BAD); | |
1078 | ||
1079 | } | |
1080 | ||
1081 | /* Now plug in the bits we need */ | |
1082 | ||
0ab648c9 | 1083 | memset(SMB_Hdr(pkt), 0, SMB_checkdir_len); |
7c16470c AJ |
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; | |
1091 | ||
1092 | SSVAL(SMB_Hdr(pkt), SMB_checkdir_bcc_offset, param_len); | |
1093 | ||
1094 | /* Now plug in the file name ... */ | |
1095 | ||
1096 | p = (char *)(SMB_Hdr(pkt) + SMB_checkdir_buf_offset); | |
1097 | *p = SMBasciiID; | |
1098 | strcpy(p+1, dir_name); | |
1099 | p = p + strlen(dir_name); | |
1100 | *(p+1) = 0; /* plug in a null ... */ | |
1101 | ||
1102 | /* Now send the packet and get the response ... */ | |
1103 | ||
1104 | if (RFCNB_Send(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
1105 | ||
1106 | #ifdef DEBUG | |
1107 | fprintf(stderr, "Error sending Check Dir Path request\n"); | |
1108 | #endif | |
1109 | ||
1110 | RFCNB_Free_Pkt(pkt); | |
1111 | SMBlib_errno = -SMBlibE_SendFailed; | |
1112 | return(SMBlibE_BAD); | |
1113 | ||
1114 | } | |
1115 | ||
1116 | /* Now get the response ... */ | |
1117 | ||
1118 | if (RFCNB_Recv(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
1119 | ||
1120 | #ifdef DEBUG | |
1121 | fprintf(stderr, "Error receiving response to Check Dir request\n"); | |
1122 | #endif | |
1123 | ||
1124 | RFCNB_Free_Pkt(pkt); | |
1125 | SMBlib_errno = -SMBlibE_RecvFailed; | |
1126 | return(SMBlibE_BAD); | |
1127 | ||
1128 | } | |
1129 | ||
1130 | /* Now parse the response and pass back any error ... */ | |
1131 | ||
1132 | if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
1133 | ||
1134 | #ifdef DEBUG | |
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)); | |
1138 | #endif | |
1139 | ||
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 ... */ | |
1144 | ||
1145 | } | |
1146 | ||
1147 | #ifdef DEBUG | |
1148 | fprintf(stderr, "Directory %s checked successfully.\n", dir_name); | |
1149 | #endif DEBUG | |
1150 | ||
1151 | RFCNB_Free_Pkt(pkt); | |
1152 | ||
1153 | return(0); | |
1154 | } | |
1155 | ||
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. */ | |
1158 | ||
1159 | int SMB_Search(SMB_Tree_Handle tree, | |
1160 | char *dir_name, | |
1161 | WORD search, | |
1162 | SMB_CP_dirent *dirents, | |
1163 | int direntc, | |
1164 | char *resumekey, | |
1165 | int resumekey_len) | |
1166 | ||
1167 | { | |
1168 | struct RFCNB_Pkt *pkt, *recv_pkt; | |
1169 | int pkt_len, param_len, recv_param_len, recv_pkt_len, ret_count, i; | |
1170 | char *p; | |
1171 | ||
1172 | param_len = strlen(dir_name) + 2 + resumekey_len + 3; /* You have to know */ | |
1173 | pkt_len = SMB_search_len + param_len; | |
1174 | ||
1175 | recv_param_len = direntc * SMB_searchr_dirent_len + 3; | |
1176 | recv_pkt_len = SMB_searchr_len + recv_param_len; | |
1177 | ||
1178 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
1179 | ||
1180 | if (pkt == NULL) { /* Really should do some error handling */ | |
1181 | ||
1182 | SMBlib_errno = SMBlibE_NoSpace; | |
1183 | return(SMBlibE_BAD); | |
1184 | ||
1185 | } | |
1186 | ||
1187 | recv_pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(recv_pkt_len); | |
1188 | ||
1189 | if (recv_pkt == NULL) { /* Really should do some error handling */ | |
1190 | ||
1191 | RFCNB_Free_Pkt(pkt); | |
1192 | SMBlib_errno = SMBlibE_NoSpace; | |
1193 | return(SMBlibE_BAD); | |
1194 | ||
1195 | } | |
1196 | ||
7c16470c AJ |
1197 | /* Now plug in the bits we need */ |
1198 | ||
0ab648c9 | 1199 | memset(SMB_Hdr(pkt), 0, SMB_search_len); |
7c16470c AJ |
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); | |
1206 | ||
1207 | /* Tell server we known about non-dos names and extended attibutes */ | |
1208 | ||
1209 | SSVAL(SMB_Hdr(pkt), SMB_hdr_flg2_offset, | |
1210 | (SMB_FLG2_NON_DOS | SMB_FLG2_EXT_ATR)); | |
1211 | ||
1212 | *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 2; | |
1213 | ||
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); | |
1217 | ||
1218 | /* Now plug in the file name ... */ | |
1219 | ||
1220 | p = (char *)(SMB_Hdr(pkt) + SMB_search_buf_offset); | |
1221 | *p = SMBasciiID; | |
1222 | strcpy(p+1, dir_name); | |
1223 | p = p + strlen(dir_name) + 2; /* Skip the null */ | |
1224 | ||
7c16470c AJ |
1225 | *p = SMBvariableblockID; |
1226 | p = p + 1; | |
1227 | ||
1228 | /* And now the resume key */ | |
1229 | ||
1230 | SSVAL(p, 0, resumekey_len); | |
1231 | ||
1232 | p = p + 2; | |
1233 | ||
1234 | bcopy(resumekey, p, resumekey_len); | |
1235 | ||
1236 | /* Now send the packet and get the response ... */ | |
1237 | ||
1238 | if (RFCNB_Send(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) { | |
1239 | ||
1240 | #ifdef DEBUG | |
1241 | fprintf(stderr, "Error sending search request\n"); | |
1242 | #endif | |
1243 | ||
1244 | RFCNB_Free_Pkt(pkt); | |
1245 | RFCNB_Free_Pkt(recv_pkt); | |
1246 | SMBlib_errno = -SMBlibE_SendFailed; | |
1247 | return(SMBlibE_BAD); | |
1248 | ||
1249 | } | |
1250 | ||
1251 | /* Now get the response ... */ | |
1252 | ||
1253 | if (RFCNB_Recv(tree -> con -> Trans_Connect, recv_pkt, recv_pkt_len) < 0) { | |
1254 | ||
1255 | #ifdef DEBUG | |
1256 | fprintf(stderr, "Error receiving response to Check Dir request\n"); | |
1257 | #endif | |
1258 | ||
1259 | RFCNB_Free_Pkt(pkt); | |
1260 | RFCNB_Free_Pkt(recv_pkt); | |
1261 | SMBlib_errno = -SMBlibE_RecvFailed; | |
1262 | return(SMBlibE_BAD); | |
1263 | ||
1264 | } | |
1265 | ||
1266 | /* Now parse the response and pass back any error ... */ | |
1267 | ||
1268 | if (CVAL(SMB_Hdr(recv_pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
1269 | ||
1270 | #ifdef DEBUG | |
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)); | |
1274 | #endif | |
1275 | ||
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 ... */ | |
1281 | ||
1282 | } | |
1283 | ||
1284 | /* Now copy the results into the user's structure */ | |
1285 | ||
1286 | ret_count = SVAL(SMB_Hdr(recv_pkt), SMB_searchr_dec_offset); | |
1287 | ||
1288 | p = SMB_Hdr(recv_pkt) + SMB_searchr_buf_offset + 3; | |
1289 | ||
1290 | /* Hmmm, should check that we have the right number of bytes ... */ | |
1291 | ||
1292 | for (i = 0; i < ret_count; i++) { | |
1293 | ||
1294 | bcopy(p, dirents[i].resume_key, 21); | |
1295 | ||
1296 | p = p + 21; | |
1297 | ||
1298 | dirents[i].file_attributes = (unsigned char)*p; | |
1299 | ||
1300 | p = p + 1; | |
1301 | ||
1302 | dirents[i].date_time = IVAL(p, 0); /* Should this be IVAL? */ | |
1303 | ||
1304 | p = p + 4; | |
1305 | ||
1306 | dirents[i].size = IVAL(p, 0); | |
1307 | ||
1308 | p = p + 4; | |
1309 | ||
1310 | bcopy(p, dirents[i].filename, 13); /* Copy in file name */ | |
1311 | ||
1312 | p = p + 13; | |
1313 | ||
1314 | } | |
1315 | ||
1316 | return(ret_count); | |
1317 | ||
1318 | } |