source: trunk/samba/source/libsmb/clifile.c@ 77

Last change on this file since 77 was 77, checked in by Paul Smedley, 18 years ago

Update trunk to 3.2.0pre1

File size: 51.6 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 client file operations
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2001-2002
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "includes.h"
22
23/****************************************************************************
24 Hard/Symlink a file (UNIX extensions).
25 Creates new name (sym)linked to oldname.
26****************************************************************************/
27
28static BOOL cli_link_internal(struct cli_state *cli, const char *oldname, const char *newname, BOOL hard_link)
29{
30 unsigned int data_len = 0;
31 unsigned int param_len = 0;
32 uint16 setup = TRANSACT2_SETPATHINFO;
33 char param[sizeof(pstring)+6];
34 pstring data;
35 char *rparam=NULL, *rdata=NULL;
36 char *p;
37 size_t oldlen = 2*(strlen(oldname)+1);
38 size_t newlen = 2*(strlen(newname)+1);
39
40 memset(param, 0, sizeof(param));
41 SSVAL(param,0,hard_link ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
42 p = &param[6];
43
44 p += clistr_push(cli, p, newname, MIN(newlen, sizeof(param)-6), STR_TERMINATE);
45 param_len = PTR_DIFF(p, param);
46
47 p = data;
48 p += clistr_push(cli, p, oldname, MIN(oldlen,sizeof(data)), STR_TERMINATE);
49 data_len = PTR_DIFF(p, data);
50
51 if (!cli_send_trans(cli, SMBtrans2,
52 NULL, /* name */
53 -1, 0, /* fid, flags */
54 &setup, 1, 0, /* setup, length, max */
55 param, param_len, 2, /* param, length, max */
56 (char *)&data, data_len, cli->max_xmit /* data, length, max */
57 )) {
58 return False;
59 }
60
61 if (!cli_receive_trans(cli, SMBtrans2,
62 &rparam, &param_len,
63 &rdata, &data_len)) {
64 return False;
65 }
66
67 SAFE_FREE(rdata);
68 SAFE_FREE(rparam);
69
70 return True;
71}
72
73/****************************************************************************
74 Map standard UNIX permissions onto wire representations.
75****************************************************************************/
76
77uint32 unix_perms_to_wire(mode_t perms)
78{
79 unsigned int ret = 0;
80
81 ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0);
82 ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0);
83 ret |= ((perms & S_IROTH) ? UNIX_R_OTH : 0);
84 ret |= ((perms & S_IXGRP) ? UNIX_X_GRP : 0);
85 ret |= ((perms & S_IWGRP) ? UNIX_W_GRP : 0);
86 ret |= ((perms & S_IRGRP) ? UNIX_R_GRP : 0);
87 ret |= ((perms & S_IXUSR) ? UNIX_X_USR : 0);
88 ret |= ((perms & S_IWUSR) ? UNIX_W_USR : 0);
89 ret |= ((perms & S_IRUSR) ? UNIX_R_USR : 0);
90#ifdef S_ISVTX
91 ret |= ((perms & S_ISVTX) ? UNIX_STICKY : 0);
92#endif
93#ifdef S_ISGID
94 ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0);
95#endif
96#ifdef S_ISUID
97 ret |= ((perms & S_ISUID) ? UNIX_SET_UID : 0);
98#endif
99 return ret;
100}
101
102/****************************************************************************
103 Map wire permissions to standard UNIX.
104****************************************************************************/
105
106mode_t wire_perms_to_unix(uint32 perms)
107{
108 mode_t ret = (mode_t)0;
109
110 ret |= ((perms & UNIX_X_OTH) ? S_IXOTH : 0);
111 ret |= ((perms & UNIX_W_OTH) ? S_IWOTH : 0);
112 ret |= ((perms & UNIX_R_OTH) ? S_IROTH : 0);
113 ret |= ((perms & UNIX_X_GRP) ? S_IXGRP : 0);
114 ret |= ((perms & UNIX_W_GRP) ? S_IWGRP : 0);
115 ret |= ((perms & UNIX_R_GRP) ? S_IRGRP : 0);
116 ret |= ((perms & UNIX_X_USR) ? S_IXUSR : 0);
117 ret |= ((perms & UNIX_W_USR) ? S_IWUSR : 0);
118 ret |= ((perms & UNIX_R_USR) ? S_IRUSR : 0);
119#ifdef S_ISVTX
120 ret |= ((perms & UNIX_STICKY) ? S_ISVTX : 0);
121#endif
122#ifdef S_ISGID
123 ret |= ((perms & UNIX_SET_GID) ? S_ISGID : 0);
124#endif
125#ifdef S_ISUID
126 ret |= ((perms & UNIX_SET_UID) ? S_ISUID : 0);
127#endif
128 return ret;
129}
130
131/****************************************************************************
132 Return the file type from the wire filetype for UNIX extensions.
133****************************************************************************/
134
135static mode_t unix_filetype_from_wire(uint32 wire_type)
136{
137 switch (wire_type) {
138 case UNIX_TYPE_FILE:
139 return S_IFREG;
140 case UNIX_TYPE_DIR:
141 return S_IFDIR;
142#ifdef S_IFLNK
143 case UNIX_TYPE_SYMLINK:
144 return S_IFLNK;
145#endif
146#ifdef S_IFCHR
147 case UNIX_TYPE_CHARDEV:
148 return S_IFCHR;
149#endif
150#ifdef S_IFBLK
151 case UNIX_TYPE_BLKDEV:
152 return S_IFBLK;
153#endif
154#ifdef S_IFIFO
155 case UNIX_TYPE_FIFO:
156 return S_IFIFO;
157#endif
158#ifdef S_IFSOCK
159 case UNIX_TYPE_SOCKET:
160 return S_IFSOCK;
161#endif
162 default:
163 return (mode_t)0;
164 }
165}
166
167/****************************************************************************
168 Do a POSIX getfacl (UNIX extensions).
169****************************************************************************/
170
171BOOL cli_unix_getfacl(struct cli_state *cli, const char *name, size_t *prb_size, char **retbuf)
172{
173 unsigned int param_len = 0;
174 unsigned int data_len = 0;
175 uint16 setup = TRANSACT2_QPATHINFO;
176 char param[sizeof(pstring)+6];
177 char *rparam=NULL, *rdata=NULL;
178 char *p;
179
180 p = param;
181 memset(p, 0, 6);
182 SSVAL(p, 0, SMB_QUERY_POSIX_ACL);
183 p += 6;
184 p += clistr_push(cli, p, name, sizeof(pstring)-6, STR_TERMINATE);
185 param_len = PTR_DIFF(p, param);
186
187 if (!cli_send_trans(cli, SMBtrans2,
188 NULL, /* name */
189 -1, 0, /* fid, flags */
190 &setup, 1, 0, /* setup, length, max */
191 param, param_len, 2, /* param, length, max */
192 NULL, 0, cli->max_xmit /* data, length, max */
193 )) {
194 return False;
195 }
196
197 if (!cli_receive_trans(cli, SMBtrans2,
198 &rparam, &param_len,
199 &rdata, &data_len)) {
200 return False;
201 }
202
203 if (data_len < 6) {
204 SAFE_FREE(rdata);
205 SAFE_FREE(rparam);
206 return False;
207 }
208
209 SAFE_FREE(rparam);
210 *retbuf = rdata;
211 *prb_size = (size_t)data_len;
212
213 return True;
214}
215
216/****************************************************************************
217 Stat a file (UNIX extensions).
218****************************************************************************/
219
220BOOL cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf)
221{
222 unsigned int param_len = 0;
223 unsigned int data_len = 0;
224 uint16 setup = TRANSACT2_QPATHINFO;
225 char param[sizeof(pstring)+6];
226 char *rparam=NULL, *rdata=NULL;
227 char *p;
228
229 ZERO_STRUCTP(sbuf);
230
231 p = param;
232 memset(p, 0, 6);
233 SSVAL(p, 0, SMB_QUERY_FILE_UNIX_BASIC);
234 p += 6;
235 p += clistr_push(cli, p, name, sizeof(pstring)-6, STR_TERMINATE);
236 param_len = PTR_DIFF(p, param);
237
238 if (!cli_send_trans(cli, SMBtrans2,
239 NULL, /* name */
240 -1, 0, /* fid, flags */
241 &setup, 1, 0, /* setup, length, max */
242 param, param_len, 2, /* param, length, max */
243 NULL, 0, cli->max_xmit /* data, length, max */
244 )) {
245 return False;
246 }
247
248 if (!cli_receive_trans(cli, SMBtrans2,
249 &rparam, &param_len,
250 &rdata, &data_len)) {
251 return False;
252 }
253
254 if (data_len < 96) {
255 SAFE_FREE(rdata);
256 SAFE_FREE(rparam);
257 return False;
258 }
259
260 sbuf->st_size = IVAL2_TO_SMB_BIG_UINT(rdata,0); /* total size, in bytes */
261 sbuf->st_blocks = IVAL2_TO_SMB_BIG_UINT(rdata,8); /* number of blocks allocated */
262#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
263 sbuf->st_blocks /= STAT_ST_BLOCKSIZE;
264#else
265 /* assume 512 byte blocks */
266 sbuf->st_blocks /= 512;
267#endif
268 set_ctimespec(sbuf, interpret_long_date(rdata + 16)); /* time of last change */
269 set_atimespec(sbuf, interpret_long_date(rdata + 24)); /* time of last access */
270 set_mtimespec(sbuf, interpret_long_date(rdata + 32)); /* time of last modification */
271
272 sbuf->st_uid = (uid_t) IVAL(rdata,40); /* user ID of owner */
273 sbuf->st_gid = (gid_t) IVAL(rdata,48); /* group ID of owner */
274 sbuf->st_mode |= unix_filetype_from_wire(IVAL(rdata, 56));
275#if defined(HAVE_MAKEDEV)
276 {
277 uint32 dev_major = IVAL(rdata,60);
278 uint32 dev_minor = IVAL(rdata,68);
279 sbuf->st_rdev = makedev(dev_major, dev_minor);
280 }
281#endif
282 sbuf->st_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(rdata,76); /* inode */
283 sbuf->st_mode |= wire_perms_to_unix(IVAL(rdata,84)); /* protection */
284 sbuf->st_nlink = IVAL(rdata,92); /* number of hard links */
285
286 SAFE_FREE(rdata);
287 SAFE_FREE(rparam);
288
289 return True;
290}
291
292/****************************************************************************
293 Symlink a file (UNIX extensions).
294****************************************************************************/
295
296BOOL cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *newname)
297{
298 return cli_link_internal(cli, oldname, newname, False);
299}
300
301/****************************************************************************
302 Hard a file (UNIX extensions).
303****************************************************************************/
304
305BOOL cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *newname)
306{
307 return cli_link_internal(cli, oldname, newname, True);
308}
309
310/****************************************************************************
311 Chmod or chown a file internal (UNIX extensions).
312****************************************************************************/
313
314static BOOL cli_unix_chmod_chown_internal(struct cli_state *cli, const char *fname, uint32 mode, uint32 uid, uint32 gid)
315{
316 unsigned int data_len = 0;
317 unsigned int param_len = 0;
318 uint16 setup = TRANSACT2_SETPATHINFO;
319 char param[sizeof(pstring)+6];
320 char data[100];
321 char *rparam=NULL, *rdata=NULL;
322 char *p;
323
324 memset(param, 0, sizeof(param));
325 memset(data, 0, sizeof(data));
326 SSVAL(param,0,SMB_SET_FILE_UNIX_BASIC);
327 p = &param[6];
328
329 p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
330 param_len = PTR_DIFF(p, param);
331
332 memset(data, 0xff, 40); /* Set all sizes/times to no change. */
333
334 SIVAL(data,40,uid);
335 SIVAL(data,48,gid);
336 SIVAL(data,84,mode);
337
338 data_len = 100;
339
340 if (!cli_send_trans(cli, SMBtrans2,
341 NULL, /* name */
342 -1, 0, /* fid, flags */
343 &setup, 1, 0, /* setup, length, max */
344 param, param_len, 2, /* param, length, max */
345 (char *)&data, data_len, cli->max_xmit /* data, length, max */
346 )) {
347 return False;
348 }
349
350 if (!cli_receive_trans(cli, SMBtrans2,
351 &rparam, &param_len,
352 &rdata, &data_len)) {
353 return False;
354 }
355
356 SAFE_FREE(rdata);
357 SAFE_FREE(rparam);
358
359 return True;
360}
361
362/****************************************************************************
363 chmod a file (UNIX extensions).
364****************************************************************************/
365
366BOOL cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
367{
368 return cli_unix_chmod_chown_internal(cli, fname,
369 unix_perms_to_wire(mode), SMB_UID_NO_CHANGE, SMB_GID_NO_CHANGE);
370}
371
372/****************************************************************************
373 chown a file (UNIX extensions).
374****************************************************************************/
375
376BOOL cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid)
377{
378 return cli_unix_chmod_chown_internal(cli, fname, SMB_MODE_NO_CHANGE, (uint32)uid, (uint32)gid);
379}
380
381/****************************************************************************
382 Rename a file.
383****************************************************************************/
384
385BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
386{
387 char *p;
388
389 memset(cli->outbuf,'\0',smb_size);
390 memset(cli->inbuf,'\0',smb_size);
391
392 set_message(cli->outbuf,1, 0, True);
393
394 SCVAL(cli->outbuf,smb_com,SMBmv);
395 SSVAL(cli->outbuf,smb_tid,cli->cnum);
396 cli_setup_packet(cli);
397
398 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
399
400 p = smb_buf(cli->outbuf);
401 *p++ = 4;
402 p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
403 *p++ = 4;
404 p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
405
406 cli_setup_bcc(cli, p);
407
408 cli_send_smb(cli);
409 if (!cli_receive_smb(cli))
410 return False;
411
412 if (cli_is_error(cli))
413 return False;
414
415 return True;
416}
417
418/****************************************************************************
419 NT Rename a file.
420****************************************************************************/
421
422BOOL cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
423{
424 char *p;
425
426 memset(cli->outbuf,'\0',smb_size);
427 memset(cli->inbuf,'\0',smb_size);
428
429 set_message(cli->outbuf, 4, 0, True);
430
431 SCVAL(cli->outbuf,smb_com,SMBntrename);
432 SSVAL(cli->outbuf,smb_tid,cli->cnum);
433 cli_setup_packet(cli);
434
435 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
436 SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_RENAME);
437
438 p = smb_buf(cli->outbuf);
439 *p++ = 4;
440 p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
441 *p++ = 4;
442 p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
443
444 cli_setup_bcc(cli, p);
445
446 cli_send_smb(cli);
447 if (!cli_receive_smb(cli))
448 return False;
449
450 if (cli_is_error(cli))
451 return False;
452
453 return True;
454}
455
456/****************************************************************************
457 NT hardlink a file.
458****************************************************************************/
459
460BOOL cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
461{
462 char *p;
463
464 memset(cli->outbuf,'\0',smb_size);
465 memset(cli->inbuf,'\0',smb_size);
466
467 set_message(cli->outbuf, 4, 0, True);
468
469 SCVAL(cli->outbuf,smb_com,SMBntrename);
470 SSVAL(cli->outbuf,smb_tid,cli->cnum);
471 cli_setup_packet(cli);
472
473 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
474 SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_HARD_LINK);
475
476 p = smb_buf(cli->outbuf);
477 *p++ = 4;
478 p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
479 *p++ = 4;
480 p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
481
482 cli_setup_bcc(cli, p);
483
484 cli_send_smb(cli);
485 if (!cli_receive_smb(cli))
486 return False;
487
488 if (cli_is_error(cli))
489 return False;
490
491 return True;
492}
493
494/****************************************************************************
495 Delete a file.
496****************************************************************************/
497
498BOOL cli_unlink_full(struct cli_state *cli, const char *fname, uint16 attrs)
499{
500 char *p;
501
502 memset(cli->outbuf,'\0',smb_size);
503 memset(cli->inbuf,'\0',smb_size);
504
505 set_message(cli->outbuf,1, 0,True);
506
507 SCVAL(cli->outbuf,smb_com,SMBunlink);
508 SSVAL(cli->outbuf,smb_tid,cli->cnum);
509 cli_setup_packet(cli);
510
511 SSVAL(cli->outbuf,smb_vwv0, attrs);
512
513 p = smb_buf(cli->outbuf);
514 *p++ = 4;
515 p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
516
517 cli_setup_bcc(cli, p);
518 cli_send_smb(cli);
519 if (!cli_receive_smb(cli)) {
520 return False;
521 }
522
523 if (cli_is_error(cli)) {
524 return False;
525 }
526
527 return True;
528}
529
530/****************************************************************************
531 Delete a file.
532****************************************************************************/
533
534BOOL cli_unlink(struct cli_state *cli, const char *fname)
535{
536 return cli_unlink_full(cli, fname, aSYSTEM | aHIDDEN);
537}
538
539/****************************************************************************
540 Create a directory.
541****************************************************************************/
542
543BOOL cli_mkdir(struct cli_state *cli, const char *dname)
544{
545 char *p;
546
547 memset(cli->outbuf,'\0',smb_size);
548 memset(cli->inbuf,'\0',smb_size);
549
550 set_message(cli->outbuf,0, 0,True);
551
552 SCVAL(cli->outbuf,smb_com,SMBmkdir);
553 SSVAL(cli->outbuf,smb_tid,cli->cnum);
554 cli_setup_packet(cli);
555
556 p = smb_buf(cli->outbuf);
557 *p++ = 4;
558 p += clistr_push(cli, p, dname, -1, STR_TERMINATE);
559
560 cli_setup_bcc(cli, p);
561
562 cli_send_smb(cli);
563 if (!cli_receive_smb(cli)) {
564 return False;
565 }
566
567 if (cli_is_error(cli)) {
568 return False;
569 }
570
571 return True;
572}
573
574/****************************************************************************
575 Remove a directory.
576****************************************************************************/
577
578BOOL cli_rmdir(struct cli_state *cli, const char *dname)
579{
580 char *p;
581
582 memset(cli->outbuf,'\0',smb_size);
583 memset(cli->inbuf,'\0',smb_size);
584
585 set_message(cli->outbuf,0, 0, True);
586
587 SCVAL(cli->outbuf,smb_com,SMBrmdir);
588 SSVAL(cli->outbuf,smb_tid,cli->cnum);
589 cli_setup_packet(cli);
590
591 p = smb_buf(cli->outbuf);
592 *p++ = 4;
593 p += clistr_push(cli, p, dname, -1, STR_TERMINATE);
594
595 cli_setup_bcc(cli, p);
596
597 cli_send_smb(cli);
598 if (!cli_receive_smb(cli)) {
599 return False;
600 }
601
602 if (cli_is_error(cli)) {
603 return False;
604 }
605
606 return True;
607}
608
609/****************************************************************************
610 Set or clear the delete on close flag.
611****************************************************************************/
612
613int cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag)
614{
615 unsigned int data_len = 1;
616 unsigned int param_len = 6;
617 uint16 setup = TRANSACT2_SETFILEINFO;
618 pstring param;
619 unsigned char data;
620 char *rparam=NULL, *rdata=NULL;
621
622 memset(param, 0, param_len);
623 SSVAL(param,0,fnum);
624 SSVAL(param,2,SMB_SET_FILE_DISPOSITION_INFO);
625
626 data = flag ? 1 : 0;
627
628 if (!cli_send_trans(cli, SMBtrans2,
629 NULL, /* name */
630 -1, 0, /* fid, flags */
631 &setup, 1, 0, /* setup, length, max */
632 param, param_len, 2, /* param, length, max */
633 (char *)&data, data_len, cli->max_xmit /* data, length, max */
634 )) {
635 return False;
636 }
637
638 if (!cli_receive_trans(cli, SMBtrans2,
639 &rparam, &param_len,
640 &rdata, &data_len)) {
641 return False;
642 }
643
644 SAFE_FREE(rdata);
645 SAFE_FREE(rparam);
646
647 return True;
648}
649
650/****************************************************************************
651 Open a file - exposing the full horror of the NT API :-).
652 Used in smbtorture.
653****************************************************************************/
654
655int cli_nt_create_full(struct cli_state *cli, const char *fname,
656 uint32 CreatFlags, uint32 DesiredAccess,
657 uint32 FileAttributes, uint32 ShareAccess,
658 uint32 CreateDisposition, uint32 CreateOptions,
659 uint8 SecuityFlags)
660{
661 char *p;
662 int len;
663
664 memset(cli->outbuf,'\0',smb_size);
665 memset(cli->inbuf,'\0',smb_size);
666
667 set_message(cli->outbuf,24,0,True);
668
669 SCVAL(cli->outbuf,smb_com,SMBntcreateX);
670 SSVAL(cli->outbuf,smb_tid,cli->cnum);
671 cli_setup_packet(cli);
672
673 SSVAL(cli->outbuf,smb_vwv0,0xFF);
674 if (cli->use_oplocks)
675 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
676
677 SIVAL(cli->outbuf,smb_ntcreate_Flags, CreatFlags);
678 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
679 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, DesiredAccess);
680 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, FileAttributes);
681 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, ShareAccess);
682 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, CreateDisposition);
683 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, CreateOptions);
684 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
685 SCVAL(cli->outbuf,smb_ntcreate_SecurityFlags, SecuityFlags);
686
687 p = smb_buf(cli->outbuf);
688 /* this alignment and termination is critical for netapp filers. Don't change */
689 p += clistr_align_out(cli, p, 0);
690 len = clistr_push(cli, p, fname, -1, 0);
691 p += len;
692 SSVAL(cli->outbuf,smb_ntcreate_NameLength, len);
693 /* sigh. this copes with broken netapp filer behaviour */
694 p += clistr_push(cli, p, "", -1, STR_TERMINATE);
695
696 cli_setup_bcc(cli, p);
697
698 cli_send_smb(cli);
699 if (!cli_receive_smb(cli)) {
700 return -1;
701 }
702
703 if (cli_is_error(cli)) {
704 return -1;
705 }
706
707 return SVAL(cli->inbuf,smb_vwv2 + 1);
708}
709
710/****************************************************************************
711 Open a file.
712****************************************************************************/
713
714int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess)
715{
716 return cli_nt_create_full(cli, fname, 0, DesiredAccess, 0,
717 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0);
718}
719
720/****************************************************************************
721 Open a file
722 WARNING: if you open with O_WRONLY then getattrE won't work!
723****************************************************************************/
724
725int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
726{
727 char *p;
728 unsigned openfn=0;
729 unsigned accessmode=0;
730
731 if (flags & O_CREAT)
732 openfn |= (1<<4);
733 if (!(flags & O_EXCL)) {
734 if (flags & O_TRUNC)
735 openfn |= (1<<1);
736 else
737 openfn |= (1<<0);
738 }
739
740 accessmode = (share_mode<<4);
741
742 if ((flags & O_ACCMODE) == O_RDWR) {
743 accessmode |= 2;
744 } else if ((flags & O_ACCMODE) == O_WRONLY) {
745 accessmode |= 1;
746 }
747
748#if defined(O_SYNC)
749 if ((flags & O_SYNC) == O_SYNC) {
750 accessmode |= (1<<14);
751 }
752#endif /* O_SYNC */
753
754 if (share_mode == DENY_FCB) {
755 accessmode = 0xFF;
756 }
757
758 memset(cli->outbuf,'\0',smb_size);
759 memset(cli->inbuf,'\0',smb_size);
760
761 set_message(cli->outbuf,15,0,True);
762
763 SCVAL(cli->outbuf,smb_com,SMBopenX);
764 SSVAL(cli->outbuf,smb_tid,cli->cnum);
765 cli_setup_packet(cli);
766
767 SSVAL(cli->outbuf,smb_vwv0,0xFF);
768 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
769 SSVAL(cli->outbuf,smb_vwv3,accessmode);
770 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
771 SSVAL(cli->outbuf,smb_vwv5,0);
772 SSVAL(cli->outbuf,smb_vwv8,openfn);
773
774 if (cli->use_oplocks) {
775 /* if using oplocks then ask for a batch oplock via
776 core and extended methods */
777 SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)|
778 FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK);
779 SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
780 }
781
782 p = smb_buf(cli->outbuf);
783 p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
784
785 cli_setup_bcc(cli, p);
786
787 cli_send_smb(cli);
788 if (!cli_receive_smb(cli)) {
789 return -1;
790 }
791
792 if (cli_is_error(cli)) {
793 return -1;
794 }
795
796 return SVAL(cli->inbuf,smb_vwv2);
797}
798
799/****************************************************************************
800 Close a file.
801****************************************************************************/
802
803BOOL cli_close(struct cli_state *cli, int fnum)
804{
805 memset(cli->outbuf,'\0',smb_size);
806 memset(cli->inbuf,'\0',smb_size);
807
808 set_message(cli->outbuf,3,0,True);
809
810 SCVAL(cli->outbuf,smb_com,SMBclose);
811 SSVAL(cli->outbuf,smb_tid,cli->cnum);
812 cli_setup_packet(cli);
813
814 SSVAL(cli->outbuf,smb_vwv0,fnum);
815 SIVALS(cli->outbuf,smb_vwv1,-1);
816
817 cli_send_smb(cli);
818 if (!cli_receive_smb(cli)) {
819 return False;
820 }
821
822 return !cli_is_error(cli);
823}
824
825
826/****************************************************************************
827 send a lock with a specified locktype
828 this is used for testing LOCKING_ANDX_CANCEL_LOCK
829****************************************************************************/
830
831NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
832 uint32 offset, uint32 len, int timeout, unsigned char locktype)
833{
834 char *p;
835 int saved_timeout = cli->timeout;
836
837 memset(cli->outbuf,'\0',smb_size);
838 memset(cli->inbuf,'\0', smb_size);
839
840 set_message(cli->outbuf,8,0,True);
841
842 SCVAL(cli->outbuf,smb_com,SMBlockingX);
843 SSVAL(cli->outbuf,smb_tid,cli->cnum);
844 cli_setup_packet(cli);
845
846 SCVAL(cli->outbuf,smb_vwv0,0xFF);
847 SSVAL(cli->outbuf,smb_vwv2,fnum);
848 SCVAL(cli->outbuf,smb_vwv3,locktype);
849 SIVALS(cli->outbuf, smb_vwv4, timeout);
850 SSVAL(cli->outbuf,smb_vwv6,0);
851 SSVAL(cli->outbuf,smb_vwv7,1);
852
853 p = smb_buf(cli->outbuf);
854 SSVAL(p, 0, cli->pid);
855 SIVAL(p, 2, offset);
856 SIVAL(p, 6, len);
857
858 p += 10;
859
860 cli_setup_bcc(cli, p);
861
862 cli_send_smb(cli);
863
864 if (timeout != 0) {
865 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
866 }
867
868 if (!cli_receive_smb(cli)) {
869 cli->timeout = saved_timeout;
870 return NT_STATUS_UNSUCCESSFUL;
871 }
872
873 cli->timeout = saved_timeout;
874
875 return cli_nt_error(cli);
876}
877
878/****************************************************************************
879 Lock a file.
880 note that timeout is in units of 2 milliseconds
881****************************************************************************/
882
883BOOL cli_lock(struct cli_state *cli, int fnum,
884 uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
885{
886 char *p;
887 int saved_timeout = cli->timeout;
888
889 memset(cli->outbuf,'\0',smb_size);
890 memset(cli->inbuf,'\0', smb_size);
891
892 set_message(cli->outbuf,8,0,True);
893
894 SCVAL(cli->outbuf,smb_com,SMBlockingX);
895 SSVAL(cli->outbuf,smb_tid,cli->cnum);
896 cli_setup_packet(cli);
897
898 SCVAL(cli->outbuf,smb_vwv0,0xFF);
899 SSVAL(cli->outbuf,smb_vwv2,fnum);
900 SCVAL(cli->outbuf,smb_vwv3,(lock_type == READ_LOCK? 1 : 0));
901 SIVALS(cli->outbuf, smb_vwv4, timeout);
902 SSVAL(cli->outbuf,smb_vwv6,0);
903 SSVAL(cli->outbuf,smb_vwv7,1);
904
905 p = smb_buf(cli->outbuf);
906 SSVAL(p, 0, cli->pid);
907 SIVAL(p, 2, offset);
908 SIVAL(p, 6, len);
909
910 p += 10;
911
912 cli_setup_bcc(cli, p);
913
914 cli_send_smb(cli);
915
916 if (timeout != 0) {
917 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout*2 + 5*1000);
918 }
919
920 if (!cli_receive_smb(cli)) {
921 cli->timeout = saved_timeout;
922 return False;
923 }
924
925 cli->timeout = saved_timeout;
926
927 if (cli_is_error(cli)) {
928 return False;
929 }
930
931 return True;
932}
933
934/****************************************************************************
935 Unlock a file.
936****************************************************************************/
937
938BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
939{
940 char *p;
941
942 memset(cli->outbuf,'\0',smb_size);
943 memset(cli->inbuf,'\0',smb_size);
944
945 set_message(cli->outbuf,8,0,True);
946
947 SCVAL(cli->outbuf,smb_com,SMBlockingX);
948 SSVAL(cli->outbuf,smb_tid,cli->cnum);
949 cli_setup_packet(cli);
950
951 SCVAL(cli->outbuf,smb_vwv0,0xFF);
952 SSVAL(cli->outbuf,smb_vwv2,fnum);
953 SCVAL(cli->outbuf,smb_vwv3,0);
954 SIVALS(cli->outbuf, smb_vwv4, 0);
955 SSVAL(cli->outbuf,smb_vwv6,1);
956 SSVAL(cli->outbuf,smb_vwv7,0);
957
958 p = smb_buf(cli->outbuf);
959 SSVAL(p, 0, cli->pid);
960 SIVAL(p, 2, offset);
961 SIVAL(p, 6, len);
962 p += 10;
963 cli_setup_bcc(cli, p);
964 cli_send_smb(cli);
965 if (!cli_receive_smb(cli)) {
966 return False;
967 }
968
969 if (cli_is_error(cli)) {
970 return False;
971 }
972
973 return True;
974}
975
976/****************************************************************************
977 Lock a file with 64 bit offsets.
978****************************************************************************/
979
980BOOL cli_lock64(struct cli_state *cli, int fnum,
981 SMB_BIG_UINT offset, SMB_BIG_UINT len, int timeout, enum brl_type lock_type)
982{
983 char *p;
984 int saved_timeout = cli->timeout;
985 int ltype;
986
987 if (! (cli->capabilities & CAP_LARGE_FILES)) {
988 return cli_lock(cli, fnum, offset, len, timeout, lock_type);
989 }
990
991 ltype = (lock_type == READ_LOCK? 1 : 0);
992 ltype |= LOCKING_ANDX_LARGE_FILES;
993
994 memset(cli->outbuf,'\0',smb_size);
995 memset(cli->inbuf,'\0', smb_size);
996
997 set_message(cli->outbuf,8,0,True);
998
999 SCVAL(cli->outbuf,smb_com,SMBlockingX);
1000 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1001 cli_setup_packet(cli);
1002
1003 SCVAL(cli->outbuf,smb_vwv0,0xFF);
1004 SSVAL(cli->outbuf,smb_vwv2,fnum);
1005 SCVAL(cli->outbuf,smb_vwv3,ltype);
1006 SIVALS(cli->outbuf, smb_vwv4, timeout);
1007 SSVAL(cli->outbuf,smb_vwv6,0);
1008 SSVAL(cli->outbuf,smb_vwv7,1);
1009
1010 p = smb_buf(cli->outbuf);
1011 SIVAL(p, 0, cli->pid);
1012 SOFF_T_R(p, 4, offset);
1013 SOFF_T_R(p, 12, len);
1014 p += 20;
1015
1016 cli_setup_bcc(cli, p);
1017 cli_send_smb(cli);
1018
1019 if (timeout != 0) {
1020 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 5*1000);
1021 }
1022
1023 if (!cli_receive_smb(cli)) {
1024 cli->timeout = saved_timeout;
1025 return False;
1026 }
1027
1028 cli->timeout = saved_timeout;
1029
1030 if (cli_is_error(cli)) {
1031 return False;
1032 }
1033
1034 return True;
1035}
1036
1037/****************************************************************************
1038 Unlock a file with 64 bit offsets.
1039****************************************************************************/
1040
1041BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
1042{
1043 char *p;
1044
1045 if (! (cli->capabilities & CAP_LARGE_FILES)) {
1046 return cli_unlock(cli, fnum, offset, len);
1047 }
1048
1049 memset(cli->outbuf,'\0',smb_size);
1050 memset(cli->inbuf,'\0',smb_size);
1051
1052 set_message(cli->outbuf,8,0,True);
1053
1054 SCVAL(cli->outbuf,smb_com,SMBlockingX);
1055 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1056 cli_setup_packet(cli);
1057
1058 SCVAL(cli->outbuf,smb_vwv0,0xFF);
1059 SSVAL(cli->outbuf,smb_vwv2,fnum);
1060 SCVAL(cli->outbuf,smb_vwv3,LOCKING_ANDX_LARGE_FILES);
1061 SIVALS(cli->outbuf, smb_vwv4, 0);
1062 SSVAL(cli->outbuf,smb_vwv6,1);
1063 SSVAL(cli->outbuf,smb_vwv7,0);
1064
1065 p = smb_buf(cli->outbuf);
1066 SIVAL(p, 0, cli->pid);
1067 SOFF_T_R(p, 4, offset);
1068 SOFF_T_R(p, 12, len);
1069 p += 20;
1070 cli_setup_bcc(cli, p);
1071 cli_send_smb(cli);
1072 if (!cli_receive_smb(cli)) {
1073 return False;
1074 }
1075
1076 if (cli_is_error(cli)) {
1077 return False;
1078 }
1079
1080 return True;
1081}
1082
1083/****************************************************************************
1084 Get/unlock a POSIX lock on a file - internal function.
1085****************************************************************************/
1086
1087static BOOL cli_posix_lock_internal(struct cli_state *cli, int fnum,
1088 SMB_BIG_UINT offset, SMB_BIG_UINT len, BOOL wait_lock, enum brl_type lock_type)
1089{
1090 unsigned int param_len = 4;
1091 unsigned int data_len = POSIX_LOCK_DATA_SIZE;
1092 uint16 setup = TRANSACT2_SETFILEINFO;
1093 char param[4];
1094 unsigned char data[POSIX_LOCK_DATA_SIZE];
1095 char *rparam=NULL, *rdata=NULL;
1096 int saved_timeout = cli->timeout;
1097
1098 SSVAL(param,0,fnum);
1099 SSVAL(param,2,SMB_SET_POSIX_LOCK);
1100
1101 switch (lock_type) {
1102 case READ_LOCK:
1103 SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_READ);
1104 break;
1105 case WRITE_LOCK:
1106 SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_WRITE);
1107 break;
1108 case UNLOCK_LOCK:
1109 SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
1110 break;
1111 default:
1112 return False;
1113 }
1114
1115 if (wait_lock) {
1116 SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_WAIT);
1117 cli->timeout = 0x7FFFFFFF;
1118 } else {
1119 SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_NOWAIT);
1120 }
1121
1122 SIVAL(data, POSIX_LOCK_PID_OFFSET, cli->pid);
1123 SOFF_T(data, POSIX_LOCK_START_OFFSET, offset);
1124 SOFF_T(data, POSIX_LOCK_LEN_OFFSET, len);
1125
1126 if (!cli_send_trans(cli, SMBtrans2,
1127 NULL, /* name */
1128 -1, 0, /* fid, flags */
1129 &setup, 1, 0, /* setup, length, max */
1130 param, param_len, 2, /* param, length, max */
1131 (char *)&data, data_len, cli->max_xmit /* data, length, max */
1132 )) {
1133 cli->timeout = saved_timeout;
1134 return False;
1135 }
1136
1137 if (!cli_receive_trans(cli, SMBtrans2,
1138 &rparam, &param_len,
1139 &rdata, &data_len)) {
1140 cli->timeout = saved_timeout;
1141 SAFE_FREE(rdata);
1142 SAFE_FREE(rparam);
1143 return False;
1144 }
1145
1146 cli->timeout = saved_timeout;
1147
1148 SAFE_FREE(rdata);
1149 SAFE_FREE(rparam);
1150
1151 return True;
1152}
1153
1154/****************************************************************************
1155 POSIX Lock a file.
1156****************************************************************************/
1157
1158BOOL cli_posix_lock(struct cli_state *cli, int fnum,
1159 SMB_BIG_UINT offset, SMB_BIG_UINT len,
1160 BOOL wait_lock, enum brl_type lock_type)
1161{
1162 if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
1163 return False;
1164 }
1165 return cli_posix_lock_internal(cli, fnum, offset, len, wait_lock, lock_type);
1166}
1167
1168/****************************************************************************
1169 POSIX Unlock a file.
1170****************************************************************************/
1171
1172BOOL cli_posix_unlock(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
1173{
1174 return cli_posix_lock_internal(cli, fnum, offset, len, False, UNLOCK_LOCK);
1175}
1176
1177/****************************************************************************
1178 POSIX Get any lock covering a file.
1179****************************************************************************/
1180
1181BOOL cli_posix_getlock(struct cli_state *cli, int fnum, SMB_BIG_UINT *poffset, SMB_BIG_UINT *plen)
1182{
1183 return True;
1184}
1185
1186/****************************************************************************
1187 Do a SMBgetattrE call.
1188****************************************************************************/
1189
1190BOOL cli_getattrE(struct cli_state *cli, int fd,
1191 uint16 *attr, SMB_OFF_T *size,
1192 time_t *change_time,
1193 time_t *access_time,
1194 time_t *write_time)
1195{
1196 memset(cli->outbuf,'\0',smb_size);
1197 memset(cli->inbuf,'\0',smb_size);
1198
1199 set_message(cli->outbuf,1,0,True);
1200
1201 SCVAL(cli->outbuf,smb_com,SMBgetattrE);
1202 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1203 cli_setup_packet(cli);
1204
1205 SSVAL(cli->outbuf,smb_vwv0,fd);
1206
1207 cli_send_smb(cli);
1208 if (!cli_receive_smb(cli)) {
1209 return False;
1210 }
1211
1212 if (cli_is_error(cli)) {
1213 return False;
1214 }
1215
1216 if (size) {
1217 *size = IVAL(cli->inbuf, smb_vwv6);
1218 }
1219
1220 if (attr) {
1221 *attr = SVAL(cli->inbuf,smb_vwv10);
1222 }
1223
1224 if (change_time) {
1225 *change_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv0);
1226 }
1227
1228 if (access_time) {
1229 *access_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv2);
1230 }
1231
1232 if (write_time) {
1233 *write_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv4);
1234 }
1235
1236 return True;
1237}
1238
1239/****************************************************************************
1240 Do a SMBgetatr call
1241****************************************************************************/
1242
1243BOOL cli_getatr(struct cli_state *cli, const char *fname,
1244 uint16 *attr, SMB_OFF_T *size, time_t *write_time)
1245{
1246 char *p;
1247
1248 memset(cli->outbuf,'\0',smb_size);
1249 memset(cli->inbuf,'\0',smb_size);
1250
1251 set_message(cli->outbuf,0,0,True);
1252
1253 SCVAL(cli->outbuf,smb_com,SMBgetatr);
1254 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1255 cli_setup_packet(cli);
1256
1257 p = smb_buf(cli->outbuf);
1258 *p++ = 4;
1259 p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
1260
1261 cli_setup_bcc(cli, p);
1262
1263 cli_send_smb(cli);
1264 if (!cli_receive_smb(cli)) {
1265 return False;
1266 }
1267
1268 if (cli_is_error(cli)) {
1269 return False;
1270 }
1271
1272 if (size) {
1273 *size = IVAL(cli->inbuf, smb_vwv3);
1274 }
1275
1276 if (write_time) {
1277 *write_time = cli_make_unix_date3(cli, cli->inbuf+smb_vwv1);
1278 }
1279
1280 if (attr) {
1281 *attr = SVAL(cli->inbuf,smb_vwv0);
1282 }
1283
1284
1285 return True;
1286}
1287
1288/****************************************************************************
1289 Do a SMBsetattrE call.
1290****************************************************************************/
1291
1292BOOL cli_setattrE(struct cli_state *cli, int fd,
1293 time_t change_time,
1294 time_t access_time,
1295 time_t write_time)
1296
1297{
1298 char *p;
1299
1300 memset(cli->outbuf,'\0',smb_size);
1301 memset(cli->inbuf,'\0',smb_size);
1302
1303 set_message(cli->outbuf,7,0,True);
1304
1305 SCVAL(cli->outbuf,smb_com,SMBsetattrE);
1306 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1307 cli_setup_packet(cli);
1308
1309 SSVAL(cli->outbuf,smb_vwv0, fd);
1310 cli_put_dos_date2(cli, cli->outbuf,smb_vwv1, change_time);
1311 cli_put_dos_date2(cli, cli->outbuf,smb_vwv3, access_time);
1312 cli_put_dos_date2(cli, cli->outbuf,smb_vwv5, write_time);
1313
1314 p = smb_buf(cli->outbuf);
1315 *p++ = 4;
1316
1317 cli_setup_bcc(cli, p);
1318
1319 cli_send_smb(cli);
1320 if (!cli_receive_smb(cli)) {
1321 return False;
1322 }
1323
1324 if (cli_is_error(cli)) {
1325 return False;
1326 }
1327
1328 return True;
1329}
1330
1331/****************************************************************************
1332 Do a SMBsetatr call.
1333****************************************************************************/
1334
1335BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
1336{
1337 char *p;
1338
1339 memset(cli->outbuf,'\0',smb_size);
1340 memset(cli->inbuf,'\0',smb_size);
1341
1342 set_message(cli->outbuf,8,0,True);
1343
1344 SCVAL(cli->outbuf,smb_com,SMBsetatr);
1345 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1346 cli_setup_packet(cli);
1347
1348 SSVAL(cli->outbuf,smb_vwv0, attr);
1349 cli_put_dos_date3(cli, cli->outbuf,smb_vwv1, t);
1350
1351 p = smb_buf(cli->outbuf);
1352 *p++ = 4;
1353 p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
1354 *p++ = 4;
1355
1356 cli_setup_bcc(cli, p);
1357
1358 cli_send_smb(cli);
1359 if (!cli_receive_smb(cli)) {
1360 return False;
1361 }
1362
1363 if (cli_is_error(cli)) {
1364 return False;
1365 }
1366
1367 return True;
1368}
1369
1370/****************************************************************************
1371 Check for existance of a dir.
1372****************************************************************************/
1373BOOL cli_chkpath(struct cli_state *cli, const char *path)
1374{
1375 pstring path2;
1376 char *p;
1377
1378 pstrcpy(path2,path);
1379 trim_char(path2,'\0','\\');
1380 if (!*path2)
1381 *path2 = '\\';
1382
1383 memset(cli->outbuf,'\0',smb_size);
1384 set_message(cli->outbuf,0,0,True);
1385 SCVAL(cli->outbuf,smb_com,SMBcheckpath);
1386 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1387 cli_setup_packet(cli);
1388 p = smb_buf(cli->outbuf);
1389 *p++ = 4;
1390 p += clistr_push(cli, p, path2, -1, STR_TERMINATE);
1391
1392 cli_setup_bcc(cli, p);
1393
1394 cli_send_smb(cli);
1395 if (!cli_receive_smb(cli)) {
1396 return False;
1397 }
1398
1399 if (cli_is_error(cli)) return False;
1400
1401 return True;
1402}
1403
1404/****************************************************************************
1405 Query disk space.
1406****************************************************************************/
1407
1408BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
1409{
1410 memset(cli->outbuf,'\0',smb_size);
1411 set_message(cli->outbuf,0,0,True);
1412 SCVAL(cli->outbuf,smb_com,SMBdskattr);
1413 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1414 cli_setup_packet(cli);
1415
1416 cli_send_smb(cli);
1417 if (!cli_receive_smb(cli)) {
1418 return False;
1419 }
1420
1421 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
1422 *total = SVAL(cli->inbuf,smb_vwv0);
1423 *avail = SVAL(cli->inbuf,smb_vwv3);
1424
1425 return True;
1426}
1427
1428/****************************************************************************
1429 Create and open a temporary file.
1430****************************************************************************/
1431
1432int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
1433{
1434 int len;
1435 char *p;
1436
1437 memset(cli->outbuf,'\0',smb_size);
1438 memset(cli->inbuf,'\0',smb_size);
1439
1440 set_message(cli->outbuf,3,0,True);
1441
1442 SCVAL(cli->outbuf,smb_com,SMBctemp);
1443 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1444 cli_setup_packet(cli);
1445
1446 SSVAL(cli->outbuf,smb_vwv0,0);
1447 SIVALS(cli->outbuf,smb_vwv1,-1);
1448
1449 p = smb_buf(cli->outbuf);
1450 *p++ = 4;
1451 p += clistr_push(cli, p, path, -1, STR_TERMINATE);
1452
1453 cli_setup_bcc(cli, p);
1454
1455 cli_send_smb(cli);
1456 if (!cli_receive_smb(cli)) {
1457 return -1;
1458 }
1459
1460 if (cli_is_error(cli)) {
1461 return -1;
1462 }
1463
1464 /* despite the spec, the result has a -1, followed by
1465 length, followed by name */
1466 p = smb_buf(cli->inbuf);
1467 p += 4;
1468 len = smb_buflen(cli->inbuf) - 4;
1469 if (len <= 0) return -1;
1470
1471 if (tmp_path) {
1472 pstring path2;
1473 clistr_pull(cli, path2, p,
1474 sizeof(path2), len, STR_ASCII);
1475 *tmp_path = SMB_STRDUP(path2);
1476 }
1477
1478 return SVAL(cli->inbuf,smb_vwv0);
1479}
1480
1481
1482/*
1483 send a raw ioctl - used by the torture code
1484*/
1485NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *blob)
1486{
1487 memset(cli->outbuf,'\0',smb_size);
1488 memset(cli->inbuf,'\0',smb_size);
1489
1490 set_message(cli->outbuf, 3, 0, True);
1491 SCVAL(cli->outbuf,smb_com,SMBioctl);
1492 cli_setup_packet(cli);
1493
1494 SSVAL(cli->outbuf, smb_vwv0, fnum);
1495 SSVAL(cli->outbuf, smb_vwv1, code>>16);
1496 SSVAL(cli->outbuf, smb_vwv2, (code&0xFFFF));
1497
1498 cli_send_smb(cli);
1499 if (!cli_receive_smb(cli)) {
1500 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1501 }
1502
1503 if (cli_is_error(cli)) {
1504 return cli_nt_error(cli);
1505 }
1506
1507 *blob = data_blob_null;
1508
1509 return NT_STATUS_OK;
1510}
1511
1512/*********************************************************
1513 Set an extended attribute utility fn.
1514*********************************************************/
1515
1516static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigned int param_len,
1517 const char *ea_name, const char *ea_val, size_t ea_len)
1518{
1519 unsigned int data_len = 0;
1520 char *data = NULL;
1521 char *rparam=NULL, *rdata=NULL;
1522 char *p;
1523 size_t ea_namelen = strlen(ea_name);
1524
1525 if (ea_namelen == 0 && ea_len == 0) {
1526 data_len = 4;
1527 data = (char *)SMB_MALLOC(data_len);
1528 if (!data) {
1529 return False;
1530 }
1531 p = data;
1532 SIVAL(p,0,data_len);
1533 } else {
1534 data_len = 4 + 4 + ea_namelen + 1 + ea_len;
1535 data = (char *)SMB_MALLOC(data_len);
1536 if (!data) {
1537 return False;
1538 }
1539 p = data;
1540 SIVAL(p,0,data_len);
1541 p += 4;
1542 SCVAL(p, 0, 0); /* EA flags. */
1543 SCVAL(p, 1, ea_namelen);
1544 SSVAL(p, 2, ea_len);
1545 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
1546 memcpy(p+4+ea_namelen+1, ea_val, ea_len);
1547 }
1548
1549 if (!cli_send_trans(cli, SMBtrans2,
1550 NULL, /* name */
1551 -1, 0, /* fid, flags */
1552 &setup, 1, 0, /* setup, length, max */
1553 param, param_len, 2, /* param, length, max */
1554 data, data_len, cli->max_xmit /* data, length, max */
1555 )) {
1556 return False;
1557 }
1558
1559 if (!cli_receive_trans(cli, SMBtrans2,
1560 &rparam, &param_len,
1561 &rdata, &data_len)) {
1562 return False;
1563 }
1564
1565 SAFE_FREE(data);
1566 SAFE_FREE(rdata);
1567 SAFE_FREE(rparam);
1568
1569 return True;
1570}
1571
1572/*********************************************************
1573 Set an extended attribute on a pathname.
1574*********************************************************/
1575
1576BOOL cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len)
1577{
1578 uint16 setup = TRANSACT2_SETPATHINFO;
1579 unsigned int param_len = 0;
1580 char param[sizeof(pstring)+6];
1581 size_t srclen = 2*(strlen(path)+1);
1582 char *p;
1583
1584 memset(param, 0, sizeof(param));
1585 SSVAL(param,0,SMB_INFO_SET_EA);
1586 p = &param[6];
1587
1588 p += clistr_push(cli, p, path, MIN(srclen, sizeof(param)-6), STR_TERMINATE);
1589 param_len = PTR_DIFF(p, param);
1590
1591 return cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len);
1592}
1593
1594/*********************************************************
1595 Set an extended attribute on an fnum.
1596*********************************************************/
1597
1598BOOL cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const char *ea_val, size_t ea_len)
1599{
1600 char param[6];
1601 uint16 setup = TRANSACT2_SETFILEINFO;
1602
1603 memset(param, 0, 6);
1604 SSVAL(param,0,fnum);
1605 SSVAL(param,2,SMB_INFO_SET_EA);
1606
1607 return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len);
1608}
1609
1610/*********************************************************
1611 Get an extended attribute list tility fn.
1612*********************************************************/
1613
1614static BOOL cli_get_ea_list(struct cli_state *cli,
1615 uint16 setup, char *param, unsigned int param_len,
1616 TALLOC_CTX *ctx,
1617 size_t *pnum_eas,
1618 struct ea_struct **pea_list)
1619{
1620 unsigned int data_len = 0;
1621 unsigned int rparam_len, rdata_len;
1622 char *rparam=NULL, *rdata=NULL;
1623 char *p;
1624 size_t ea_size;
1625 size_t num_eas;
1626 BOOL ret = False;
1627 struct ea_struct *ea_list;
1628
1629 *pnum_eas = 0;
1630 if (pea_list) {
1631 *pea_list = NULL;
1632 }
1633
1634 if (!cli_send_trans(cli, SMBtrans2,
1635 NULL, /* Name */
1636 -1, 0, /* fid, flags */
1637 &setup, 1, 0, /* setup, length, max */
1638 param, param_len, 10, /* param, length, max */
1639#ifdef __OS2__
1640 NULL, data_len, CLI_BUFFER_SIZE /* data, length, max */
1641#else
1642 NULL, data_len, cli->max_xmit /* data, length, max */
1643#endif
1644 )) {
1645 return False;
1646 }
1647
1648 if (!cli_receive_trans(cli, SMBtrans2,
1649 &rparam, &rparam_len,
1650 &rdata, &rdata_len)) {
1651 return False;
1652 }
1653
1654 if (!rdata || rdata_len < 4) {
1655 goto out;
1656 }
1657
1658 ea_size = (size_t)IVAL(rdata,0);
1659 if (ea_size > rdata_len) {
1660 goto out;
1661 }
1662
1663 if (ea_size == 0) {
1664 /* No EA's present. */
1665 ret = True;
1666 goto out;
1667 }
1668
1669 p = rdata + 4;
1670 ea_size -= 4;
1671
1672 /* Validate the EA list and count it. */
1673 for (num_eas = 0; ea_size >= 4; num_eas++) {
1674 unsigned int ea_namelen = CVAL(p,1);
1675 unsigned int ea_valuelen = SVAL(p,2);
1676 if (ea_namelen == 0) {
1677 goto out;
1678 }
1679 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
1680 goto out;
1681 }
1682 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
1683 p += 4 + ea_namelen + 1 + ea_valuelen;
1684 }
1685
1686 if (num_eas == 0) {
1687 ret = True;
1688 goto out;
1689 }
1690
1691 *pnum_eas = num_eas;
1692 if (!pea_list) {
1693 /* Caller only wants number of EA's. */
1694 ret = True;
1695 goto out;
1696 }
1697
1698 ea_list = TALLOC_ARRAY(ctx, struct ea_struct, num_eas);
1699 if (!ea_list) {
1700 goto out;
1701 }
1702
1703 ea_size = (size_t)IVAL(rdata,0);
1704 p = rdata + 4;
1705
1706 for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
1707 struct ea_struct *ea = &ea_list[num_eas];
1708 fstring unix_ea_name;
1709 unsigned int ea_namelen = CVAL(p,1);
1710 unsigned int ea_valuelen = SVAL(p,2);
1711
1712 ea->flags = CVAL(p,0);
1713 unix_ea_name[0] = '\0';
1714 pull_ascii_fstring(unix_ea_name, p + 4);
1715 ea->name = talloc_strdup(ctx, unix_ea_name);
1716 /* Ensure the value is null terminated (in case it's a string). */
1717 ea->value = data_blob_talloc(ctx, NULL, ea_valuelen + 1);
1718 if (!ea->value.data) {
1719 goto out;
1720 }
1721 if (ea_valuelen) {
1722 memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
1723 }
1724 ea->value.data[ea_valuelen] = 0;
1725 ea->value.length--;
1726 p += 4 + ea_namelen + 1 + ea_valuelen;
1727 }
1728
1729 *pea_list = ea_list;
1730 ret = True;
1731
1732 out :
1733
1734 SAFE_FREE(rdata);
1735 SAFE_FREE(rparam);
1736 return ret;
1737}
1738
1739/*********************************************************
1740 Get an extended attribute list from a pathname.
1741*********************************************************/
1742
1743BOOL cli_get_ea_list_path(struct cli_state *cli, const char *path,
1744 TALLOC_CTX *ctx,
1745 size_t *pnum_eas,
1746 struct ea_struct **pea_list)
1747{
1748 uint16 setup = TRANSACT2_QPATHINFO;
1749 unsigned int param_len = 0;
1750 char param[sizeof(pstring)+6];
1751 char *p;
1752
1753 p = param;
1754 memset(p, 0, 6);
1755 SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS);
1756 p += 6;
1757 p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
1758 param_len = PTR_DIFF(p, param);
1759
1760 return cli_get_ea_list(cli, setup, param, param_len, ctx, pnum_eas, pea_list);
1761}
1762
1763/*********************************************************
1764 Get an extended attribute list from an fnum.
1765*********************************************************/
1766
1767BOOL cli_get_ea_list_fnum(struct cli_state *cli, int fnum,
1768 TALLOC_CTX *ctx,
1769 size_t *pnum_eas,
1770 struct ea_struct **pea_list)
1771{
1772 uint16 setup = TRANSACT2_QFILEINFO;
1773 char param[6];
1774
1775 memset(param, 0, 6);
1776 SSVAL(param,0,fnum);
1777 SSVAL(param,2,SMB_INFO_SET_EA);
1778
1779 return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
1780}
1781
1782/****************************************************************************
1783 Convert open "flags" arg to uint32 on wire.
1784****************************************************************************/
1785
1786static uint32 open_flags_to_wire(int flags)
1787{
1788 int open_mode = flags & O_ACCMODE;
1789 uint32 ret = 0;
1790
1791 switch (open_mode) {
1792 case O_WRONLY:
1793 ret |= SMB_O_WRONLY;
1794 break;
1795 case O_RDWR:
1796 ret |= SMB_O_RDWR;
1797 break;
1798 default:
1799 case O_RDONLY:
1800 ret |= SMB_O_RDONLY;
1801 break;
1802 }
1803
1804 if (flags & O_CREAT) {
1805 ret |= SMB_O_CREAT;
1806 }
1807 if (flags & O_EXCL) {
1808 ret |= SMB_O_EXCL;
1809 }
1810 if (flags & O_TRUNC) {
1811 ret |= SMB_O_TRUNC;
1812 }
1813#if defined(O_SYNC)
1814 if (flags & O_SYNC) {
1815 ret |= SMB_O_SYNC;
1816 }
1817#endif /* O_SYNC */
1818 if (flags & O_APPEND) {
1819 ret |= SMB_O_APPEND;
1820 }
1821#if defined(O_DIRECT)
1822 if (flags & O_DIRECT) {
1823 ret |= SMB_O_DIRECT;
1824 }
1825#endif
1826#if defined(O_DIRECTORY)
1827 if (flags & O_DIRECTORY) {
1828 ret &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
1829 ret |= SMB_O_DIRECTORY;
1830 }
1831#endif
1832 return ret;
1833}
1834
1835/****************************************************************************
1836 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
1837****************************************************************************/
1838
1839static int cli_posix_open_internal(struct cli_state *cli, const char *fname, int flags, mode_t mode, BOOL is_dir)
1840{
1841 unsigned int data_len = 0;
1842 unsigned int param_len = 0;
1843 uint16 setup = TRANSACT2_SETPATHINFO;
1844 char param[sizeof(pstring)+6];
1845 char data[18];
1846 char *rparam=NULL, *rdata=NULL;
1847 char *p;
1848 int fnum = -1;
1849 uint32 wire_flags = open_flags_to_wire(flags);
1850
1851 memset(param, 0, sizeof(param));
1852 SSVAL(param,0, SMB_POSIX_PATH_OPEN);
1853 p = &param[6];
1854
1855 p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
1856 param_len = PTR_DIFF(p, param);
1857
1858 if (is_dir) {
1859 wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
1860 wire_flags |= SMB_O_DIRECTORY;
1861 }
1862
1863 p = data;
1864 SIVAL(p,0,0); /* No oplock. */
1865 SIVAL(p,4,wire_flags);
1866 SIVAL(p,8,unix_perms_to_wire(mode));
1867 SIVAL(p,12,0); /* Top bits of perms currently undefined. */
1868 SSVAL(p,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
1869
1870 data_len = 18;
1871
1872 if (!cli_send_trans(cli, SMBtrans2,
1873 NULL, /* name */
1874 -1, 0, /* fid, flags */
1875 &setup, 1, 0, /* setup, length, max */
1876 param, param_len, 2, /* param, length, max */
1877 (char *)&data, data_len, cli->max_xmit /* data, length, max */
1878 )) {
1879 return -1;
1880 }
1881
1882 if (!cli_receive_trans(cli, SMBtrans2,
1883 &rparam, &param_len,
1884 &rdata, &data_len)) {
1885 return -1;
1886 }
1887
1888 fnum = SVAL(rdata,2);
1889
1890 SAFE_FREE(rdata);
1891 SAFE_FREE(rparam);
1892
1893 return fnum;
1894}
1895
1896/****************************************************************************
1897 open - POSIX semantics.
1898****************************************************************************/
1899
1900int cli_posix_open(struct cli_state *cli, const char *fname, int flags, mode_t mode)
1901{
1902 return cli_posix_open_internal(cli, fname, flags, mode, False);
1903}
1904
1905/****************************************************************************
1906 mkdir - POSIX semantics.
1907****************************************************************************/
1908
1909int cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
1910{
1911 return (cli_posix_open_internal(cli, fname, O_CREAT, mode, True) == -1) ? -1 : 0;
1912}
1913
1914/****************************************************************************
1915 unlink or rmdir - POSIX semantics.
1916****************************************************************************/
1917
1918static BOOL cli_posix_unlink_internal(struct cli_state *cli, const char *fname, BOOL is_dir)
1919{
1920 unsigned int data_len = 0;
1921 unsigned int param_len = 0;
1922 uint16 setup = TRANSACT2_SETPATHINFO;
1923 char param[sizeof(pstring)+6];
1924 char data[2];
1925 char *rparam=NULL, *rdata=NULL;
1926 char *p;
1927
1928 memset(param, 0, sizeof(param));
1929 SSVAL(param,0, SMB_POSIX_PATH_UNLINK);
1930 p = &param[6];
1931
1932 p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
1933 param_len = PTR_DIFF(p, param);
1934
1935 SSVAL(data, 0, is_dir ? SMB_POSIX_UNLINK_DIRECTORY_TARGET :
1936 SMB_POSIX_UNLINK_FILE_TARGET);
1937 data_len = 2;
1938
1939 if (!cli_send_trans(cli, SMBtrans2,
1940 NULL, /* name */
1941 -1, 0, /* fid, flags */
1942 &setup, 1, 0, /* setup, length, max */
1943 param, param_len, 2, /* param, length, max */
1944 (char *)&data, data_len, cli->max_xmit /* data, length, max */
1945 )) {
1946 return False;
1947 }
1948
1949 if (!cli_receive_trans(cli, SMBtrans2,
1950 &rparam, &param_len,
1951 &rdata, &data_len)) {
1952 return False;
1953 }
1954
1955 SAFE_FREE(rdata);
1956 SAFE_FREE(rparam);
1957
1958 return True;
1959}
1960
1961/****************************************************************************
1962 unlink - POSIX semantics.
1963****************************************************************************/
1964
1965BOOL cli_posix_unlink(struct cli_state *cli, const char *fname)
1966{
1967 return cli_posix_unlink_internal(cli, fname, False);
1968}
1969
1970/****************************************************************************
1971 rmdir - POSIX semantics.
1972****************************************************************************/
1973
1974int cli_posix_rmdir(struct cli_state *cli, const char *fname)
1975{
1976 return cli_posix_unlink_internal(cli, fname, True);
1977}
Note: See TracBrowser for help on using the repository browser.