2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2001-2002
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.
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.
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/>.
23 /****************************************************************************
24 Hard/Symlink a file (UNIX extensions).
25 Creates new name (sym)linked to oldname.
26 ****************************************************************************/
28 static bool cli_link_internal(struct cli_state *cli, const char *oldname, const char *newname, bool hard_link)
30 unsigned int data_len = 0;
31 unsigned int param_len = 0;
32 uint16 setup = TRANSACT2_SETPATHINFO;
35 char *rparam=NULL, *rdata=NULL;
37 size_t oldlen = 2*(strlen(oldname)+1);
38 size_t newlen = 2*(strlen(newname)+1);
40 param = SMB_MALLOC(6+newlen+2);
41 data = SMB_MALLOC(oldlen+2);
42 if (!param || !data) {
46 SSVAL(param,0,hard_link ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
50 p += clistr_push(cli, p, newname, newlen, STR_TERMINATE);
51 param_len = PTR_DIFF(p, param);
54 p += clistr_push(cli, p, oldname, oldlen, STR_TERMINATE);
55 data_len = PTR_DIFF(p, data);
57 if (!cli_send_trans(cli, SMBtrans2,
59 -1, 0, /* fid, flags */
60 &setup, 1, 0, /* setup, length, max */
61 param, param_len, 2, /* param, length, max */
62 (char *)&data, data_len, cli->max_xmit /* data, length, max */
72 if (!cli_receive_trans(cli, SMBtrans2,
86 /****************************************************************************
87 Map standard UNIX permissions onto wire representations.
88 ****************************************************************************/
90 uint32 unix_perms_to_wire(mode_t perms)
94 ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0);
95 ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0);
96 ret |= ((perms & S_IROTH) ? UNIX_R_OTH : 0);
97 ret |= ((perms & S_IXGRP) ? UNIX_X_GRP : 0);
98 ret |= ((perms & S_IWGRP) ? UNIX_W_GRP : 0);
99 ret |= ((perms & S_IRGRP) ? UNIX_R_GRP : 0);
100 ret |= ((perms & S_IXUSR) ? UNIX_X_USR : 0);
101 ret |= ((perms & S_IWUSR) ? UNIX_W_USR : 0);
102 ret |= ((perms & S_IRUSR) ? UNIX_R_USR : 0);
104 ret |= ((perms & S_ISVTX) ? UNIX_STICKY : 0);
107 ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0);
110 ret |= ((perms & S_ISUID) ? UNIX_SET_UID : 0);
115 /****************************************************************************
116 Map wire permissions to standard UNIX.
117 ****************************************************************************/
119 mode_t wire_perms_to_unix(uint32 perms)
121 mode_t ret = (mode_t)0;
123 ret |= ((perms & UNIX_X_OTH) ? S_IXOTH : 0);
124 ret |= ((perms & UNIX_W_OTH) ? S_IWOTH : 0);
125 ret |= ((perms & UNIX_R_OTH) ? S_IROTH : 0);
126 ret |= ((perms & UNIX_X_GRP) ? S_IXGRP : 0);
127 ret |= ((perms & UNIX_W_GRP) ? S_IWGRP : 0);
128 ret |= ((perms & UNIX_R_GRP) ? S_IRGRP : 0);
129 ret |= ((perms & UNIX_X_USR) ? S_IXUSR : 0);
130 ret |= ((perms & UNIX_W_USR) ? S_IWUSR : 0);
131 ret |= ((perms & UNIX_R_USR) ? S_IRUSR : 0);
133 ret |= ((perms & UNIX_STICKY) ? S_ISVTX : 0);
136 ret |= ((perms & UNIX_SET_GID) ? S_ISGID : 0);
139 ret |= ((perms & UNIX_SET_UID) ? S_ISUID : 0);
144 /****************************************************************************
145 Return the file type from the wire filetype for UNIX extensions.
146 ****************************************************************************/
148 static mode_t unix_filetype_from_wire(uint32 wire_type)
156 case UNIX_TYPE_SYMLINK:
160 case UNIX_TYPE_CHARDEV:
164 case UNIX_TYPE_BLKDEV:
172 case UNIX_TYPE_SOCKET:
180 /****************************************************************************
181 Do a POSIX getfacl (UNIX extensions).
182 ****************************************************************************/
184 bool cli_unix_getfacl(struct cli_state *cli, const char *name, size_t *prb_size, char **retbuf)
186 unsigned int param_len = 0;
187 unsigned int data_len = 0;
188 uint16 setup = TRANSACT2_QPATHINFO;
190 size_t nlen = 2*(strlen(name)+1);
191 char *rparam=NULL, *rdata=NULL;
194 param = SMB_MALLOC(6+nlen+2);
201 SSVAL(p, 0, SMB_QUERY_POSIX_ACL);
203 p += clistr_push(cli, p, name, nlen, STR_TERMINATE);
204 param_len = PTR_DIFF(p, param);
206 if (!cli_send_trans(cli, SMBtrans2,
208 -1, 0, /* fid, flags */
209 &setup, 1, 0, /* setup, length, max */
210 param, param_len, 2, /* param, length, max */
211 NULL, 0, cli->max_xmit /* data, length, max */
219 if (!cli_receive_trans(cli, SMBtrans2,
221 &rdata, &data_len)) {
233 *prb_size = (size_t)data_len;
238 /****************************************************************************
239 Stat a file (UNIX extensions).
240 ****************************************************************************/
242 bool cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf)
244 unsigned int param_len = 0;
245 unsigned int data_len = 0;
246 uint16 setup = TRANSACT2_QPATHINFO;
248 size_t nlen = 2*(strlen(name)+1);
249 char *rparam=NULL, *rdata=NULL;
254 param = SMB_MALLOC(6+nlen+2);
260 SSVAL(p, 0, SMB_QUERY_FILE_UNIX_BASIC);
262 p += clistr_push(cli, p, name, nlen, STR_TERMINATE);
263 param_len = PTR_DIFF(p, param);
265 if (!cli_send_trans(cli, SMBtrans2,
267 -1, 0, /* fid, flags */
268 &setup, 1, 0, /* setup, length, max */
269 param, param_len, 2, /* param, length, max */
270 NULL, 0, cli->max_xmit /* data, length, max */
278 if (!cli_receive_trans(cli, SMBtrans2,
280 &rdata, &data_len)) {
290 sbuf->st_size = IVAL2_TO_SMB_BIG_UINT(rdata,0); /* total size, in bytes */
291 sbuf->st_blocks = IVAL2_TO_SMB_BIG_UINT(rdata,8); /* number of blocks allocated */
292 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
293 sbuf->st_blocks /= STAT_ST_BLOCKSIZE;
295 /* assume 512 byte blocks */
296 sbuf->st_blocks /= 512;
298 set_ctimespec(sbuf, interpret_long_date(rdata + 16)); /* time of last change */
299 set_atimespec(sbuf, interpret_long_date(rdata + 24)); /* time of last access */
300 set_mtimespec(sbuf, interpret_long_date(rdata + 32)); /* time of last modification */
302 sbuf->st_uid = (uid_t) IVAL(rdata,40); /* user ID of owner */
303 sbuf->st_gid = (gid_t) IVAL(rdata,48); /* group ID of owner */
304 sbuf->st_mode |= unix_filetype_from_wire(IVAL(rdata, 56));
305 #if defined(HAVE_MAKEDEV)
307 uint32 dev_major = IVAL(rdata,60);
308 uint32 dev_minor = IVAL(rdata,68);
309 sbuf->st_rdev = makedev(dev_major, dev_minor);
312 sbuf->st_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(rdata,76); /* inode */
313 sbuf->st_mode |= wire_perms_to_unix(IVAL(rdata,84)); /* protection */
314 sbuf->st_nlink = IVAL(rdata,92); /* number of hard links */
322 /****************************************************************************
323 Symlink a file (UNIX extensions).
324 ****************************************************************************/
326 bool cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *newname)
328 return cli_link_internal(cli, oldname, newname, False);
331 /****************************************************************************
332 Hard a file (UNIX extensions).
333 ****************************************************************************/
335 bool cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *newname)
337 return cli_link_internal(cli, oldname, newname, True);
340 /****************************************************************************
341 Chmod or chown a file internal (UNIX extensions).
342 ****************************************************************************/
344 static bool cli_unix_chmod_chown_internal(struct cli_state *cli, const char *fname, uint32 mode, uint32 uid, uint32 gid)
346 unsigned int data_len = 0;
347 unsigned int param_len = 0;
348 uint16 setup = TRANSACT2_SETPATHINFO;
349 size_t nlen = 2*(strlen(fname)+1);
352 char *rparam=NULL, *rdata=NULL;
355 param = SMB_MALLOC(6+nlen+2);
359 memset(param, '\0', 6);
360 memset(data, 0, sizeof(data));
362 SSVAL(param,0,SMB_SET_FILE_UNIX_BASIC);
365 p += clistr_push(cli, p, fname, nlen, STR_TERMINATE);
366 param_len = PTR_DIFF(p, param);
368 memset(data, 0xff, 40); /* Set all sizes/times to no change. */
376 if (!cli_send_trans(cli, SMBtrans2,
378 -1, 0, /* fid, flags */
379 &setup, 1, 0, /* setup, length, max */
380 param, param_len, 2, /* param, length, max */
381 (char *)&data, data_len, cli->max_xmit /* data, length, max */
389 if (!cli_receive_trans(cli, SMBtrans2,
391 &rdata, &data_len)) {
401 /****************************************************************************
402 chmod a file (UNIX extensions).
403 ****************************************************************************/
405 bool cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
407 return cli_unix_chmod_chown_internal(cli, fname,
408 unix_perms_to_wire(mode), SMB_UID_NO_CHANGE, SMB_GID_NO_CHANGE);
411 /****************************************************************************
412 chown a file (UNIX extensions).
413 ****************************************************************************/
415 bool cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid)
417 return cli_unix_chmod_chown_internal(cli, fname,
418 SMB_MODE_NO_CHANGE, (uint32)uid, (uint32)gid);
421 /****************************************************************************
423 ****************************************************************************/
425 bool cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
429 memset(cli->outbuf,'\0',smb_size);
430 memset(cli->inbuf,'\0',smb_size);
432 set_message(cli->outbuf,1, 0, true);
434 SCVAL(cli->outbuf,smb_com,SMBmv);
435 SSVAL(cli->outbuf,smb_tid,cli->cnum);
436 cli_setup_packet(cli);
438 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
440 p = smb_buf(cli->outbuf);
442 p += clistr_push(cli, p, fname_src,
443 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
445 p += clistr_push(cli, p, fname_dst,
446 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
448 cli_setup_bcc(cli, p);
451 if (!cli_receive_smb(cli)) {
455 if (cli_is_error(cli)) {
462 /****************************************************************************
464 ****************************************************************************/
466 bool cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
470 memset(cli->outbuf,'\0',smb_size);
471 memset(cli->inbuf,'\0',smb_size);
473 set_message(cli->outbuf, 4, 0, true);
475 SCVAL(cli->outbuf,smb_com,SMBntrename);
476 SSVAL(cli->outbuf,smb_tid,cli->cnum);
477 cli_setup_packet(cli);
479 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
480 SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_RENAME);
482 p = smb_buf(cli->outbuf);
484 p += clistr_push(cli, p, fname_src,
485 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
487 p += clistr_push(cli, p, fname_dst,
488 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
490 cli_setup_bcc(cli, p);
493 if (!cli_receive_smb(cli)) {
497 if (cli_is_error(cli)) {
504 /****************************************************************************
506 ****************************************************************************/
508 bool cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
512 memset(cli->outbuf,'\0',smb_size);
513 memset(cli->inbuf,'\0',smb_size);
515 set_message(cli->outbuf, 4, 0, true);
517 SCVAL(cli->outbuf,smb_com,SMBntrename);
518 SSVAL(cli->outbuf,smb_tid,cli->cnum);
519 cli_setup_packet(cli);
521 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
522 SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_HARD_LINK);
524 p = smb_buf(cli->outbuf);
526 p += clistr_push(cli, p, fname_src,
527 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
529 p += clistr_push(cli, p, fname_dst,
530 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
532 cli_setup_bcc(cli, p);
535 if (!cli_receive_smb(cli)) {
539 if (cli_is_error(cli)) {
546 /****************************************************************************
548 ****************************************************************************/
550 bool cli_unlink_full(struct cli_state *cli, const char *fname, uint16 attrs)
554 memset(cli->outbuf,'\0',smb_size);
555 memset(cli->inbuf,'\0',smb_size);
557 set_message(cli->outbuf,1, 0, true);
559 SCVAL(cli->outbuf,smb_com,SMBunlink);
560 SSVAL(cli->outbuf,smb_tid,cli->cnum);
561 cli_setup_packet(cli);
563 SSVAL(cli->outbuf,smb_vwv0, attrs);
565 p = smb_buf(cli->outbuf);
567 p += clistr_push(cli, p, fname,
568 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
570 cli_setup_bcc(cli, p);
572 if (!cli_receive_smb(cli)) {
576 if (cli_is_error(cli)) {
583 /****************************************************************************
585 ****************************************************************************/
587 bool cli_unlink(struct cli_state *cli, const char *fname)
589 return cli_unlink_full(cli, fname, aSYSTEM | aHIDDEN);
592 /****************************************************************************
594 ****************************************************************************/
596 bool cli_mkdir(struct cli_state *cli, const char *dname)
600 memset(cli->outbuf,'\0',smb_size);
601 memset(cli->inbuf,'\0',smb_size);
603 set_message(cli->outbuf,0, 0, true);
605 SCVAL(cli->outbuf,smb_com,SMBmkdir);
606 SSVAL(cli->outbuf,smb_tid,cli->cnum);
607 cli_setup_packet(cli);
609 p = smb_buf(cli->outbuf);
611 p += clistr_push(cli, p, dname,
612 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
614 cli_setup_bcc(cli, p);
617 if (!cli_receive_smb(cli)) {
621 if (cli_is_error(cli)) {
628 /****************************************************************************
630 ****************************************************************************/
632 bool cli_rmdir(struct cli_state *cli, const char *dname)
636 memset(cli->outbuf,'\0',smb_size);
637 memset(cli->inbuf,'\0',smb_size);
639 set_message(cli->outbuf,0, 0, true);
641 SCVAL(cli->outbuf,smb_com,SMBrmdir);
642 SSVAL(cli->outbuf,smb_tid,cli->cnum);
643 cli_setup_packet(cli);
645 p = smb_buf(cli->outbuf);
647 p += clistr_push(cli, p, dname,
648 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
650 cli_setup_bcc(cli, p);
653 if (!cli_receive_smb(cli)) {
657 if (cli_is_error(cli)) {
664 /****************************************************************************
665 Set or clear the delete on close flag.
666 ****************************************************************************/
668 int cli_nt_delete_on_close(struct cli_state *cli, int fnum, bool flag)
670 unsigned int data_len = 1;
671 unsigned int param_len = 6;
672 uint16 setup = TRANSACT2_SETFILEINFO;
675 char *rparam=NULL, *rdata=NULL;
677 memset(param, 0, param_len);
679 SSVAL(param,2,SMB_SET_FILE_DISPOSITION_INFO);
683 if (!cli_send_trans(cli, SMBtrans2,
685 -1, 0, /* fid, flags */
686 &setup, 1, 0, /* setup, length, max */
687 param, param_len, 2, /* param, length, max */
688 (char *)&data, data_len, cli->max_xmit /* data, length, max */
693 if (!cli_receive_trans(cli, SMBtrans2,
695 &rdata, &data_len)) {
705 /****************************************************************************
706 Open a file - exposing the full horror of the NT API :-).
708 ****************************************************************************/
710 int cli_nt_create_full(struct cli_state *cli, const char *fname,
711 uint32 CreatFlags, uint32 DesiredAccess,
712 uint32 FileAttributes, uint32 ShareAccess,
713 uint32 CreateDisposition, uint32 CreateOptions,
719 memset(cli->outbuf,'\0',smb_size);
720 memset(cli->inbuf,'\0',smb_size);
722 set_message(cli->outbuf,24,0, true);
724 SCVAL(cli->outbuf,smb_com,SMBntcreateX);
725 SSVAL(cli->outbuf,smb_tid,cli->cnum);
726 cli_setup_packet(cli);
728 SSVAL(cli->outbuf,smb_vwv0,0xFF);
729 if (cli->use_oplocks)
730 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
732 SIVAL(cli->outbuf,smb_ntcreate_Flags, CreatFlags);
733 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
734 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, DesiredAccess);
735 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, FileAttributes);
736 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, ShareAccess);
737 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, CreateDisposition);
738 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, CreateOptions);
739 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
740 SCVAL(cli->outbuf,smb_ntcreate_SecurityFlags, SecuityFlags);
742 p = smb_buf(cli->outbuf);
743 /* this alignment and termination is critical for netapp filers. Don't change */
744 p += clistr_align_out(cli, p, 0);
745 len = clistr_push(cli, p, fname,
746 cli->bufsize - PTR_DIFF(p,cli->outbuf), 0);
748 SSVAL(cli->outbuf,smb_ntcreate_NameLength, len);
749 /* sigh. this copes with broken netapp filer behaviour */
750 p += clistr_push(cli, p, "",
751 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
753 cli_setup_bcc(cli, p);
756 if (!cli_receive_smb(cli)) {
760 if (cli_is_error(cli)) {
764 return SVAL(cli->inbuf,smb_vwv2 + 1);
767 /****************************************************************************
769 ****************************************************************************/
771 int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess)
773 return cli_nt_create_full(cli, fname, 0, DesiredAccess, 0,
774 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0);
777 /****************************************************************************
779 WARNING: if you open with O_WRONLY then getattrE won't work!
780 ****************************************************************************/
782 int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
786 unsigned accessmode=0;
790 if (!(flags & O_EXCL)) {
797 accessmode = (share_mode<<4);
799 if ((flags & O_ACCMODE) == O_RDWR) {
801 } else if ((flags & O_ACCMODE) == O_WRONLY) {
806 if ((flags & O_SYNC) == O_SYNC) {
807 accessmode |= (1<<14);
811 if (share_mode == DENY_FCB) {
815 memset(cli->outbuf,'\0',smb_size);
816 memset(cli->inbuf,'\0',smb_size);
818 set_message(cli->outbuf,15,0, true);
820 SCVAL(cli->outbuf,smb_com,SMBopenX);
821 SSVAL(cli->outbuf,smb_tid,cli->cnum);
822 cli_setup_packet(cli);
824 SSVAL(cli->outbuf,smb_vwv0,0xFF);
825 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
826 SSVAL(cli->outbuf,smb_vwv3,accessmode);
827 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
828 SSVAL(cli->outbuf,smb_vwv5,0);
829 SSVAL(cli->outbuf,smb_vwv8,openfn);
831 if (cli->use_oplocks) {
832 /* if using oplocks then ask for a batch oplock via
833 core and extended methods */
834 SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)|
835 FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK);
836 SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
839 p = smb_buf(cli->outbuf);
840 p += clistr_push(cli, p, fname,
841 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
843 cli_setup_bcc(cli, p);
846 if (!cli_receive_smb(cli)) {
850 if (cli_is_error(cli)) {
854 return SVAL(cli->inbuf,smb_vwv2);
857 /****************************************************************************
859 ****************************************************************************/
861 bool cli_close(struct cli_state *cli, int fnum)
863 memset(cli->outbuf,'\0',smb_size);
864 memset(cli->inbuf,'\0',smb_size);
866 set_message(cli->outbuf,3,0,True);
868 SCVAL(cli->outbuf,smb_com,SMBclose);
869 SSVAL(cli->outbuf,smb_tid,cli->cnum);
870 cli_setup_packet(cli);
872 SSVAL(cli->outbuf,smb_vwv0,fnum);
873 SIVALS(cli->outbuf,smb_vwv1,-1);
876 if (!cli_receive_smb(cli)) {
880 return !cli_is_error(cli);
884 /****************************************************************************
885 send a lock with a specified locktype
886 this is used for testing LOCKING_ANDX_CANCEL_LOCK
887 ****************************************************************************/
889 NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
890 uint32 offset, uint32 len,
891 int timeout, unsigned char locktype)
894 int saved_timeout = cli->timeout;
896 memset(cli->outbuf,'\0',smb_size);
897 memset(cli->inbuf,'\0', smb_size);
899 set_message(cli->outbuf,8,0,True);
901 SCVAL(cli->outbuf,smb_com,SMBlockingX);
902 SSVAL(cli->outbuf,smb_tid,cli->cnum);
903 cli_setup_packet(cli);
905 SCVAL(cli->outbuf,smb_vwv0,0xFF);
906 SSVAL(cli->outbuf,smb_vwv2,fnum);
907 SCVAL(cli->outbuf,smb_vwv3,locktype);
908 SIVALS(cli->outbuf, smb_vwv4, timeout);
909 SSVAL(cli->outbuf,smb_vwv6,0);
910 SSVAL(cli->outbuf,smb_vwv7,1);
912 p = smb_buf(cli->outbuf);
913 SSVAL(p, 0, cli->pid);
919 cli_setup_bcc(cli, p);
924 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
927 if (!cli_receive_smb(cli)) {
928 cli->timeout = saved_timeout;
929 return NT_STATUS_UNSUCCESSFUL;
932 cli->timeout = saved_timeout;
934 return cli_nt_error(cli);
937 /****************************************************************************
939 note that timeout is in units of 2 milliseconds
940 ****************************************************************************/
942 bool cli_lock(struct cli_state *cli, int fnum,
943 uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
946 int saved_timeout = cli->timeout;
948 memset(cli->outbuf,'\0',smb_size);
949 memset(cli->inbuf,'\0', smb_size);
951 set_message(cli->outbuf,8,0,True);
953 SCVAL(cli->outbuf,smb_com,SMBlockingX);
954 SSVAL(cli->outbuf,smb_tid,cli->cnum);
955 cli_setup_packet(cli);
957 SCVAL(cli->outbuf,smb_vwv0,0xFF);
958 SSVAL(cli->outbuf,smb_vwv2,fnum);
959 SCVAL(cli->outbuf,smb_vwv3,(lock_type == READ_LOCK? 1 : 0));
960 SIVALS(cli->outbuf, smb_vwv4, timeout);
961 SSVAL(cli->outbuf,smb_vwv6,0);
962 SSVAL(cli->outbuf,smb_vwv7,1);
964 p = smb_buf(cli->outbuf);
965 SSVAL(p, 0, cli->pid);
971 cli_setup_bcc(cli, p);
976 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout*2 + 5*1000);
979 if (!cli_receive_smb(cli)) {
980 cli->timeout = saved_timeout;
984 cli->timeout = saved_timeout;
986 if (cli_is_error(cli)) {
993 /****************************************************************************
995 ****************************************************************************/
997 bool cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
1001 memset(cli->outbuf,'\0',smb_size);
1002 memset(cli->inbuf,'\0',smb_size);
1004 set_message(cli->outbuf,8,0,True);
1006 SCVAL(cli->outbuf,smb_com,SMBlockingX);
1007 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1008 cli_setup_packet(cli);
1010 SCVAL(cli->outbuf,smb_vwv0,0xFF);
1011 SSVAL(cli->outbuf,smb_vwv2,fnum);
1012 SCVAL(cli->outbuf,smb_vwv3,0);
1013 SIVALS(cli->outbuf, smb_vwv4, 0);
1014 SSVAL(cli->outbuf,smb_vwv6,1);
1015 SSVAL(cli->outbuf,smb_vwv7,0);
1017 p = smb_buf(cli->outbuf);
1018 SSVAL(p, 0, cli->pid);
1019 SIVAL(p, 2, offset);
1022 cli_setup_bcc(cli, p);
1024 if (!cli_receive_smb(cli)) {
1028 if (cli_is_error(cli)) {
1035 /****************************************************************************
1036 Lock a file with 64 bit offsets.
1037 ****************************************************************************/
1039 bool cli_lock64(struct cli_state *cli, int fnum,
1040 SMB_BIG_UINT offset, SMB_BIG_UINT len, int timeout, enum brl_type lock_type)
1043 int saved_timeout = cli->timeout;
1046 if (! (cli->capabilities & CAP_LARGE_FILES)) {
1047 return cli_lock(cli, fnum, offset, len, timeout, lock_type);
1050 ltype = (lock_type == READ_LOCK? 1 : 0);
1051 ltype |= LOCKING_ANDX_LARGE_FILES;
1053 memset(cli->outbuf,'\0',smb_size);
1054 memset(cli->inbuf,'\0', smb_size);
1056 set_message(cli->outbuf,8,0,True);
1058 SCVAL(cli->outbuf,smb_com,SMBlockingX);
1059 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1060 cli_setup_packet(cli);
1062 SCVAL(cli->outbuf,smb_vwv0,0xFF);
1063 SSVAL(cli->outbuf,smb_vwv2,fnum);
1064 SCVAL(cli->outbuf,smb_vwv3,ltype);
1065 SIVALS(cli->outbuf, smb_vwv4, timeout);
1066 SSVAL(cli->outbuf,smb_vwv6,0);
1067 SSVAL(cli->outbuf,smb_vwv7,1);
1069 p = smb_buf(cli->outbuf);
1070 SIVAL(p, 0, cli->pid);
1071 SOFF_T_R(p, 4, offset);
1072 SOFF_T_R(p, 12, len);
1075 cli_setup_bcc(cli, p);
1079 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 5*1000);
1082 if (!cli_receive_smb(cli)) {
1083 cli->timeout = saved_timeout;
1087 cli->timeout = saved_timeout;
1089 if (cli_is_error(cli)) {
1096 /****************************************************************************
1097 Unlock a file with 64 bit offsets.
1098 ****************************************************************************/
1100 bool cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
1104 if (! (cli->capabilities & CAP_LARGE_FILES)) {
1105 return cli_unlock(cli, fnum, offset, len);
1108 memset(cli->outbuf,'\0',smb_size);
1109 memset(cli->inbuf,'\0',smb_size);
1111 set_message(cli->outbuf,8,0,True);
1113 SCVAL(cli->outbuf,smb_com,SMBlockingX);
1114 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1115 cli_setup_packet(cli);
1117 SCVAL(cli->outbuf,smb_vwv0,0xFF);
1118 SSVAL(cli->outbuf,smb_vwv2,fnum);
1119 SCVAL(cli->outbuf,smb_vwv3,LOCKING_ANDX_LARGE_FILES);
1120 SIVALS(cli->outbuf, smb_vwv4, 0);
1121 SSVAL(cli->outbuf,smb_vwv6,1);
1122 SSVAL(cli->outbuf,smb_vwv7,0);
1124 p = smb_buf(cli->outbuf);
1125 SIVAL(p, 0, cli->pid);
1126 SOFF_T_R(p, 4, offset);
1127 SOFF_T_R(p, 12, len);
1129 cli_setup_bcc(cli, p);
1131 if (!cli_receive_smb(cli)) {
1135 if (cli_is_error(cli)) {
1142 /****************************************************************************
1143 Get/unlock a POSIX lock on a file - internal function.
1144 ****************************************************************************/
1146 static bool cli_posix_lock_internal(struct cli_state *cli, int fnum,
1147 SMB_BIG_UINT offset, SMB_BIG_UINT len, bool wait_lock, enum brl_type lock_type)
1149 unsigned int param_len = 4;
1150 unsigned int data_len = POSIX_LOCK_DATA_SIZE;
1151 uint16 setup = TRANSACT2_SETFILEINFO;
1153 unsigned char data[POSIX_LOCK_DATA_SIZE];
1154 char *rparam=NULL, *rdata=NULL;
1155 int saved_timeout = cli->timeout;
1157 SSVAL(param,0,fnum);
1158 SSVAL(param,2,SMB_SET_POSIX_LOCK);
1160 switch (lock_type) {
1162 SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_READ);
1165 SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_WRITE);
1168 SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
1175 SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_WAIT);
1176 cli->timeout = 0x7FFFFFFF;
1178 SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_NOWAIT);
1181 SIVAL(data, POSIX_LOCK_PID_OFFSET, cli->pid);
1182 SOFF_T(data, POSIX_LOCK_START_OFFSET, offset);
1183 SOFF_T(data, POSIX_LOCK_LEN_OFFSET, len);
1185 if (!cli_send_trans(cli, SMBtrans2,
1187 -1, 0, /* fid, flags */
1188 &setup, 1, 0, /* setup, length, max */
1189 param, param_len, 2, /* param, length, max */
1190 (char *)&data, data_len, cli->max_xmit /* data, length, max */
1192 cli->timeout = saved_timeout;
1196 if (!cli_receive_trans(cli, SMBtrans2,
1197 &rparam, ¶m_len,
1198 &rdata, &data_len)) {
1199 cli->timeout = saved_timeout;
1205 cli->timeout = saved_timeout;
1213 /****************************************************************************
1215 ****************************************************************************/
1217 bool cli_posix_lock(struct cli_state *cli, int fnum,
1218 SMB_BIG_UINT offset, SMB_BIG_UINT len,
1219 bool wait_lock, enum brl_type lock_type)
1221 if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
1224 return cli_posix_lock_internal(cli, fnum, offset, len, wait_lock, lock_type);
1227 /****************************************************************************
1228 POSIX Unlock a file.
1229 ****************************************************************************/
1231 bool cli_posix_unlock(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
1233 return cli_posix_lock_internal(cli, fnum, offset, len, False, UNLOCK_LOCK);
1236 /****************************************************************************
1237 POSIX Get any lock covering a file.
1238 ****************************************************************************/
1240 bool cli_posix_getlock(struct cli_state *cli, int fnum, SMB_BIG_UINT *poffset, SMB_BIG_UINT *plen)
1245 /****************************************************************************
1246 Do a SMBgetattrE call.
1247 ****************************************************************************/
1249 bool cli_getattrE(struct cli_state *cli, int fd,
1250 uint16 *attr, SMB_OFF_T *size,
1251 time_t *change_time,
1252 time_t *access_time,
1255 memset(cli->outbuf,'\0',smb_size);
1256 memset(cli->inbuf,'\0',smb_size);
1258 set_message(cli->outbuf,1,0,True);
1260 SCVAL(cli->outbuf,smb_com,SMBgetattrE);
1261 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1262 cli_setup_packet(cli);
1264 SSVAL(cli->outbuf,smb_vwv0,fd);
1267 if (!cli_receive_smb(cli)) {
1271 if (cli_is_error(cli)) {
1276 *size = IVAL(cli->inbuf, smb_vwv6);
1280 *attr = SVAL(cli->inbuf,smb_vwv10);
1284 *change_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv0);
1288 *access_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv2);
1292 *write_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv4);
1298 /****************************************************************************
1300 ****************************************************************************/
1302 bool cli_getatr(struct cli_state *cli, const char *fname,
1303 uint16 *attr, SMB_OFF_T *size, time_t *write_time)
1307 memset(cli->outbuf,'\0',smb_size);
1308 memset(cli->inbuf,'\0',smb_size);
1310 set_message(cli->outbuf,0,0,True);
1312 SCVAL(cli->outbuf,smb_com,SMBgetatr);
1313 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1314 cli_setup_packet(cli);
1316 p = smb_buf(cli->outbuf);
1318 p += clistr_push(cli, p, fname,
1319 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
1321 cli_setup_bcc(cli, p);
1324 if (!cli_receive_smb(cli)) {
1328 if (cli_is_error(cli)) {
1333 *size = IVAL(cli->inbuf, smb_vwv3);
1337 *write_time = cli_make_unix_date3(cli, cli->inbuf+smb_vwv1);
1341 *attr = SVAL(cli->inbuf,smb_vwv0);
1347 /****************************************************************************
1348 Do a SMBsetattrE call.
1349 ****************************************************************************/
1351 bool cli_setattrE(struct cli_state *cli, int fd,
1359 memset(cli->outbuf,'\0',smb_size);
1360 memset(cli->inbuf,'\0',smb_size);
1362 set_message(cli->outbuf,7,0,True);
1364 SCVAL(cli->outbuf,smb_com,SMBsetattrE);
1365 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1366 cli_setup_packet(cli);
1368 SSVAL(cli->outbuf,smb_vwv0, fd);
1369 cli_put_dos_date2(cli, cli->outbuf,smb_vwv1, change_time);
1370 cli_put_dos_date2(cli, cli->outbuf,smb_vwv3, access_time);
1371 cli_put_dos_date2(cli, cli->outbuf,smb_vwv5, write_time);
1373 p = smb_buf(cli->outbuf);
1376 cli_setup_bcc(cli, p);
1379 if (!cli_receive_smb(cli)) {
1383 if (cli_is_error(cli)) {
1390 /****************************************************************************
1391 Do a SMBsetatr call.
1392 ****************************************************************************/
1394 bool cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
1398 memset(cli->outbuf,'\0',smb_size);
1399 memset(cli->inbuf,'\0',smb_size);
1401 set_message(cli->outbuf,8,0,True);
1403 SCVAL(cli->outbuf,smb_com,SMBsetatr);
1404 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1405 cli_setup_packet(cli);
1407 SSVAL(cli->outbuf,smb_vwv0, attr);
1408 cli_put_dos_date3(cli, cli->outbuf,smb_vwv1, t);
1410 p = smb_buf(cli->outbuf);
1412 p += clistr_push(cli, p, fname,
1413 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
1416 cli_setup_bcc(cli, p);
1419 if (!cli_receive_smb(cli)) {
1423 if (cli_is_error(cli)) {
1430 /****************************************************************************
1431 Check for existance of a dir.
1432 ****************************************************************************/
1434 bool cli_chkpath(struct cli_state *cli, const char *path)
1438 TALLOC_CTX *frame = talloc_stackframe();
1440 path2 = talloc_strdup(frame, path);
1445 trim_char(path2,'\0','\\');
1447 path2 = talloc_strdup(frame, "\\");
1454 memset(cli->outbuf,'\0',smb_size);
1455 set_message(cli->outbuf,0,0,True);
1456 SCVAL(cli->outbuf,smb_com,SMBcheckpath);
1457 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1458 cli_setup_packet(cli);
1459 p = smb_buf(cli->outbuf);
1461 p += clistr_push(cli, p, path2,
1462 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
1464 cli_setup_bcc(cli, p);
1467 if (!cli_receive_smb(cli)) {
1474 if (cli_is_error(cli)) return False;
1479 /****************************************************************************
1481 ****************************************************************************/
1483 bool cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
1485 memset(cli->outbuf,'\0',smb_size);
1486 set_message(cli->outbuf,0,0,True);
1487 SCVAL(cli->outbuf,smb_com,SMBdskattr);
1488 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1489 cli_setup_packet(cli);
1492 if (!cli_receive_smb(cli)) {
1496 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
1497 *total = SVAL(cli->inbuf,smb_vwv0);
1498 *avail = SVAL(cli->inbuf,smb_vwv3);
1503 /****************************************************************************
1504 Create and open a temporary file.
1505 ****************************************************************************/
1507 int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
1512 memset(cli->outbuf,'\0',smb_size);
1513 memset(cli->inbuf,'\0',smb_size);
1515 set_message(cli->outbuf,3,0,True);
1517 SCVAL(cli->outbuf,smb_com,SMBctemp);
1518 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1519 cli_setup_packet(cli);
1521 SSVAL(cli->outbuf,smb_vwv0,0);
1522 SIVALS(cli->outbuf,smb_vwv1,-1);
1524 p = smb_buf(cli->outbuf);
1526 p += clistr_push(cli, p, path,
1527 cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
1529 cli_setup_bcc(cli, p);
1532 if (!cli_receive_smb(cli)) {
1536 if (cli_is_error(cli)) {
1540 /* despite the spec, the result has a -1, followed by
1541 length, followed by name */
1542 p = smb_buf(cli->inbuf);
1544 len = smb_buflen(cli->inbuf) - 4;
1545 if (len <= 0 || len > PATH_MAX) return -1;
1548 char *path2 = SMB_MALLOC_ARRAY(char, len+1);
1552 clistr_pull(cli, path2, p,
1553 len+1, len, STR_ASCII);
1557 return SVAL(cli->inbuf,smb_vwv0);
1561 send a raw ioctl - used by the torture code
1563 NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *blob)
1565 memset(cli->outbuf,'\0',smb_size);
1566 memset(cli->inbuf,'\0',smb_size);
1568 set_message(cli->outbuf, 3, 0, True);
1569 SCVAL(cli->outbuf,smb_com,SMBioctl);
1570 cli_setup_packet(cli);
1572 SSVAL(cli->outbuf, smb_vwv0, fnum);
1573 SSVAL(cli->outbuf, smb_vwv1, code>>16);
1574 SSVAL(cli->outbuf, smb_vwv2, (code&0xFFFF));
1577 if (!cli_receive_smb(cli)) {
1578 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1581 if (cli_is_error(cli)) {
1582 return cli_nt_error(cli);
1585 *blob = data_blob_null;
1587 return NT_STATUS_OK;
1590 /*********************************************************
1591 Set an extended attribute utility fn.
1592 *********************************************************/
1594 static bool cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigned int param_len,
1595 const char *ea_name, const char *ea_val, size_t ea_len)
1597 unsigned int data_len = 0;
1599 char *rparam=NULL, *rdata=NULL;
1601 size_t ea_namelen = strlen(ea_name);
1603 if (ea_namelen == 0 && ea_len == 0) {
1605 data = (char *)SMB_MALLOC(data_len);
1610 SIVAL(p,0,data_len);
1612 data_len = 4 + 4 + ea_namelen + 1 + ea_len;
1613 data = (char *)SMB_MALLOC(data_len);
1618 SIVAL(p,0,data_len);
1620 SCVAL(p, 0, 0); /* EA flags. */
1621 SCVAL(p, 1, ea_namelen);
1622 SSVAL(p, 2, ea_len);
1623 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
1624 memcpy(p+4+ea_namelen+1, ea_val, ea_len);
1627 if (!cli_send_trans(cli, SMBtrans2,
1629 -1, 0, /* fid, flags */
1630 &setup, 1, 0, /* setup, length, max */
1631 param, param_len, 2, /* param, length, max */
1632 data, data_len, cli->max_xmit /* data, length, max */
1638 if (!cli_receive_trans(cli, SMBtrans2,
1639 &rparam, ¶m_len,
1640 &rdata, &data_len)) {
1652 /*********************************************************
1653 Set an extended attribute on a pathname.
1654 *********************************************************/
1656 bool cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len)
1658 uint16 setup = TRANSACT2_SETPATHINFO;
1659 unsigned int param_len = 0;
1661 size_t srclen = 2*(strlen(path)+1);
1665 param = SMB_MALLOC(6+srclen+2);
1669 memset(param, '\0', 6);
1670 SSVAL(param,0,SMB_INFO_SET_EA);
1673 p += clistr_push(cli, p, path, srclen, STR_TERMINATE);
1674 param_len = PTR_DIFF(p, param);
1676 ret = cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len);
1681 /*********************************************************
1682 Set an extended attribute on an fnum.
1683 *********************************************************/
1685 bool cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const char *ea_val, size_t ea_len)
1688 uint16 setup = TRANSACT2_SETFILEINFO;
1690 memset(param, 0, 6);
1691 SSVAL(param,0,fnum);
1692 SSVAL(param,2,SMB_INFO_SET_EA);
1694 return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len);
1697 /*********************************************************
1698 Get an extended attribute list tility fn.
1699 *********************************************************/
1701 static bool cli_get_ea_list(struct cli_state *cli,
1702 uint16 setup, char *param, unsigned int param_len,
1705 struct ea_struct **pea_list)
1707 unsigned int data_len = 0;
1708 unsigned int rparam_len, rdata_len;
1709 char *rparam=NULL, *rdata=NULL;
1714 struct ea_struct *ea_list;
1721 if (!cli_send_trans(cli, SMBtrans2,
1723 -1, 0, /* fid, flags */
1724 &setup, 1, 0, /* setup, length, max */
1725 param, param_len, 10, /* param, length, max */
1726 NULL, data_len, cli->max_xmit /* data, length, max */
1731 if (!cli_receive_trans(cli, SMBtrans2,
1732 &rparam, &rparam_len,
1733 &rdata, &rdata_len)) {
1737 if (!rdata || rdata_len < 4) {
1741 ea_size = (size_t)IVAL(rdata,0);
1742 if (ea_size > rdata_len) {
1747 /* No EA's present. */
1755 /* Validate the EA list and count it. */
1756 for (num_eas = 0; ea_size >= 4; num_eas++) {
1757 unsigned int ea_namelen = CVAL(p,1);
1758 unsigned int ea_valuelen = SVAL(p,2);
1759 if (ea_namelen == 0) {
1762 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
1765 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
1766 p += 4 + ea_namelen + 1 + ea_valuelen;
1774 *pnum_eas = num_eas;
1776 /* Caller only wants number of EA's. */
1781 ea_list = TALLOC_ARRAY(ctx, struct ea_struct, num_eas);
1786 ea_size = (size_t)IVAL(rdata,0);
1789 for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
1790 struct ea_struct *ea = &ea_list[num_eas];
1791 fstring unix_ea_name;
1792 unsigned int ea_namelen = CVAL(p,1);
1793 unsigned int ea_valuelen = SVAL(p,2);
1795 ea->flags = CVAL(p,0);
1796 unix_ea_name[0] = '\0';
1797 pull_ascii_fstring(unix_ea_name, p + 4);
1798 ea->name = talloc_strdup(ctx, unix_ea_name);
1799 /* Ensure the value is null terminated (in case it's a string). */
1800 ea->value = data_blob_talloc(ctx, NULL, ea_valuelen + 1);
1801 if (!ea->value.data) {
1805 memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
1807 ea->value.data[ea_valuelen] = 0;
1809 p += 4 + ea_namelen + 1 + ea_valuelen;
1812 *pea_list = ea_list;
1822 /*********************************************************
1823 Get an extended attribute list from a pathname.
1824 *********************************************************/
1826 bool cli_get_ea_list_path(struct cli_state *cli, const char *path,
1829 struct ea_struct **pea_list)
1831 uint16 setup = TRANSACT2_QPATHINFO;
1832 unsigned int param_len = 0;
1835 size_t srclen = 2*(strlen(path)+1);
1838 param = SMB_MALLOC(6+srclen+2);
1844 SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS);
1846 p += clistr_push(cli, p, path, srclen, STR_TERMINATE);
1847 param_len = PTR_DIFF(p, param);
1849 ret = cli_get_ea_list(cli, setup, param, param_len, ctx, pnum_eas, pea_list);
1854 /*********************************************************
1855 Get an extended attribute list from an fnum.
1856 *********************************************************/
1858 bool cli_get_ea_list_fnum(struct cli_state *cli, int fnum,
1861 struct ea_struct **pea_list)
1863 uint16 setup = TRANSACT2_QFILEINFO;
1866 memset(param, 0, 6);
1867 SSVAL(param,0,fnum);
1868 SSVAL(param,2,SMB_INFO_SET_EA);
1870 return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
1873 /****************************************************************************
1874 Convert open "flags" arg to uint32 on wire.
1875 ****************************************************************************/
1877 static uint32 open_flags_to_wire(int flags)
1879 int open_mode = flags & O_ACCMODE;
1882 switch (open_mode) {
1884 ret |= SMB_O_WRONLY;
1891 ret |= SMB_O_RDONLY;
1895 if (flags & O_CREAT) {
1898 if (flags & O_EXCL) {
1901 if (flags & O_TRUNC) {
1905 if (flags & O_SYNC) {
1909 if (flags & O_APPEND) {
1910 ret |= SMB_O_APPEND;
1912 #if defined(O_DIRECT)
1913 if (flags & O_DIRECT) {
1914 ret |= SMB_O_DIRECT;
1917 #if defined(O_DIRECTORY)
1918 if (flags & O_DIRECTORY) {
1919 ret &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
1920 ret |= SMB_O_DIRECTORY;
1926 /****************************************************************************
1927 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
1928 ****************************************************************************/
1930 static int cli_posix_open_internal(struct cli_state *cli, const char *fname, int flags, mode_t mode, bool is_dir)
1932 unsigned int data_len = 0;
1933 unsigned int param_len = 0;
1934 uint16 setup = TRANSACT2_SETPATHINFO;
1937 char *rparam=NULL, *rdata=NULL;
1940 uint32 wire_flags = open_flags_to_wire(flags);
1941 size_t srclen = 2*(strlen(fname)+1);
1943 param = SMB_MALLOC(6+srclen+2);
1947 memset(param, '\0', 6);
1948 SSVAL(param,0, SMB_POSIX_PATH_OPEN);
1951 p += clistr_push(cli, p, fname, srclen, STR_TERMINATE);
1952 param_len = PTR_DIFF(p, param);
1955 wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
1956 wire_flags |= SMB_O_DIRECTORY;
1960 SIVAL(p,0,0); /* No oplock. */
1961 SIVAL(p,4,wire_flags);
1962 SIVAL(p,8,unix_perms_to_wire(mode));
1963 SIVAL(p,12,0); /* Top bits of perms currently undefined. */
1964 SSVAL(p,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
1968 if (!cli_send_trans(cli, SMBtrans2,
1970 -1, 0, /* fid, flags */
1971 &setup, 1, 0, /* setup, length, max */
1972 param, param_len, 2, /* param, length, max */
1973 (char *)&data, data_len, cli->max_xmit /* data, length, max */
1981 if (!cli_receive_trans(cli, SMBtrans2,
1982 &rparam, ¶m_len,
1983 &rdata, &data_len)) {
1987 fnum = SVAL(rdata,2);
1995 /****************************************************************************
1996 open - POSIX semantics.
1997 ****************************************************************************/
1999 int cli_posix_open(struct cli_state *cli, const char *fname, int flags, mode_t mode)
2001 return cli_posix_open_internal(cli, fname, flags, mode, False);
2004 /****************************************************************************
2005 mkdir - POSIX semantics.
2006 ****************************************************************************/
2008 int cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
2010 return (cli_posix_open_internal(cli, fname, O_CREAT, mode, True) == -1) ? -1 : 0;
2013 /****************************************************************************
2014 unlink or rmdir - POSIX semantics.
2015 ****************************************************************************/
2017 static bool cli_posix_unlink_internal(struct cli_state *cli, const char *fname, bool is_dir)
2019 unsigned int data_len = 0;
2020 unsigned int param_len = 0;
2021 uint16 setup = TRANSACT2_SETPATHINFO;
2024 char *rparam=NULL, *rdata=NULL;
2026 size_t srclen = 2*(strlen(fname)+1);
2028 param = SMB_MALLOC(6+srclen+2);
2032 memset(param, '\0', 6);
2033 SSVAL(param,0, SMB_POSIX_PATH_UNLINK);
2036 p += clistr_push(cli, p, fname, srclen, STR_TERMINATE);
2037 param_len = PTR_DIFF(p, param);
2039 SSVAL(data, 0, is_dir ? SMB_POSIX_UNLINK_DIRECTORY_TARGET :
2040 SMB_POSIX_UNLINK_FILE_TARGET);
2043 if (!cli_send_trans(cli, SMBtrans2,
2045 -1, 0, /* fid, flags */
2046 &setup, 1, 0, /* setup, length, max */
2047 param, param_len, 2, /* param, length, max */
2048 (char *)&data, data_len, cli->max_xmit /* data, length, max */
2056 if (!cli_receive_trans(cli, SMBtrans2,
2057 &rparam, ¶m_len,
2058 &rdata, &data_len)) {
2068 /****************************************************************************
2069 unlink - POSIX semantics.
2070 ****************************************************************************/
2072 bool cli_posix_unlink(struct cli_state *cli, const char *fname)
2074 return cli_posix_unlink_internal(cli, fname, False);
2077 /****************************************************************************
2078 rmdir - POSIX semantics.
2079 ****************************************************************************/
2081 int cli_posix_rmdir(struct cli_state *cli, const char *fname)
2083 return cli_posix_unlink_internal(cli, fname, True);