source: branches/samba-3.0/source/libsmb/clifile.c@ 390

Last change on this file since 390 was 143, checked in by Paul Smedley, 17 years ago

The parameter is wrong, must be the same as path info. Fixes ticket:5

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