2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct *conn,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
44 const SMB_STRUCT_STAT *psbuf);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
53 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type = get_remote_arch();
57 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58 val = SMB_ROUNDUP(val,rval);
63 /********************************************************************
64 Given a stat buffer return the allocated size on disk, taking into
66 ********************************************************************/
68 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
72 if(S_ISDIR(sbuf->st_mode)) {
76 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
77 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
79 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
82 if (fsp && fsp->initial_allocation_size)
83 ret = MAX(ret,fsp->initial_allocation_size);
85 return smb_roundup(conn, ret);
88 /****************************************************************************
89 Utility functions for dealing with extended attributes.
90 ****************************************************************************/
92 /****************************************************************************
93 Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
96 static bool samba_private_attr_name(const char *unix_ea_name)
98 static const char *prohibited_ea_names[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME,
100 SAMBA_XATTR_DOS_ATTRIB,
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
110 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
111 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
117 /****************************************************************************
118 Get one EA value. Fill in a struct ea_struct.
119 ****************************************************************************/
121 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
122 files_struct *fsp, const char *fname,
123 const char *ea_name, struct ea_struct *pea)
125 /* Get the value of this xattr. Max size is 64k. */
126 size_t attr_size = 256;
132 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 return NT_STATUS_NO_MEMORY;
137 if (fsp && fsp->fh->fd != -1) {
138 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
140 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
143 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
149 return map_nt_error_from_unix(errno);
152 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
153 dump_data(10, (uint8 *)val, sizeret);
156 if (strnequal(ea_name, "user.", 5)) {
157 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
159 pea->name = talloc_strdup(mem_ctx, ea_name);
161 if (pea->name == NULL) {
163 return NT_STATUS_NO_MEMORY;
165 pea->value.data = (unsigned char *)val;
166 pea->value.length = (size_t)sizeret;
170 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
171 files_struct *fsp, const char *fname,
172 char ***pnames, size_t *pnum_names)
174 /* Get a list of all xattrs. Max namesize is 64k. */
175 size_t ea_namelist_size = 1024;
176 char *ea_namelist = NULL;
183 if (!lp_ea_support(SNUM(conn))) {
190 * TALLOC the result early to get the talloc hierarchy right.
193 names = TALLOC_ARRAY(mem_ctx, char *, 1);
195 DEBUG(0, ("talloc failed\n"));
196 return NT_STATUS_NO_MEMORY;
199 while (ea_namelist_size <= 65536) {
201 ea_namelist = TALLOC_REALLOC_ARRAY(
202 names, ea_namelist, char, ea_namelist_size);
203 if (ea_namelist == NULL) {
204 DEBUG(0, ("talloc failed\n"));
206 return NT_STATUS_NO_MEMORY;
209 if (fsp && fsp->fh->fd != -1) {
210 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
213 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
217 if ((sizeret == -1) && (errno == ERANGE)) {
218 ea_namelist_size *= 2;
227 return map_nt_error_from_unix(errno);
230 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
231 (unsigned int)sizeret));
241 * Ensure the result is 0-terminated
244 if (ea_namelist[sizeret-1] != '\0') {
246 return NT_STATUS_INTERNAL_ERROR;
254 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
258 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
260 DEBUG(0, ("talloc failed\n"));
262 return NT_STATUS_NO_MEMORY;
268 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
269 names[num_names++] = p;
273 *pnum_names = num_names;
277 /****************************************************************************
278 Return a linked list of the total EA's. Plus the total size
279 ****************************************************************************/
281 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
282 const char *fname, size_t *pea_total_len)
284 /* Get a list of all xattrs. Max namesize is 64k. */
287 struct ea_list *ea_list_head = NULL;
292 if (!lp_ea_support(SNUM(conn))) {
296 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
299 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
303 for (i=0; i<num_names; i++) {
304 struct ea_list *listp;
307 if (strnequal(names[i], "system.", 7)
308 || samba_private_attr_name(names[i]))
311 listp = TALLOC_P(mem_ctx, struct ea_list);
316 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
322 push_ascii_fstring(dos_ea_name, listp->ea.name);
325 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
327 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
328 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
329 (unsigned int)listp->ea.value.length));
331 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
335 /* Add on 4 for total length. */
336 if (*pea_total_len) {
340 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
341 (unsigned int)*pea_total_len));
346 /****************************************************************************
347 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
349 ****************************************************************************/
351 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
352 connection_struct *conn, struct ea_list *ea_list)
354 unsigned int ret_data_size = 4;
357 SMB_ASSERT(total_data_size >= 4);
359 if (!lp_ea_support(SNUM(conn))) {
364 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
367 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
368 dos_namelen = strlen(dos_ea_name);
369 if (dos_namelen > 255 || dos_namelen == 0) {
372 if (ea_list->ea.value.length > 65535) {
375 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
379 /* We know we have room. */
380 SCVAL(p,0,ea_list->ea.flags);
381 SCVAL(p,1,dos_namelen);
382 SSVAL(p,2,ea_list->ea.value.length);
383 fstrcpy(p+4, dos_ea_name);
384 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
386 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
387 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
390 ret_data_size = PTR_DIFF(p, pdata);
391 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
392 SIVAL(pdata,0,ret_data_size);
393 return ret_data_size;
396 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
398 size_t total_ea_len = 0;
399 TALLOC_CTX *mem_ctx = NULL;
401 if (!lp_ea_support(SNUM(conn))) {
404 mem_ctx = talloc_tos();
405 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
409 /****************************************************************************
410 Ensure the EA name is case insensitive by matching any existing EA name.
411 ****************************************************************************/
413 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
416 TALLOC_CTX *mem_ctx = talloc_tos();
417 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
419 for (; ea_list; ea_list = ea_list->next) {
420 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
421 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
422 &unix_ea_name[5], ea_list->ea.name));
423 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
429 /****************************************************************************
430 Set or delete an extended attribute.
431 ****************************************************************************/
433 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
435 if (!lp_ea_support(SNUM(conn))) {
436 return NT_STATUS_EAS_NOT_SUPPORTED;
439 for (;ea_list; ea_list = ea_list->next) {
441 fstring unix_ea_name;
443 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
444 fstrcat(unix_ea_name, ea_list->ea.name);
446 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
448 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
450 if (samba_private_attr_name(unix_ea_name)) {
451 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
452 return NT_STATUS_ACCESS_DENIED;
455 if (ea_list->ea.value.length == 0) {
456 /* Remove the attribute. */
457 if (fsp && (fsp->fh->fd != -1)) {
458 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
459 unix_ea_name, fsp->fsp_name));
460 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
462 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
463 unix_ea_name, fname));
464 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
467 /* Removing a non existent attribute always succeeds. */
468 if (ret == -1 && errno == ENOATTR) {
469 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
475 if (fsp && (fsp->fh->fd != -1)) {
476 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
477 unix_ea_name, fsp->fsp_name));
478 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
479 ea_list->ea.value.data, ea_list->ea.value.length, 0);
481 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
482 unix_ea_name, fname));
483 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
484 ea_list->ea.value.data, ea_list->ea.value.length, 0);
490 if (errno == ENOTSUP) {
491 return NT_STATUS_EAS_NOT_SUPPORTED;
494 return map_nt_error_from_unix(errno);
500 /****************************************************************************
501 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
502 ****************************************************************************/
504 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
506 struct ea_list *ea_list_head = NULL;
509 while (offset + 2 < data_size) {
510 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
511 unsigned int namelen = CVAL(pdata,offset);
513 offset++; /* Go past the namelen byte. */
515 /* integer wrap paranioa. */
516 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
517 (offset > data_size) || (namelen > data_size) ||
518 (offset + namelen >= data_size)) {
521 /* Ensure the name is null terminated. */
522 if (pdata[offset + namelen] != '\0') {
525 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
530 offset += (namelen + 1); /* Go past the name + terminating zero. */
531 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
532 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
538 /****************************************************************************
539 Read one EA list entry from the buffer.
540 ****************************************************************************/
542 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
544 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
546 unsigned int namelen;
556 eal->ea.flags = CVAL(pdata,0);
557 namelen = CVAL(pdata,1);
558 val_len = SVAL(pdata,2);
560 if (4 + namelen + 1 + val_len > data_size) {
564 /* Ensure the name is null terminated. */
565 if (pdata[namelen + 4] != '\0') {
568 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
573 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
574 if (!eal->ea.value.data) {
578 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
580 /* Ensure we're null terminated just in case we print the value. */
581 eal->ea.value.data[val_len] = '\0';
582 /* But don't count the null. */
583 eal->ea.value.length--;
586 *pbytes_used = 4 + namelen + 1 + val_len;
589 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
590 dump_data(10, eal->ea.value.data, eal->ea.value.length);
595 /****************************************************************************
596 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
597 ****************************************************************************/
599 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
601 struct ea_list *ea_list_head = NULL;
603 size_t bytes_used = 0;
605 while (offset < data_size) {
606 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
612 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
613 offset += bytes_used;
619 /****************************************************************************
620 Count the total EA size needed.
621 ****************************************************************************/
623 static size_t ea_list_size(struct ea_list *ealist)
626 struct ea_list *listp;
629 for (listp = ealist; listp; listp = listp->next) {
630 push_ascii_fstring(dos_ea_name, listp->ea.name);
631 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
633 /* Add on 4 for total length. */
641 /****************************************************************************
642 Return a union of EA's from a file list and a list of names.
643 The TALLOC context for the two lists *MUST* be identical as we steal
644 memory from one list to add to another. JRA.
645 ****************************************************************************/
647 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
649 struct ea_list *nlistp, *flistp;
651 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
652 for (flistp = file_list; flistp; flistp = flistp->next) {
653 if (strequal(nlistp->ea.name, flistp->ea.name)) {
659 /* Copy the data from this entry. */
660 nlistp->ea.flags = flistp->ea.flags;
661 nlistp->ea.value = flistp->ea.value;
664 nlistp->ea.flags = 0;
665 ZERO_STRUCT(nlistp->ea.value);
669 *total_ea_len = ea_list_size(name_list);
673 /****************************************************************************
674 Send the required number of replies back.
675 We assume all fields other than the data fields are
676 set correctly for the type of call.
677 HACK ! Always assumes smb_setup field is zero.
678 ****************************************************************************/
680 void send_trans2_replies(connection_struct *conn,
681 struct smb_request *req,
688 /* As we are using a protocol > LANMAN1 then the max_send
689 variable must have been set in the sessetupX call.
690 This takes precedence over the max_xmit field in the
691 global struct. These different max_xmit variables should
692 be merged as this is now too confusing */
694 int data_to_send = datasize;
695 int params_to_send = paramsize;
697 const char *pp = params;
698 const char *pd = pdata;
699 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
700 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
701 int data_alignment_offset = 0;
702 bool overflow = False;
704 /* Modify the data_to_send and datasize and set the error if
705 we're trying to send more than max_data_bytes. We still send
706 the part of the packet(s) that fit. Strange, but needed
709 if (max_data_bytes > 0 && datasize > max_data_bytes) {
710 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
711 max_data_bytes, datasize ));
712 datasize = data_to_send = max_data_bytes;
716 /* If there genuinely are no parameters or data to send just send the empty packet */
718 if(params_to_send == 0 && data_to_send == 0) {
719 reply_outbuf(req, 10, 0);
720 show_msg((char *)req->outbuf);
724 /* When sending params and data ensure that both are nicely aligned */
725 /* Only do this alignment when there is also data to send - else
726 can cause NT redirector problems. */
728 if (((params_to_send % 4) != 0) && (data_to_send != 0))
729 data_alignment_offset = 4 - (params_to_send % 4);
731 /* Space is bufsize minus Netbios over TCP header minus SMB header */
732 /* The alignment_offset is to align the param bytes on an even byte
733 boundary. NT 4.0 Beta needs this to work correctly. */
735 useable_space = max_send - (smb_size
738 + data_alignment_offset);
740 /* useable_space can never be more than max_send minus the alignment offset. */
742 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
744 while (params_to_send || data_to_send) {
745 /* Calculate whether we will totally or partially fill this packet */
747 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
749 /* We can never send more than useable_space */
751 * Note that 'useable_space' does not include the alignment offsets,
752 * but we must include the alignment offsets in the calculation of
753 * the length of the data we send over the wire, as the alignment offsets
754 * are sent here. Fix from Marc_Jacobsen@hp.com.
757 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
759 reply_outbuf(req, 10, total_sent_thistime);
761 /* Set total params and data to be sent */
762 SSVAL(req->outbuf,smb_tprcnt,paramsize);
763 SSVAL(req->outbuf,smb_tdrcnt,datasize);
765 /* Calculate how many parameters and data we can fit into
766 * this packet. Parameters get precedence
769 params_sent_thistime = MIN(params_to_send,useable_space);
770 data_sent_thistime = useable_space - params_sent_thistime;
771 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
773 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
775 /* smb_proff is the offset from the start of the SMB header to the
776 parameter bytes, however the first 4 bytes of outbuf are
777 the Netbios over TCP header. Thus use smb_base() to subtract
778 them from the calculation */
780 SSVAL(req->outbuf,smb_proff,
781 ((smb_buf(req->outbuf)+alignment_offset)
782 - smb_base(req->outbuf)));
784 if(params_sent_thistime == 0)
785 SSVAL(req->outbuf,smb_prdisp,0);
787 /* Absolute displacement of param bytes sent in this packet */
788 SSVAL(req->outbuf,smb_prdisp,pp - params);
790 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
791 if(data_sent_thistime == 0) {
792 SSVAL(req->outbuf,smb_droff,0);
793 SSVAL(req->outbuf,smb_drdisp, 0);
795 /* The offset of the data bytes is the offset of the
796 parameter bytes plus the number of parameters being sent this time */
797 SSVAL(req->outbuf, smb_droff,
798 ((smb_buf(req->outbuf)+alignment_offset)
799 - smb_base(req->outbuf))
800 + params_sent_thistime + data_alignment_offset);
801 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
804 /* Initialize the padding for alignment */
806 if (alignment_offset != 0) {
807 memset(smb_buf(req->outbuf), 0, alignment_offset);
810 /* Copy the param bytes into the packet */
812 if(params_sent_thistime) {
813 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
814 params_sent_thistime);
817 /* Copy in the data bytes */
818 if(data_sent_thistime) {
819 if (data_alignment_offset != 0) {
820 memset((smb_buf(req->outbuf)+alignment_offset+
821 params_sent_thistime), 0,
822 data_alignment_offset);
824 memcpy(smb_buf(req->outbuf)+alignment_offset
825 +params_sent_thistime+data_alignment_offset,
826 pd,data_sent_thistime);
829 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
830 params_sent_thistime, data_sent_thistime, useable_space));
831 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
832 params_to_send, data_to_send, paramsize, datasize));
835 error_packet_set((char *)req->outbuf,
836 ERRDOS,ERRbufferoverflow,
837 STATUS_BUFFER_OVERFLOW,
841 /* Send the packet */
842 show_msg((char *)req->outbuf);
843 if (!srv_send_smb(smbd_server_fd(),
845 IS_CONN_ENCRYPTED(conn)))
846 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
848 TALLOC_FREE(req->outbuf);
850 pp += params_sent_thistime;
851 pd += data_sent_thistime;
853 params_to_send -= params_sent_thistime;
854 data_to_send -= data_sent_thistime;
857 if(params_to_send < 0 || data_to_send < 0) {
858 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
859 params_to_send, data_to_send));
867 /****************************************************************************
868 Reply to a TRANSACT2_OPEN.
869 ****************************************************************************/
871 static void call_trans2open(connection_struct *conn,
872 struct smb_request *req,
873 char **pparams, int total_params,
874 char **ppdata, int total_data,
875 unsigned int max_data_bytes)
877 char *params = *pparams;
878 char *pdata = *ppdata;
883 bool return_additional_info;
894 SMB_STRUCT_STAT sbuf;
897 struct ea_list *ea_list = NULL;
902 uint32 create_disposition;
903 uint32 create_options = 0;
904 TALLOC_CTX *ctx = talloc_tos();
907 * Ensure we have enough parameters to perform the operation.
910 if (total_params < 29) {
911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
915 flags = SVAL(params, 0);
916 deny_mode = SVAL(params, 2);
917 open_attr = SVAL(params,6);
918 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
919 if (oplock_request) {
920 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
924 return_additional_info = BITSETW(params,0);
925 open_sattr = SVAL(params, 4);
926 open_time = make_unix_date3(params+8);
928 open_ofun = SVAL(params,12);
929 open_size = IVAL(params,14);
933 reply_doserror(req, ERRSRV, ERRaccess);
937 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
938 total_params - 28, STR_TERMINATE,
940 if (!NT_STATUS_IS_OK(status)) {
941 reply_nterror(req, status);
945 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
946 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
947 (unsigned int)open_ofun, open_size));
949 if (open_ofun == 0) {
950 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
954 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
959 reply_doserror(req, ERRDOS, ERRbadaccess);
963 /* Any data in this call is an EA list. */
964 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
965 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
969 if (total_data != 4) {
970 if (total_data < 10) {
971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
975 if (IVAL(pdata,0) > total_data) {
976 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
977 IVAL(pdata,0), (unsigned int)total_data));
978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 ea_list = read_ea_list(talloc_tos(), pdata + 4,
985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
988 } else if (IVAL(pdata,0) != 4) {
989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
993 status = create_file(conn, /* conn */
995 0, /* root_dir_fid */
997 access_mask, /* access_mask */
998 share_mode, /* share_access */
999 create_disposition, /* create_disposition*/
1000 create_options, /* create_options */
1001 open_attr, /* file_attributes */
1002 oplock_request, /* oplock_request */
1003 open_size, /* allocation_size */
1005 ea_list, /* ea_list */
1007 &smb_action, /* pinfo */
1010 if (!NT_STATUS_IS_OK(status)) {
1011 if (open_was_deferred(req->mid)) {
1012 /* We have re-scheduled this call. */
1015 reply_openerror(req, status);
1019 size = get_file_size(sbuf);
1020 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1021 mtime = sbuf.st_mtime;
1022 inode = sbuf.st_ino;
1024 close_file(fsp,ERROR_CLOSE);
1025 reply_doserror(req, ERRDOS,ERRnoaccess);
1029 /* Realloc the size of parameters and data we will return */
1030 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1031 if(*pparams == NULL ) {
1032 reply_nterror(req, NT_STATUS_NO_MEMORY);
1037 SSVAL(params,0,fsp->fnum);
1038 SSVAL(params,2,fattr);
1039 srv_put_dos_date2(params,4, mtime);
1040 SIVAL(params,8, (uint32)size);
1041 SSVAL(params,12,deny_mode);
1042 SSVAL(params,14,0); /* open_type - file or directory. */
1043 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1045 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1046 smb_action |= EXTENDED_OPLOCK_GRANTED;
1049 SSVAL(params,18,smb_action);
1052 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1054 SIVAL(params,20,inode);
1055 SSVAL(params,24,0); /* Padding. */
1057 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1058 SIVAL(params, 26, ea_size);
1060 SIVAL(params, 26, 0);
1063 /* Send the required number of replies */
1064 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1067 /*********************************************************
1068 Routine to check if a given string matches exactly.
1069 as a special case a mask of "." does NOT match. That
1070 is required for correct wildcard semantics
1071 Case can be significant or not.
1072 **********************************************************/
1074 static bool exact_match(connection_struct *conn,
1078 if (mask[0] == '.' && mask[1] == 0)
1080 if (conn->case_sensitive)
1081 return strcmp(str,mask)==0;
1082 if (StrCaseCmp(str,mask) != 0) {
1085 if (dptr_has_wild(conn->dirptr)) {
1091 /****************************************************************************
1092 Return the filetype for UNIX extensions.
1093 ****************************************************************************/
1095 static uint32 unix_filetype(mode_t mode)
1098 return UNIX_TYPE_FILE;
1099 else if(S_ISDIR(mode))
1100 return UNIX_TYPE_DIR;
1102 else if(S_ISLNK(mode))
1103 return UNIX_TYPE_SYMLINK;
1106 else if(S_ISCHR(mode))
1107 return UNIX_TYPE_CHARDEV;
1110 else if(S_ISBLK(mode))
1111 return UNIX_TYPE_BLKDEV;
1114 else if(S_ISFIFO(mode))
1115 return UNIX_TYPE_FIFO;
1118 else if(S_ISSOCK(mode))
1119 return UNIX_TYPE_SOCKET;
1122 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1123 return UNIX_TYPE_UNKNOWN;
1126 /****************************************************************************
1127 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1128 ****************************************************************************/
1130 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1132 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1133 SMB_STRUCT_STAT *psbuf,
1135 enum perm_type ptype,
1140 if (perms == SMB_MODE_NO_CHANGE) {
1141 if (!VALID_STAT(*psbuf)) {
1142 return NT_STATUS_INVALID_PARAMETER;
1144 *ret_perms = psbuf->st_mode;
1145 return NT_STATUS_OK;
1149 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1150 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1151 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1152 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1153 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1154 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1155 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1156 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1157 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1159 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1162 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1165 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1170 /* Apply mode mask */
1171 ret &= lp_create_mask(SNUM(conn));
1172 /* Add in force bits */
1173 ret |= lp_force_create_mode(SNUM(conn));
1176 ret &= lp_dir_mask(SNUM(conn));
1177 /* Add in force bits */
1178 ret |= lp_force_dir_mode(SNUM(conn));
1180 case PERM_EXISTING_FILE:
1181 /* Apply mode mask */
1182 ret &= lp_security_mask(SNUM(conn));
1183 /* Add in force bits */
1184 ret |= lp_force_security_mode(SNUM(conn));
1186 case PERM_EXISTING_DIR:
1187 /* Apply mode mask */
1188 ret &= lp_dir_security_mask(SNUM(conn));
1189 /* Add in force bits */
1190 ret |= lp_force_dir_security_mode(SNUM(conn));
1195 return NT_STATUS_OK;
1198 /****************************************************************************
1199 Get a level dependent lanman2 dir entry.
1200 ****************************************************************************/
1202 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1203 connection_struct *conn,
1205 const char *path_mask,
1208 int requires_resume_key,
1213 int space_remaining,
1215 bool *got_exact_match,
1216 int *last_entry_off,
1217 struct ea_list *name_list)
1221 SMB_STRUCT_STAT sbuf;
1222 const char *mask = NULL;
1223 char *pathreal = NULL;
1224 const char *fname = NULL;
1225 char *p, *q, *pdata = *ppdata;
1229 SMB_OFF_T file_size = 0;
1230 SMB_BIG_UINT allocation_size = 0;
1232 struct timespec mdate_ts, adate_ts, create_date_ts;
1233 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1235 char *last_entry_ptr;
1237 uint32 nt_extmode; /* Used for NT connections instead of mode */
1238 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1239 bool check_mangled_names = lp_manglednames(conn->params);
1240 char mangled_name[13]; /* mangled 8.3 name. */
1242 *out_of_space = False;
1243 *got_exact_match = False;
1245 ZERO_STRUCT(mdate_ts);
1246 ZERO_STRUCT(adate_ts);
1247 ZERO_STRUCT(create_date_ts);
1249 if (!conn->dirptr) {
1253 p = strrchr_m(path_mask,'/');
1256 mask = talloc_strdup(ctx,"*.*");
1266 bool ms_dfs_link = False;
1268 /* Needed if we run out of space */
1269 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1270 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1273 * Due to bugs in NT client redirectors we are not using
1274 * resume keys any more - set them to zero.
1275 * Check out the related comments in findfirst/findnext.
1281 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1282 (long)conn->dirptr,curr_dirpos));
1289 * fname may get mangled, dname is never mangled.
1290 * Whenever we're accessing the filesystem we use
1291 * pathreal which is composed from dname.
1297 /* Mangle fname if it's an illegal name. */
1298 if (mangle_must_mangle(dname,conn->params)) {
1299 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1300 continue; /* Error - couldn't mangle. */
1302 fname = mangled_name;
1305 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1306 got_match = mask_match(fname, mask, conn->case_sensitive);
1309 if(!got_match && check_mangled_names &&
1310 !mangle_is_8_3(fname, False, conn->params)) {
1312 * It turns out that NT matches wildcards against
1313 * both long *and* short names. This may explain some
1314 * of the wildcard wierdness from old DOS clients
1315 * that some people have been seeing.... JRA.
1317 /* Force the mangling into 8.3. */
1318 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1319 continue; /* Error - couldn't mangle. */
1322 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1323 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1328 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1330 if (dont_descend && !isdots) {
1336 pathreal = talloc_asprintf(ctx,
1341 pathreal = talloc_asprintf(ctx,
1351 if (INFO_LEVEL_IS_UNIX(info_level)) {
1352 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1353 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1354 pathreal,strerror(errno)));
1355 TALLOC_FREE(pathreal);
1358 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1359 /* Needed to show the msdfs symlinks as
1362 if(lp_host_msdfs() &&
1363 lp_msdfs_root(SNUM(conn)) &&
1364 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1365 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1368 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1372 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1373 pathreal,strerror(errno)));
1374 TALLOC_FREE(pathreal);
1380 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1382 mode = dos_mode(conn,pathreal,&sbuf);
1385 if (!dir_check_ftype(conn,mode,dirtype)) {
1386 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1387 TALLOC_FREE(pathreal);
1391 if (!(mode & aDIR)) {
1392 file_size = get_file_size(sbuf);
1394 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1396 mdate_ts = get_mtimespec(&sbuf);
1397 adate_ts = get_atimespec(&sbuf);
1398 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1400 if (lp_dos_filetime_resolution(SNUM(conn))) {
1401 dos_filetime_timespec(&create_date_ts);
1402 dos_filetime_timespec(&mdate_ts);
1403 dos_filetime_timespec(&adate_ts);
1406 create_date = convert_timespec_to_time_t(create_date_ts);
1407 mdate = convert_timespec_to_time_t(mdate_ts);
1408 adate = convert_timespec_to_time_t(adate_ts);
1410 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1414 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1421 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1423 switch (info_level) {
1424 case SMB_FIND_INFO_STANDARD:
1425 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1426 if(requires_resume_key) {
1430 srv_put_dos_date2(p,0,create_date);
1431 srv_put_dos_date2(p,4,adate);
1432 srv_put_dos_date2(p,8,mdate);
1433 SIVAL(p,12,(uint32)file_size);
1434 SIVAL(p,16,(uint32)allocation_size);
1438 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1439 p += ucs2_align(base_data, p, 0);
1441 len = srvstr_push(base_data, flags2, p,
1442 fname, PTR_DIFF(end_data, p),
1444 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1446 SCVAL(nameptr, -1, len - 2);
1448 SCVAL(nameptr, -1, 0);
1452 SCVAL(nameptr, -1, len - 1);
1454 SCVAL(nameptr, -1, 0);
1460 case SMB_FIND_EA_SIZE:
1461 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1462 if(requires_resume_key) {
1466 srv_put_dos_date2(p,0,create_date);
1467 srv_put_dos_date2(p,4,adate);
1468 srv_put_dos_date2(p,8,mdate);
1469 SIVAL(p,12,(uint32)file_size);
1470 SIVAL(p,16,(uint32)allocation_size);
1473 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1474 SIVAL(p,22,ea_size); /* Extended attributes */
1478 len = srvstr_push(base_data, flags2,
1479 p, fname, PTR_DIFF(end_data, p),
1480 STR_TERMINATE | STR_NOALIGN);
1481 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1494 SCVAL(nameptr,0,len);
1496 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1499 case SMB_FIND_EA_LIST:
1501 struct ea_list *file_list = NULL;
1504 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1508 if(requires_resume_key) {
1512 srv_put_dos_date2(p,0,create_date);
1513 srv_put_dos_date2(p,4,adate);
1514 srv_put_dos_date2(p,8,mdate);
1515 SIVAL(p,12,(uint32)file_size);
1516 SIVAL(p,16,(uint32)allocation_size);
1518 p += 22; /* p now points to the EA area. */
1520 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1521 name_list = ea_list_union(name_list, file_list, &ea_len);
1523 /* We need to determine if this entry will fit in the space available. */
1524 /* Max string size is 255 bytes. */
1525 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1526 /* Move the dirptr back to prev_dirpos */
1527 dptr_SeekDir(conn->dirptr, prev_dirpos);
1528 *out_of_space = True;
1529 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1530 return False; /* Not finished - just out of space */
1533 /* Push the ea_data followed by the name. */
1534 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1536 len = srvstr_push(base_data, flags2,
1537 p + 1, fname, PTR_DIFF(end_data, p+1),
1538 STR_TERMINATE | STR_NOALIGN);
1539 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1552 SCVAL(nameptr,0,len);
1554 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1558 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1559 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1560 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1562 SIVAL(p,0,reskey); p += 4;
1563 put_long_date_timespec(p,create_date_ts); p += 8;
1564 put_long_date_timespec(p,adate_ts); p += 8;
1565 put_long_date_timespec(p,mdate_ts); p += 8;
1566 put_long_date_timespec(p,mdate_ts); p += 8;
1567 SOFF_T(p,0,file_size); p += 8;
1568 SOFF_T(p,0,allocation_size); p += 8;
1569 SIVAL(p,0,nt_extmode); p += 4;
1570 q = p; p += 4; /* q is placeholder for name length. */
1572 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1573 SIVAL(p,0,ea_size); /* Extended attributes */
1576 /* Clear the short name buffer. This is
1577 * IMPORTANT as not doing so will trigger
1578 * a Win2k client bug. JRA.
1580 if (!was_8_3 && check_mangled_names) {
1581 if (!name_to_8_3(fname,mangled_name,True,
1583 /* Error - mangle failed ! */
1584 memset(mangled_name,'\0',12);
1586 mangled_name[12] = 0;
1587 len = srvstr_push(base_data, flags2,
1588 p+2, mangled_name, 24,
1589 STR_UPPER|STR_UNICODE);
1591 memset(p + 2 + len,'\0',24 - len);
1598 len = srvstr_push(base_data, flags2, p,
1599 fname, PTR_DIFF(end_data, p),
1600 STR_TERMINATE_ASCII);
1603 SIVAL(p,0,0); /* Ensure any padding is null. */
1604 len = PTR_DIFF(p, pdata);
1605 len = (len + 3) & ~3;
1610 case SMB_FIND_FILE_DIRECTORY_INFO:
1611 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1613 SIVAL(p,0,reskey); p += 4;
1614 put_long_date_timespec(p,create_date_ts); p += 8;
1615 put_long_date_timespec(p,adate_ts); p += 8;
1616 put_long_date_timespec(p,mdate_ts); p += 8;
1617 put_long_date_timespec(p,mdate_ts); p += 8;
1618 SOFF_T(p,0,file_size); p += 8;
1619 SOFF_T(p,0,allocation_size); p += 8;
1620 SIVAL(p,0,nt_extmode); p += 4;
1621 len = srvstr_push(base_data, flags2,
1622 p + 4, fname, PTR_DIFF(end_data, p+4),
1623 STR_TERMINATE_ASCII);
1626 SIVAL(p,0,0); /* Ensure any padding is null. */
1627 len = PTR_DIFF(p, pdata);
1628 len = (len + 3) & ~3;
1633 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1634 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1636 SIVAL(p,0,reskey); p += 4;
1637 put_long_date_timespec(p,create_date_ts); p += 8;
1638 put_long_date_timespec(p,adate_ts); p += 8;
1639 put_long_date_timespec(p,mdate_ts); p += 8;
1640 put_long_date_timespec(p,mdate_ts); p += 8;
1641 SOFF_T(p,0,file_size); p += 8;
1642 SOFF_T(p,0,allocation_size); p += 8;
1643 SIVAL(p,0,nt_extmode); p += 4;
1644 q = p; p += 4; /* q is placeholder for name length. */
1646 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1647 SIVAL(p,0,ea_size); /* Extended attributes */
1650 len = srvstr_push(base_data, flags2, p,
1651 fname, PTR_DIFF(end_data, p),
1652 STR_TERMINATE_ASCII);
1656 SIVAL(p,0,0); /* Ensure any padding is null. */
1657 len = PTR_DIFF(p, pdata);
1658 len = (len + 3) & ~3;
1663 case SMB_FIND_FILE_NAMES_INFO:
1664 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1666 SIVAL(p,0,reskey); p += 4;
1668 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1669 acl on a dir (tridge) */
1670 len = srvstr_push(base_data, flags2, p,
1671 fname, PTR_DIFF(end_data, p),
1672 STR_TERMINATE_ASCII);
1675 SIVAL(p,0,0); /* Ensure any padding is null. */
1676 len = PTR_DIFF(p, pdata);
1677 len = (len + 3) & ~3;
1682 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1683 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1685 SIVAL(p,0,reskey); p += 4;
1686 put_long_date_timespec(p,create_date_ts); p += 8;
1687 put_long_date_timespec(p,adate_ts); p += 8;
1688 put_long_date_timespec(p,mdate_ts); p += 8;
1689 put_long_date_timespec(p,mdate_ts); p += 8;
1690 SOFF_T(p,0,file_size); p += 8;
1691 SOFF_T(p,0,allocation_size); p += 8;
1692 SIVAL(p,0,nt_extmode); p += 4;
1693 q = p; p += 4; /* q is placeholder for name length. */
1695 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1696 SIVAL(p,0,ea_size); /* Extended attributes */
1699 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1700 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1701 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1702 len = srvstr_push(base_data, flags2, p,
1703 fname, PTR_DIFF(end_data, p),
1704 STR_TERMINATE_ASCII);
1707 SIVAL(p,0,0); /* Ensure any padding is null. */
1708 len = PTR_DIFF(p, pdata);
1709 len = (len + 3) & ~3;
1714 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1715 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1716 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1718 SIVAL(p,0,reskey); p += 4;
1719 put_long_date_timespec(p,create_date_ts); p += 8;
1720 put_long_date_timespec(p,adate_ts); p += 8;
1721 put_long_date_timespec(p,mdate_ts); p += 8;
1722 put_long_date_timespec(p,mdate_ts); p += 8;
1723 SOFF_T(p,0,file_size); p += 8;
1724 SOFF_T(p,0,allocation_size); p += 8;
1725 SIVAL(p,0,nt_extmode); p += 4;
1726 q = p; p += 4; /* q is placeholder for name length */
1728 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1729 SIVAL(p,0,ea_size); /* Extended attributes */
1732 /* Clear the short name buffer. This is
1733 * IMPORTANT as not doing so will trigger
1734 * a Win2k client bug. JRA.
1736 if (!was_8_3 && check_mangled_names) {
1737 if (!name_to_8_3(fname,mangled_name,True,
1739 /* Error - mangle failed ! */
1740 memset(mangled_name,'\0',12);
1742 mangled_name[12] = 0;
1743 len = srvstr_push(base_data, flags2,
1744 p+2, mangled_name, 24,
1745 STR_UPPER|STR_UNICODE);
1748 memset(p + 2 + len,'\0',24 - len);
1755 SSVAL(p,0,0); p += 2; /* Reserved ? */
1756 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1757 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1758 len = srvstr_push(base_data, flags2, p,
1759 fname, PTR_DIFF(end_data, p),
1760 STR_TERMINATE_ASCII);
1763 SIVAL(p,0,0); /* Ensure any padding is null. */
1764 len = PTR_DIFF(p, pdata);
1765 len = (len + 3) & ~3;
1770 /* CIFS UNIX Extension. */
1772 case SMB_FIND_FILE_UNIX:
1773 case SMB_FIND_FILE_UNIX_INFO2:
1775 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1777 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1779 if (info_level == SMB_FIND_FILE_UNIX) {
1780 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1781 p = store_file_unix_basic(conn, p,
1783 len = srvstr_push(base_data, flags2, p,
1784 fname, PTR_DIFF(end_data, p),
1787 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1788 p = store_file_unix_basic_info2(conn, p,
1792 len = srvstr_push(base_data, flags2, p, fname,
1793 PTR_DIFF(end_data, p), 0);
1794 SIVAL(nameptr, 0, len);
1798 SIVAL(p,0,0); /* Ensure any padding is null. */
1800 len = PTR_DIFF(p, pdata);
1801 len = (len + 3) & ~3;
1802 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1804 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1813 if (PTR_DIFF(p,pdata) > space_remaining) {
1814 /* Move the dirptr back to prev_dirpos */
1815 dptr_SeekDir(conn->dirptr, prev_dirpos);
1816 *out_of_space = True;
1817 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1818 return False; /* Not finished - just out of space */
1821 /* Setup the last entry pointer, as an offset from base_data */
1822 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1823 /* Advance the data pointer to the next slot */
1829 /****************************************************************************
1830 Reply to a TRANS2_FINDFIRST.
1831 ****************************************************************************/
1833 static void call_trans2findfirst(connection_struct *conn,
1834 struct smb_request *req,
1835 char **pparams, int total_params,
1836 char **ppdata, int total_data,
1837 unsigned int max_data_bytes)
1839 /* We must be careful here that we don't return more than the
1840 allowed number of data bytes. If this means returning fewer than
1841 maxentries then so be it. We assume that the redirector has
1842 enough room for the fixed number of parameter bytes it has
1844 char *params = *pparams;
1845 char *pdata = *ppdata;
1849 uint16 findfirst_flags;
1850 bool close_after_first;
1852 bool requires_resume_key;
1854 char *directory = NULL;
1855 const char *mask = NULL;
1857 int last_entry_off=0;
1861 bool finished = False;
1862 bool dont_descend = False;
1863 bool out_of_space = False;
1864 int space_remaining;
1865 bool mask_contains_wcard = False;
1866 SMB_STRUCT_STAT sbuf;
1867 struct ea_list *ea_list = NULL;
1868 NTSTATUS ntstatus = NT_STATUS_OK;
1869 TALLOC_CTX *ctx = talloc_tos();
1871 if (total_params < 13) {
1872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1876 dirtype = SVAL(params,0);
1877 maxentries = SVAL(params,2);
1878 findfirst_flags = SVAL(params,4);
1879 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1880 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1881 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1882 info_level = SVAL(params,6);
1884 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1885 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1886 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1887 info_level, max_data_bytes));
1890 /* W2K3 seems to treat zero as 1. */
1894 switch (info_level) {
1895 case SMB_FIND_INFO_STANDARD:
1896 case SMB_FIND_EA_SIZE:
1897 case SMB_FIND_EA_LIST:
1898 case SMB_FIND_FILE_DIRECTORY_INFO:
1899 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1900 case SMB_FIND_FILE_NAMES_INFO:
1901 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1902 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1903 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1905 case SMB_FIND_FILE_UNIX:
1906 case SMB_FIND_FILE_UNIX_INFO2:
1907 if (!lp_unix_extensions()) {
1908 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1913 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1917 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1918 params+12, total_params - 12,
1919 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1920 if (!NT_STATUS_IS_OK(ntstatus)) {
1921 reply_nterror(req, ntstatus);
1925 ntstatus = resolve_dfspath_wcard(ctx, conn,
1926 req->flags2 & FLAGS2_DFS_PATHNAMES,
1929 &mask_contains_wcard);
1930 if (!NT_STATUS_IS_OK(ntstatus)) {
1931 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1932 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1933 ERRSRV, ERRbadpath);
1936 reply_nterror(req, ntstatus);
1940 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1941 if (!NT_STATUS_IS_OK(ntstatus)) {
1942 reply_nterror(req, ntstatus);
1946 ntstatus = check_name(conn, directory);
1947 if (!NT_STATUS_IS_OK(ntstatus)) {
1948 reply_nterror(req, ntstatus);
1952 p = strrchr_m(directory,'/');
1954 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1955 if((directory[0] == '.') && (directory[1] == '\0')) {
1957 mask_contains_wcard = True;
1961 directory = talloc_strdup(talloc_tos(), "./");
1963 reply_nterror(req, NT_STATUS_NO_MEMORY);
1971 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1973 if (info_level == SMB_FIND_EA_LIST) {
1976 if (total_data < 4) {
1977 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1981 ea_size = IVAL(pdata,0);
1982 if (ea_size != total_data) {
1983 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1984 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1989 if (!lp_ea_support(SNUM(conn))) {
1990 reply_doserror(req, ERRDOS, ERReasnotsupported);
1994 /* Pull out the list of names. */
1995 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2002 *ppdata = (char *)SMB_REALLOC(
2003 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2004 if(*ppdata == NULL ) {
2005 reply_nterror(req, NT_STATUS_NO_MEMORY);
2009 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2011 /* Realloc the params space */
2012 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2013 if (*pparams == NULL) {
2014 reply_nterror(req, NT_STATUS_NO_MEMORY);
2019 /* Save the wildcard match and attribs we are using on this directory -
2020 needed as lanman2 assumes these are being saved between calls */
2022 ntstatus = dptr_create(conn,
2028 mask_contains_wcard,
2032 if (!NT_STATUS_IS_OK(ntstatus)) {
2033 reply_nterror(req, ntstatus);
2037 dptr_num = dptr_dnum(conn->dirptr);
2038 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2040 /* We don't need to check for VOL here as this is returned by
2041 a different TRANS2 call. */
2043 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2044 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2045 dont_descend = True;
2048 space_remaining = max_data_bytes;
2049 out_of_space = False;
2051 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2052 bool got_exact_match = False;
2054 /* this is a heuristic to avoid seeking the dirptr except when
2055 absolutely necessary. It allows for a filename of about 40 chars */
2056 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2057 out_of_space = True;
2060 finished = !get_lanman2_dir_entry(ctx,
2063 mask,dirtype,info_level,
2064 requires_resume_key,dont_descend,
2066 space_remaining, &out_of_space,
2068 &last_entry_off, ea_list);
2071 if (finished && out_of_space)
2074 if (!finished && !out_of_space)
2078 * As an optimisation if we know we aren't looking
2079 * for a wildcard name (ie. the name matches the wildcard exactly)
2080 * then we can finish on any (first) match.
2081 * This speeds up large directory searches. JRA.
2087 /* Ensure space_remaining never goes -ve. */
2088 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2089 space_remaining = 0;
2090 out_of_space = true;
2092 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2096 /* Check if we can close the dirptr */
2097 if(close_after_first || (finished && close_if_end)) {
2098 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2099 dptr_close(&dptr_num);
2103 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2104 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2105 * the protocol level is less than NT1. Tested with smbclient. JRA.
2106 * This should fix the OS/2 client bug #2335.
2109 if(numentries == 0) {
2110 dptr_close(&dptr_num);
2111 if (Protocol < PROTOCOL_NT1) {
2112 reply_doserror(req, ERRDOS, ERRnofiles);
2115 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2116 ERRDOS, ERRbadfile);
2121 /* At this point pdata points to numentries directory entries. */
2123 /* Set up the return parameter block */
2124 SSVAL(params,0,dptr_num);
2125 SSVAL(params,2,numentries);
2126 SSVAL(params,4,finished);
2127 SSVAL(params,6,0); /* Never an EA error */
2128 SSVAL(params,8,last_entry_off);
2130 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2133 if ((! *directory) && dptr_path(dptr_num)) {
2134 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2136 reply_nterror(req, NT_STATUS_NO_MEMORY);
2140 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2141 smb_fn_name(CVAL(req->inbuf,smb_com)),
2142 mask, directory, dirtype, numentries ) );
2145 * Force a name mangle here to ensure that the
2146 * mask as an 8.3 name is top of the mangled cache.
2147 * The reasons for this are subtle. Don't remove
2148 * this code unless you know what you are doing
2149 * (see PR#13758). JRA.
2152 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2153 char mangled_name[13];
2154 name_to_8_3(mask, mangled_name, True, conn->params);
2160 /****************************************************************************
2161 Reply to a TRANS2_FINDNEXT.
2162 ****************************************************************************/
2164 static void call_trans2findnext(connection_struct *conn,
2165 struct smb_request *req,
2166 char **pparams, int total_params,
2167 char **ppdata, int total_data,
2168 unsigned int max_data_bytes)
2170 /* We must be careful here that we don't return more than the
2171 allowed number of data bytes. If this means returning fewer than
2172 maxentries then so be it. We assume that the redirector has
2173 enough room for the fixed number of parameter bytes it has
2175 char *params = *pparams;
2176 char *pdata = *ppdata;
2182 uint16 findnext_flags;
2183 bool close_after_request;
2185 bool requires_resume_key;
2187 bool mask_contains_wcard = False;
2188 char *resume_name = NULL;
2189 const char *mask = NULL;
2190 const char *directory = NULL;
2194 int i, last_entry_off=0;
2195 bool finished = False;
2196 bool dont_descend = False;
2197 bool out_of_space = False;
2198 int space_remaining;
2199 struct ea_list *ea_list = NULL;
2200 NTSTATUS ntstatus = NT_STATUS_OK;
2201 TALLOC_CTX *ctx = talloc_tos();
2203 if (total_params < 13) {
2204 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2208 dptr_num = SVAL(params,0);
2209 maxentries = SVAL(params,2);
2210 info_level = SVAL(params,4);
2211 resume_key = IVAL(params,6);
2212 findnext_flags = SVAL(params,10);
2213 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2214 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2215 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2216 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2218 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2220 total_params - 12, STR_TERMINATE, &ntstatus,
2221 &mask_contains_wcard);
2222 if (!NT_STATUS_IS_OK(ntstatus)) {
2223 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2224 complain (it thinks we're asking for the directory above the shared
2225 path or an invalid name). Catch this as the resume name is only compared, never used in
2226 a file access. JRA. */
2227 srvstr_pull_talloc(ctx, params, req->flags2,
2228 &resume_name, params+12,
2232 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2233 reply_nterror(req, ntstatus);
2238 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2239 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2240 resume_key = %d resume name = %s continue=%d level = %d\n",
2241 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2242 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2245 /* W2K3 seems to treat zero as 1. */
2249 switch (info_level) {
2250 case SMB_FIND_INFO_STANDARD:
2251 case SMB_FIND_EA_SIZE:
2252 case SMB_FIND_EA_LIST:
2253 case SMB_FIND_FILE_DIRECTORY_INFO:
2254 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2255 case SMB_FIND_FILE_NAMES_INFO:
2256 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2257 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2258 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2260 case SMB_FIND_FILE_UNIX:
2261 case SMB_FIND_FILE_UNIX_INFO2:
2262 if (!lp_unix_extensions()) {
2263 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2268 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2272 if (info_level == SMB_FIND_EA_LIST) {
2275 if (total_data < 4) {
2276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2280 ea_size = IVAL(pdata,0);
2281 if (ea_size != total_data) {
2282 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2283 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2288 if (!lp_ea_support(SNUM(conn))) {
2289 reply_doserror(req, ERRDOS, ERReasnotsupported);
2293 /* Pull out the list of names. */
2294 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2301 *ppdata = (char *)SMB_REALLOC(
2302 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2303 if(*ppdata == NULL) {
2304 reply_nterror(req, NT_STATUS_NO_MEMORY);
2309 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2311 /* Realloc the params space */
2312 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2313 if(*pparams == NULL ) {
2314 reply_nterror(req, NT_STATUS_NO_MEMORY);
2320 /* Check that the dptr is valid */
2321 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2322 reply_doserror(req, ERRDOS, ERRnofiles);
2326 string_set(&conn->dirpath,dptr_path(dptr_num));
2328 /* Get the wildcard mask from the dptr */
2329 if((p = dptr_wcard(dptr_num))== NULL) {
2330 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2331 reply_doserror(req, ERRDOS, ERRnofiles);
2336 directory = conn->dirpath;
2338 /* Get the attr mask from the dptr */
2339 dirtype = dptr_attr(dptr_num);
2341 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2342 dptr_num, mask, dirtype,
2344 dptr_TellDir(conn->dirptr)));
2346 /* We don't need to check for VOL here as this is returned by
2347 a different TRANS2 call. */
2349 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2350 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2351 dont_descend = True;
2354 space_remaining = max_data_bytes;
2355 out_of_space = False;
2358 * Seek to the correct position. We no longer use the resume key but
2359 * depend on the last file name instead.
2362 if(*resume_name && !continue_bit) {
2365 long current_pos = 0;
2367 * Remember, name_to_8_3 is called by
2368 * get_lanman2_dir_entry(), so the resume name
2369 * could be mangled. Ensure we check the unmangled name.
2372 if (mangle_is_mangled(resume_name, conn->params)) {
2373 char *new_resume_name = NULL;
2374 mangle_lookup_name_from_8_3(ctx,
2378 if (new_resume_name) {
2379 resume_name = new_resume_name;
2384 * Fix for NT redirector problem triggered by resume key indexes
2385 * changing between directory scans. We now return a resume key of 0
2386 * and instead look for the filename to continue from (also given
2387 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2388 * findfirst/findnext (as is usual) then the directory pointer
2389 * should already be at the correct place.
2392 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2393 } /* end if resume_name && !continue_bit */
2395 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2396 bool got_exact_match = False;
2398 /* this is a heuristic to avoid seeking the dirptr except when
2399 absolutely necessary. It allows for a filename of about 40 chars */
2400 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2401 out_of_space = True;
2404 finished = !get_lanman2_dir_entry(ctx,
2407 mask,dirtype,info_level,
2408 requires_resume_key,dont_descend,
2410 space_remaining, &out_of_space,
2412 &last_entry_off, ea_list);
2415 if (finished && out_of_space)
2418 if (!finished && !out_of_space)
2422 * As an optimisation if we know we aren't looking
2423 * for a wildcard name (ie. the name matches the wildcard exactly)
2424 * then we can finish on any (first) match.
2425 * This speeds up large directory searches. JRA.
2431 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2434 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2435 smb_fn_name(CVAL(req->inbuf,smb_com)),
2436 mask, directory, dirtype, numentries ) );
2438 /* Check if we can close the dirptr */
2439 if(close_after_request || (finished && close_if_end)) {
2440 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2441 dptr_close(&dptr_num); /* This frees up the saved mask */
2444 /* Set up the return parameter block */
2445 SSVAL(params,0,numentries);
2446 SSVAL(params,2,finished);
2447 SSVAL(params,4,0); /* Never an EA error */
2448 SSVAL(params,6,last_entry_off);
2450 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2456 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2458 E_md4hash(lp_servicename(SNUM(conn)),objid);
2462 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2464 SMB_ASSERT(extended_info != NULL);
2466 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2467 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2468 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2469 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2470 #ifdef SAMBA_VERSION_REVISION
2471 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2473 extended_info->samba_subversion = 0;
2474 #ifdef SAMBA_VERSION_RC_RELEASE
2475 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2477 #ifdef SAMBA_VERSION_PRE_RELEASE
2478 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2481 #ifdef SAMBA_VERSION_VENDOR_PATCH
2482 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2484 extended_info->samba_gitcommitdate = 0;
2485 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2486 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2489 memset(extended_info->samba_version_string, 0,
2490 sizeof(extended_info->samba_version_string));
2492 snprintf (extended_info->samba_version_string,
2493 sizeof(extended_info->samba_version_string),
2494 "%s", samba_version_string());
2497 /****************************************************************************
2498 Reply to a TRANS2_QFSINFO (query filesystem info).
2499 ****************************************************************************/
2501 static void call_trans2qfsinfo(connection_struct *conn,
2502 struct smb_request *req,
2503 char **pparams, int total_params,
2504 char **ppdata, int total_data,
2505 unsigned int max_data_bytes)
2507 char *pdata, *end_data;
2508 char *params = *pparams;
2512 const char *vname = volume_label(SNUM(conn));
2513 int snum = SNUM(conn);
2514 char *fstype = lp_fstype(SNUM(conn));
2515 uint32 additional_flags = 0;
2517 if (total_params < 2) {
2518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2522 info_level = SVAL(params,0);
2525 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2526 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2527 "info level (0x%x) on IPC$.\n",
2528 (unsigned int)info_level));
2529 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2534 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2535 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2536 DEBUG(0,("call_trans2qfsinfo: encryption required "
2537 "and info level 0x%x sent.\n",
2538 (unsigned int)info_level));
2539 exit_server_cleanly("encryption required "
2545 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2547 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2548 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2549 reply_doserror(req, ERRSRV, ERRinvdevice);
2553 *ppdata = (char *)SMB_REALLOC(
2554 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2555 if (*ppdata == NULL ) {
2556 reply_nterror(req, NT_STATUS_NO_MEMORY);
2561 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2562 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2564 switch (info_level) {
2565 case SMB_INFO_ALLOCATION:
2567 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2569 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2570 reply_unixerror(req, ERRHRD, ERRgeneral);
2574 block_size = lp_block_size(snum);
2575 if (bsize < block_size) {
2576 SMB_BIG_UINT factor = block_size/bsize;
2581 if (bsize > block_size) {
2582 SMB_BIG_UINT factor = bsize/block_size;
2587 bytes_per_sector = 512;
2588 sectors_per_unit = bsize/bytes_per_sector;
2590 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2591 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2592 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2594 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2595 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2596 SIVAL(pdata,l1_cUnit,dsize);
2597 SIVAL(pdata,l1_cUnitAvail,dfree);
2598 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2602 case SMB_INFO_VOLUME:
2603 /* Return volume name */
2605 * Add volume serial number - hash of a combination of
2606 * the called hostname and the service name.
2608 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2610 * Win2k3 and previous mess this up by sending a name length
2611 * one byte short. I believe only older clients (OS/2 Win9x) use
2612 * this call so try fixing this by adding a terminating null to
2613 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2617 pdata+l2_vol_szVolLabel, vname,
2618 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2619 STR_NOALIGN|STR_TERMINATE);
2620 SCVAL(pdata,l2_vol_cch,len);
2621 data_len = l2_vol_szVolLabel + len;
2622 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2623 (unsigned)st.st_ctime, len, vname));
2626 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2627 case SMB_FS_ATTRIBUTE_INFORMATION:
2629 additional_flags = 0;
2630 #if defined(HAVE_SYS_QUOTAS)
2631 additional_flags |= FILE_VOLUME_QUOTAS;
2634 if(lp_nt_acl_support(SNUM(conn))) {
2635 additional_flags |= FILE_PERSISTENT_ACLS;
2638 /* Capabilities are filled in at connection time through STATVFS call */
2639 additional_flags |= conn->fs_capabilities;
2641 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2642 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2643 additional_flags); /* FS ATTRIBUTES */
2645 SIVAL(pdata,4,255); /* Max filename component length */
2646 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2647 and will think we can't do long filenames */
2648 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2649 PTR_DIFF(end_data, pdata+12),
2652 data_len = 12 + len;
2655 case SMB_QUERY_FS_LABEL_INFO:
2656 case SMB_FS_LABEL_INFORMATION:
2657 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2658 PTR_DIFF(end_data, pdata+4), 0);
2663 case SMB_QUERY_FS_VOLUME_INFO:
2664 case SMB_FS_VOLUME_INFORMATION:
2667 * Add volume serial number - hash of a combination of
2668 * the called hostname and the service name.
2670 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2671 (str_checksum(get_local_machine_name())<<16));
2673 /* Max label len is 32 characters. */
2674 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2675 PTR_DIFF(end_data, pdata+18),
2677 SIVAL(pdata,12,len);
2680 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2681 (int)strlen(vname),vname, lp_servicename(snum)));
2684 case SMB_QUERY_FS_SIZE_INFO:
2685 case SMB_FS_SIZE_INFORMATION:
2687 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2689 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2690 reply_unixerror(req, ERRHRD, ERRgeneral);
2693 block_size = lp_block_size(snum);
2694 if (bsize < block_size) {
2695 SMB_BIG_UINT factor = block_size/bsize;
2700 if (bsize > block_size) {
2701 SMB_BIG_UINT factor = bsize/block_size;
2706 bytes_per_sector = 512;
2707 sectors_per_unit = bsize/bytes_per_sector;
2708 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2709 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2710 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2711 SBIG_UINT(pdata,0,dsize);
2712 SBIG_UINT(pdata,8,dfree);
2713 SIVAL(pdata,16,sectors_per_unit);
2714 SIVAL(pdata,20,bytes_per_sector);
2718 case SMB_FS_FULL_SIZE_INFORMATION:
2720 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2722 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2723 reply_unixerror(req, ERRHRD, ERRgeneral);
2726 block_size = lp_block_size(snum);
2727 if (bsize < block_size) {
2728 SMB_BIG_UINT factor = block_size/bsize;
2733 if (bsize > block_size) {
2734 SMB_BIG_UINT factor = bsize/block_size;
2739 bytes_per_sector = 512;
2740 sectors_per_unit = bsize/bytes_per_sector;
2741 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2742 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2743 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2744 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2745 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2746 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2747 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2748 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2752 case SMB_QUERY_FS_DEVICE_INFO:
2753 case SMB_FS_DEVICE_INFORMATION:
2755 SIVAL(pdata,0,0); /* dev type */
2756 SIVAL(pdata,4,0); /* characteristics */
2759 #ifdef HAVE_SYS_QUOTAS
2760 case SMB_FS_QUOTA_INFORMATION:
2762 * what we have to send --metze:
2764 * Unknown1: 24 NULL bytes
2765 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2766 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2767 * Quota Flags: 2 byte :
2768 * Unknown3: 6 NULL bytes
2772 * details for Quota Flags:
2774 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2775 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2776 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2777 * 0x0001 Enable Quotas: enable quota for this fs
2781 /* we need to fake up a fsp here,
2782 * because its not send in this call
2785 SMB_NTQUOTA_STRUCT quotas;
2788 ZERO_STRUCT(quotas);
2794 if (current_user.ut.uid != 0) {
2795 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2796 lp_servicename(SNUM(conn)),conn->user));
2797 reply_doserror(req, ERRDOS, ERRnoaccess);
2801 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2802 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2803 reply_doserror(req, ERRSRV, ERRerror);
2809 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2811 /* Unknown1 24 NULL bytes*/
2812 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2813 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2814 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2816 /* Default Soft Quota 8 bytes */
2817 SBIG_UINT(pdata,24,quotas.softlim);
2819 /* Default Hard Quota 8 bytes */
2820 SBIG_UINT(pdata,32,quotas.hardlim);
2822 /* Quota flag 2 bytes */
2823 SSVAL(pdata,40,quotas.qflags);
2825 /* Unknown3 6 NULL bytes */
2831 #endif /* HAVE_SYS_QUOTAS */
2832 case SMB_FS_OBJECTID_INFORMATION:
2834 unsigned char objid[16];
2835 struct smb_extended_info extended_info;
2836 memcpy(pdata,create_volume_objectid(conn, objid),16);
2837 samba_extended_info_version (&extended_info);
2838 SIVAL(pdata,16,extended_info.samba_magic);
2839 SIVAL(pdata,20,extended_info.samba_version);
2840 SIVAL(pdata,24,extended_info.samba_subversion);
2841 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2842 memcpy(pdata+36,extended_info.samba_version_string,28);
2848 * Query the version and capabilities of the CIFS UNIX extensions
2852 case SMB_QUERY_CIFS_UNIX_INFO:
2854 bool large_write = lp_min_receive_file_size() &&
2855 !srv_is_signing_active();
2856 bool large_read = !srv_is_signing_active();
2857 int encrypt_caps = 0;
2859 if (!lp_unix_extensions()) {
2860 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2864 switch (conn->encrypt_level) {
2870 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2873 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2874 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2875 large_write = false;
2881 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2882 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2884 /* We have POSIX ACLs, pathname, encryption,
2885 * large read/write, and locking capability. */
2887 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2888 CIFS_UNIX_POSIX_ACLS_CAP|
2889 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2890 CIFS_UNIX_FCNTL_LOCKS_CAP|
2891 CIFS_UNIX_EXTATTR_CAP|
2892 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2894 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2896 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2900 case SMB_QUERY_POSIX_FS_INFO:
2903 vfs_statvfs_struct svfs;
2905 if (!lp_unix_extensions()) {
2906 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2910 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2914 SIVAL(pdata,0,svfs.OptimalTransferSize);
2915 SIVAL(pdata,4,svfs.BlockSize);
2916 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2917 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2918 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2919 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2920 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2921 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2922 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2924 } else if (rc == EOPNOTSUPP) {
2925 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2927 #endif /* EOPNOTSUPP */
2929 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2930 reply_doserror(req, ERRSRV, ERRerror);
2936 case SMB_QUERY_POSIX_WHOAMI:
2942 if (!lp_unix_extensions()) {
2943 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2947 if (max_data_bytes < 40) {
2948 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2952 /* We ARE guest if global_sid_Builtin_Guests is
2953 * in our list of SIDs.
2955 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2956 current_user.nt_user_token)) {
2957 flags |= SMB_WHOAMI_GUEST;
2960 /* We are NOT guest if global_sid_Authenticated_Users
2961 * is in our list of SIDs.
2963 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2964 current_user.nt_user_token)) {
2965 flags &= ~SMB_WHOAMI_GUEST;
2968 /* NOTE: 8 bytes for UID/GID, irrespective of native
2969 * platform size. This matches
2970 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2972 data_len = 4 /* flags */
2979 + 4 /* pad/reserved */
2980 + (current_user.ut.ngroups * 8)
2982 + (current_user.nt_user_token->num_sids *
2986 SIVAL(pdata, 0, flags);
2987 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2988 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2989 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2992 if (data_len >= max_data_bytes) {
2993 /* Potential overflow, skip the GIDs and SIDs. */
2995 SIVAL(pdata, 24, 0); /* num_groups */
2996 SIVAL(pdata, 28, 0); /* num_sids */
2997 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2998 SIVAL(pdata, 36, 0); /* reserved */
3004 SIVAL(pdata, 24, current_user.ut.ngroups);
3006 current_user.nt_user_token->num_sids);
3008 /* We walk the SID list twice, but this call is fairly
3009 * infrequent, and I don't expect that it's performance
3010 * sensitive -- jpeach
3012 for (i = 0, sid_bytes = 0;
3013 i < current_user.nt_user_token->num_sids; ++i) {
3014 sid_bytes += ndr_size_dom_sid(
3015 ¤t_user.nt_user_token->user_sids[i], 0);
3018 /* SID list byte count */
3019 SIVAL(pdata, 32, sid_bytes);
3021 /* 4 bytes pad/reserved - must be zero */
3022 SIVAL(pdata, 36, 0);
3026 for (i = 0; i < current_user.ut.ngroups; ++i) {
3027 SBIG_UINT(pdata, data_len,
3028 (SMB_BIG_UINT)current_user.ut.groups[i]);
3034 i < current_user.nt_user_token->num_sids; ++i) {
3035 int sid_len = ndr_size_dom_sid(
3036 ¤t_user.nt_user_token->user_sids[i], 0);
3038 sid_linearize(pdata + data_len, sid_len,
3039 ¤t_user.nt_user_token->user_sids[i]);
3040 data_len += sid_len;
3046 case SMB_MAC_QUERY_FS_INFO:
3048 * Thursby MAC extension... ONLY on NTFS filesystems
3049 * once we do streams then we don't need this
3051 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3053 SIVAL(pdata,84,0x100); /* Don't support mac... */
3058 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3063 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3066 DEBUG( 4, ( "%s info_level = %d\n",
3067 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3072 /****************************************************************************
3073 Reply to a TRANS2_SETFSINFO (set filesystem info).
3074 ****************************************************************************/
3076 static void call_trans2setfsinfo(connection_struct *conn,
3077 struct smb_request *req,
3078 char **pparams, int total_params,
3079 char **ppdata, int total_data,
3080 unsigned int max_data_bytes)
3082 char *pdata = *ppdata;
3083 char *params = *pparams;
3086 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3089 if (total_params < 4) {
3090 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3096 info_level = SVAL(params,2);
3099 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3100 info_level != SMB_SET_CIFS_UNIX_INFO) {
3101 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3102 "info level (0x%x) on IPC$.\n",
3103 (unsigned int)info_level));
3104 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3109 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3110 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3111 DEBUG(0,("call_trans2setfsinfo: encryption required "
3112 "and info level 0x%x sent.\n",
3113 (unsigned int)info_level));
3114 exit_server_cleanly("encryption required "
3120 switch(info_level) {
3121 case SMB_SET_CIFS_UNIX_INFO:
3123 uint16 client_unix_major;
3124 uint16 client_unix_minor;
3125 uint32 client_unix_cap_low;
3126 uint32 client_unix_cap_high;
3128 if (!lp_unix_extensions()) {
3130 NT_STATUS_INVALID_LEVEL);
3134 /* There should be 12 bytes of capabilities set. */
3135 if (total_data < 8) {
3138 NT_STATUS_INVALID_PARAMETER);
3141 client_unix_major = SVAL(pdata,0);
3142 client_unix_minor = SVAL(pdata,2);
3143 client_unix_cap_low = IVAL(pdata,4);
3144 client_unix_cap_high = IVAL(pdata,8);
3145 /* Just print these values for now. */
3146 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3147 cap_low = 0x%x, cap_high = 0x%x\n",
3148 (unsigned int)client_unix_major,
3149 (unsigned int)client_unix_minor,
3150 (unsigned int)client_unix_cap_low,
3151 (unsigned int)client_unix_cap_high ));
3153 /* Here is where we must switch to posix pathname processing... */
3154 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3155 lp_set_posix_pathnames();
3156 mangle_change_to_posix();
3159 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3160 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3161 /* Client that knows how to do posix locks,
3162 * but not posix open/mkdir operations. Set a
3163 * default type for read/write checks. */
3165 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3171 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3174 size_t param_len = 0;
3175 size_t data_len = total_data;
3177 if (!lp_unix_extensions()) {
3180 NT_STATUS_INVALID_LEVEL);
3184 if (lp_smb_encrypt(SNUM(conn)) == false) {
3187 NT_STATUS_NOT_SUPPORTED);
3191 DEBUG( 4,("call_trans2setfsinfo: "
3192 "request transport encryption.\n"));
3194 status = srv_request_encryption_setup(conn,
3195 (unsigned char **)ppdata,
3197 (unsigned char **)pparams,
3200 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3201 !NT_STATUS_IS_OK(status)) {
3202 reply_nterror(req, status);
3206 send_trans2_replies(conn, req,
3213 if (NT_STATUS_IS_OK(status)) {
3214 /* Server-side transport
3215 * encryption is now *on*. */
3216 status = srv_encryption_start(conn);
3217 if (!NT_STATUS_IS_OK(status)) {
3218 exit_server_cleanly(
3219 "Failure in setting "
3220 "up encrypted transport");
3226 case SMB_FS_QUOTA_INFORMATION:
3228 files_struct *fsp = NULL;
3229 SMB_NTQUOTA_STRUCT quotas;
3231 ZERO_STRUCT(quotas);
3234 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3235 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3236 lp_servicename(SNUM(conn)),conn->user));
3237 reply_doserror(req, ERRSRV, ERRaccess);
3241 /* note: normaly there're 48 bytes,
3242 * but we didn't use the last 6 bytes for now
3245 fsp = file_fsp(SVAL(params,0));
3246 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3247 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3249 req, NT_STATUS_INVALID_HANDLE);
3253 if (total_data < 42) {
3254 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3258 NT_STATUS_INVALID_PARAMETER);
3262 /* unknown_1 24 NULL bytes in pdata*/
3264 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3265 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3266 #ifdef LARGE_SMB_OFF_T
3267 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3268 #else /* LARGE_SMB_OFF_T */
3269 if ((IVAL(pdata,28) != 0)&&
3270 ((quotas.softlim != 0xFFFFFFFF)||
3271 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3272 /* more than 32 bits? */
3275 NT_STATUS_INVALID_PARAMETER);
3278 #endif /* LARGE_SMB_OFF_T */
3280 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3281 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3282 #ifdef LARGE_SMB_OFF_T
3283 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3284 #else /* LARGE_SMB_OFF_T */
3285 if ((IVAL(pdata,36) != 0)&&
3286 ((quotas.hardlim != 0xFFFFFFFF)||
3287 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3288 /* more than 32 bits? */
3291 NT_STATUS_INVALID_PARAMETER);
3294 #endif /* LARGE_SMB_OFF_T */
3296 /* quota_flags 2 bytes **/
3297 quotas.qflags = SVAL(pdata,40);
3299 /* unknown_2 6 NULL bytes follow*/
3301 /* now set the quotas */
3302 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3303 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3304 reply_doserror(req, ERRSRV, ERRerror);
3311 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3313 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3319 * sending this reply works fine,
3320 * but I'm not sure it's the same
3321 * like windows do...
3324 reply_outbuf(req, 10, 0);
3327 #if defined(HAVE_POSIX_ACLS)
3328 /****************************************************************************
3329 Utility function to count the number of entries in a POSIX acl.
3330 ****************************************************************************/
3332 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3334 unsigned int ace_count = 0;
3335 int entry_id = SMB_ACL_FIRST_ENTRY;
3336 SMB_ACL_ENTRY_T entry;
3338 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3340 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3341 entry_id = SMB_ACL_NEXT_ENTRY;
3348 /****************************************************************************
3349 Utility function to marshall a POSIX acl into wire format.
3350 ****************************************************************************/
3352 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3354 int entry_id = SMB_ACL_FIRST_ENTRY;
3355 SMB_ACL_ENTRY_T entry;
3357 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3358 SMB_ACL_TAG_T tagtype;
3359 SMB_ACL_PERMSET_T permset;
3360 unsigned char perms = 0;
3361 unsigned int own_grp;
3364 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3365 entry_id = SMB_ACL_NEXT_ENTRY;
3368 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3369 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3373 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3374 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3378 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3379 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3380 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3382 SCVAL(pdata,1,perms);
3385 case SMB_ACL_USER_OBJ:
3386 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3387 own_grp = (unsigned int)pst->st_uid;
3388 SIVAL(pdata,2,own_grp);
3393 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3395 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3398 own_grp = (unsigned int)*puid;
3399 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3400 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3401 SIVAL(pdata,2,own_grp);
3405 case SMB_ACL_GROUP_OBJ:
3406 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3407 own_grp = (unsigned int)pst->st_gid;
3408 SIVAL(pdata,2,own_grp);
3413 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3415 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3418 own_grp = (unsigned int)*pgid;
3419 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3420 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3421 SIVAL(pdata,2,own_grp);
3426 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3427 SIVAL(pdata,2,0xFFFFFFFF);
3428 SIVAL(pdata,6,0xFFFFFFFF);
3431 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3432 SIVAL(pdata,2,0xFFFFFFFF);
3433 SIVAL(pdata,6,0xFFFFFFFF);
3436 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3439 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3446 /****************************************************************************
3447 Store the FILE_UNIX_BASIC info.
3448 ****************************************************************************/
3450 static char *store_file_unix_basic(connection_struct *conn,
3453 const SMB_STRUCT_STAT *psbuf)
3455 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3456 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3458 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3461 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3464 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3465 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3466 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3469 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3473 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3477 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3480 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3484 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3488 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3491 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3495 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3502 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3503 * the chflags(2) (or equivalent) flags.
3505 * XXX: this really should be behind the VFS interface. To do this, we would
3506 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3507 * Each VFS module could then implement its own mapping as appropriate for the
3508 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3510 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3514 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3518 { UF_IMMUTABLE, EXT_IMMUTABLE },
3522 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3526 { UF_HIDDEN, EXT_HIDDEN },
3529 /* Do not remove. We need to guarantee that this array has at least one
3530 * entry to build on HP-UX.
3536 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3537 uint32 *smb_fflags, uint32 *smb_fmask)
3539 #ifdef HAVE_STAT_ST_FLAGS
3542 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3543 *smb_fmask |= info2_flags_map[i].smb_fflag;
3544 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3545 *smb_fflags |= info2_flags_map[i].smb_fflag;
3548 #endif /* HAVE_STAT_ST_FLAGS */
3551 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3552 const uint32 smb_fflags,
3553 const uint32 smb_fmask,
3556 #ifdef HAVE_STAT_ST_FLAGS
3557 uint32 max_fmask = 0;
3560 *stat_fflags = psbuf->st_flags;
3562 /* For each flags requested in smb_fmask, check the state of the
3563 * corresponding flag in smb_fflags and set or clear the matching
3567 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3568 max_fmask |= info2_flags_map[i].smb_fflag;
3569 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3570 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3571 *stat_fflags |= info2_flags_map[i].stat_fflag;
3573 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3578 /* If smb_fmask is asking to set any bits that are not supported by
3579 * our flag mappings, we should fail.
3581 if ((smb_fmask & max_fmask) != smb_fmask) {
3588 #endif /* HAVE_STAT_ST_FLAGS */
3592 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3593 * of file flags and birth (create) time.
3595 static char *store_file_unix_basic_info2(connection_struct *conn,
3598 const SMB_STRUCT_STAT *psbuf)
3600 uint32 file_flags = 0;
3601 uint32 flags_mask = 0;
3603 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3605 /* Create (birth) time 64 bit */
3606 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3609 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3610 SIVAL(pdata, 0, file_flags); /* flags */
3611 SIVAL(pdata, 4, flags_mask); /* mask */
3617 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3618 const struct stream_struct *streams,
3620 unsigned int max_data_bytes,
3621 unsigned int *data_size)
3624 unsigned int ofs = 0;
3626 for (i=0; i<num_streams; i++) {
3627 unsigned int next_offset;
3629 smb_ucs2_t *namebuf;
3631 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3634 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3635 return NT_STATUS_INVALID_PARAMETER;
3639 * name_buf is now null-terminated, we need to marshall as not
3645 if (ofs + 24 + namelen > max_data_bytes) {
3646 TALLOC_FREE(namebuf);
3647 return NT_STATUS_BUFFER_TOO_SMALL;
3650 SIVAL(data, ofs+4, namelen);
3651 SOFF_T(data, ofs+8, streams[i].size);
3652 SOFF_T(data, ofs+16, streams[i].alloc_size);
3653 memcpy(data+ofs+24, namebuf, namelen);
3654 TALLOC_FREE(namebuf);
3656 next_offset = ofs + 24 + namelen;
3658 if (i == num_streams-1) {
3659 SIVAL(data, ofs, 0);
3662 unsigned int align = ndr_align_size(next_offset, 8);
3664 if (next_offset + align > max_data_bytes) {
3665 return NT_STATUS_BUFFER_TOO_SMALL;
3668 memset(data+next_offset, 0, align);
3669 next_offset += align;
3671 SIVAL(data, ofs, next_offset - ofs);
3680 return NT_STATUS_OK;
3683 /****************************************************************************
3684 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3685 ****************************************************************************/
3687 static void call_trans2qpipeinfo(connection_struct *conn,
3688 struct smb_request *req,
3689 unsigned int tran_call,
3690 char **pparams, int total_params,
3691 char **ppdata, int total_data,
3692 unsigned int max_data_bytes)
3694 char *params = *pparams;
3695 char *pdata = *ppdata;
3696 unsigned int data_size = 0;
3697 unsigned int param_size = 2;
3699 smb_np_struct *p_pipe = NULL;
3702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3706 if (total_params < 4) {
3707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3711 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3712 if (p_pipe == NULL) {
3713 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3717 info_level = SVAL(params,2);
3719 *pparams = (char *)SMB_REALLOC(*pparams,2);
3720 if (*pparams == NULL) {
3721 reply_nterror(req, NT_STATUS_NO_MEMORY);
3726 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3727 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3728 if (*ppdata == NULL ) {
3729 reply_nterror(req, NT_STATUS_NO_MEMORY);
3734 switch (info_level) {
3735 case SMB_FILE_STANDARD_INFORMATION:
3737 SOFF_T(pdata,0,4096LL);
3744 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3748 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3754 /****************************************************************************
3755 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3756 file name or file id).
3757 ****************************************************************************/
3759 static void call_trans2qfilepathinfo(connection_struct *conn,
3760 struct smb_request *req,
3761 unsigned int tran_call,
3762 char **pparams, int total_params,
3763 char **ppdata, int total_data,
3764 unsigned int max_data_bytes)
3766 char *params = *pparams;
3767 char *pdata = *ppdata;
3768 char *dstart, *dend;
3772 SMB_OFF_T file_size=0;
3773 SMB_BIG_UINT allocation_size=0;
3774 unsigned int data_size = 0;
3775 unsigned int param_size = 2;
3776 SMB_STRUCT_STAT sbuf;
3777 char *dos_fname = NULL;
3783 bool delete_pending = False;
3785 time_t create_time, mtime, atime;
3786 struct timespec create_time_ts, mtime_ts, atime_ts;
3787 files_struct *fsp = NULL;
3788 struct file_id fileid;
3789 struct ea_list *ea_list = NULL;
3790 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3791 char *lock_data = NULL;
3792 TALLOC_CTX *ctx = talloc_tos();
3795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3801 if (tran_call == TRANSACT2_QFILEINFO) {
3802 if (total_params < 4) {
3803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3808 call_trans2qpipeinfo(conn, req, tran_call,
3809 pparams, total_params,
3815 fsp = file_fsp(SVAL(params,0));
3816 info_level = SVAL(params,2);
3818 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3820 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3821 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3825 /* Initial check for valid fsp ptr. */
3826 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3830 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3832 reply_nterror(req, NT_STATUS_NO_MEMORY);
3836 if(fsp->fake_file_handle) {
3838 * This is actually for the QUOTA_FAKE_FILE --metze
3841 /* We know this name is ok, it's already passed the checks. */
3843 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3845 * This is actually a QFILEINFO on a directory
3846 * handle (returned from an NT SMB). NT5.0 seems
3847 * to do this call. JRA.
3850 if (INFO_LEVEL_IS_UNIX(info_level)) {
3851 /* Always do lstat for UNIX calls. */
3852 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3853 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3854 reply_unixerror(req,ERRDOS,ERRbadpath);
3857 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3858 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3859 reply_unixerror(req, ERRDOS, ERRbadpath);
3863 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3864 delete_pending = get_delete_on_close_flag(fileid);
3867 * Original code - this is an open file.
3869 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3873 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3874 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3875 reply_unixerror(req, ERRDOS, ERRbadfid);
3878 pos = fsp->fh->position_information;
3879 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3880 delete_pending = get_delete_on_close_flag(fileid);
3881 access_mask = fsp->access_mask;
3885 NTSTATUS status = NT_STATUS_OK;
3888 if (total_params < 7) {
3889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3893 info_level = SVAL(params,0);
3895 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3897 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3898 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3902 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3904 STR_TERMINATE, &status);
3905 if (!NT_STATUS_IS_OK(status)) {
3906 reply_nterror(req, status);
3910 status = resolve_dfspath(ctx,
3912 req->flags2 & FLAGS2_DFS_PATHNAMES,
3915 if (!NT_STATUS_IS_OK(status)) {
3916 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3917 reply_botherror(req,
3918 NT_STATUS_PATH_NOT_COVERED,
3919 ERRSRV, ERRbadpath);
3921 reply_nterror(req, status);
3925 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3926 if (!NT_STATUS_IS_OK(status)) {
3927 reply_nterror(req, status);
3930 status = check_name(conn, fname);
3931 if (!NT_STATUS_IS_OK(status)) {
3932 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3933 reply_nterror(req, status);
3937 if (INFO_LEVEL_IS_UNIX(info_level)) {
3938 /* Always do lstat for UNIX calls. */
3939 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3940 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3941 reply_unixerror(req, ERRDOS, ERRbadpath);
3944 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3945 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3946 reply_unixerror(req, ERRDOS, ERRbadpath);
3950 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3951 delete_pending = get_delete_on_close_flag(fileid);
3952 if (delete_pending) {
3953 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3958 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3959 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3963 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3964 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3966 p = strrchr_m(fname,'/');
3972 mode = dos_mode(conn,fname,&sbuf);
3974 mode = FILE_ATTRIBUTE_NORMAL;
3976 nlink = sbuf.st_nlink;
3978 if (nlink && (mode&aDIR)) {
3982 if ((nlink > 0) && delete_pending) {
3986 fullpathname = fname;
3988 file_size = get_file_size(sbuf);
3990 /* Pull out any data sent here before we realloc. */
3991 switch (info_level) {
3992 case SMB_INFO_QUERY_EAS_FROM_LIST:
3994 /* Pull any EA list from the data portion. */
3997 if (total_data < 4) {
3999 req, NT_STATUS_INVALID_PARAMETER);
4002 ea_size = IVAL(pdata,0);
4004 if (total_data > 0 && ea_size != total_data) {
4005 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4006 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4008 req, NT_STATUS_INVALID_PARAMETER);
4012 if (!lp_ea_support(SNUM(conn))) {
4013 reply_doserror(req, ERRDOS,
4014 ERReasnotsupported);
4018 /* Pull out the list of names. */
4019 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4022 req, NT_STATUS_INVALID_PARAMETER);
4028 case SMB_QUERY_POSIX_LOCK:
4030 if (fsp == NULL || fsp->fh->fd == -1) {
4031 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4035 if (total_data != POSIX_LOCK_DATA_SIZE) {
4037 req, NT_STATUS_INVALID_PARAMETER);
4041 /* Copy the lock range data. */
4042 lock_data = (char *)TALLOC_MEMDUP(
4043 ctx, pdata, total_data);
4045 reply_nterror(req, NT_STATUS_NO_MEMORY);
4053 *pparams = (char *)SMB_REALLOC(*pparams,2);
4054 if (*pparams == NULL) {
4055 reply_nterror(req, NT_STATUS_NO_MEMORY);
4060 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4061 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4062 if (*ppdata == NULL ) {
4063 reply_nterror(req, NT_STATUS_NO_MEMORY);
4068 dend = dstart + data_size - 1;
4070 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4071 mtime_ts = get_mtimespec(&sbuf);
4072 atime_ts = get_atimespec(&sbuf);
4074 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4077 if (!null_timespec(fsp->pending_modtime)) {
4078 /* the pending modtime overrides the current modtime */
4079 mtime_ts = fsp->pending_modtime;
4083 /* Do we have this path open ? */
4084 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4085 fsp1 = file_find_di_first(fileid);
4086 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
4087 /* the pending modtime overrides the current modtime */
4088 mtime_ts = fsp1->pending_modtime;
4090 if (fsp1 && fsp1->initial_allocation_size) {
4091 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4095 if (lp_dos_filetime_resolution(SNUM(conn))) {
4096 dos_filetime_timespec(&create_time_ts);
4097 dos_filetime_timespec(&mtime_ts);
4098 dos_filetime_timespec(&atime_ts);
4101 create_time = convert_timespec_to_time_t(create_time_ts);
4102 mtime = convert_timespec_to_time_t(mtime_ts);
4103 atime = convert_timespec_to_time_t(atime_ts);
4105 /* NT expects the name to be in an exact form of the *full*
4106 filename. See the trans2 torture test */
4107 if (ISDOT(base_name)) {
4108 dos_fname = talloc_strdup(ctx, "\\");
4110 reply_nterror(req, NT_STATUS_NO_MEMORY);
4114 dos_fname = talloc_asprintf(ctx,
4118 reply_nterror(req, NT_STATUS_NO_MEMORY);
4121 string_replace(dos_fname, '/', '\\');
4124 switch (info_level) {
4125 case SMB_INFO_STANDARD:
4126 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4128 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4129 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4130 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4131 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4132 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4133 SSVAL(pdata,l1_attrFile,mode);
4136 case SMB_INFO_QUERY_EA_SIZE:
4138 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4139 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4141 srv_put_dos_date2(pdata,0,create_time);
4142 srv_put_dos_date2(pdata,4,atime);
4143 srv_put_dos_date2(pdata,8,mtime); /* write time */
4144 SIVAL(pdata,12,(uint32)file_size);
4145 SIVAL(pdata,16,(uint32)allocation_size);
4146 SSVAL(pdata,20,mode);
4147 SIVAL(pdata,22,ea_size);
4151 case SMB_INFO_IS_NAME_VALID:
4152 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4153 if (tran_call == TRANSACT2_QFILEINFO) {
4154 /* os/2 needs this ? really ?*/
4155 reply_doserror(req, ERRDOS, ERRbadfunc);
4162 case SMB_INFO_QUERY_EAS_FROM_LIST:
4164 size_t total_ea_len = 0;
4165 struct ea_list *ea_file_list = NULL;
4167 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4169 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4170 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4172 if (!ea_list || (total_ea_len > data_size)) {
4174 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4178 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4182 case SMB_INFO_QUERY_ALL_EAS:
4184 /* We have data_size bytes to put EA's into. */
4185 size_t total_ea_len = 0;
4187 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4189 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4190 if (!ea_list || (total_ea_len > data_size)) {
4192 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4196 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4200 case SMB_FILE_BASIC_INFORMATION:
4201 case SMB_QUERY_FILE_BASIC_INFO:
4203 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4204 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4205 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4207 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4211 put_long_date_timespec(pdata,create_time_ts);
4212 put_long_date_timespec(pdata+8,atime_ts);
4213 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4214 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4215 SIVAL(pdata,32,mode);
4217 DEBUG(5,("SMB_QFBI - "));
4218 DEBUG(5,("create: %s ", ctime(&create_time)));
4219 DEBUG(5,("access: %s ", ctime(&atime)));
4220 DEBUG(5,("write: %s ", ctime(&mtime)));
4221 DEBUG(5,("change: %s ", ctime(&mtime)));
4222 DEBUG(5,("mode: %x\n", mode));
4225 case SMB_FILE_STANDARD_INFORMATION:
4226 case SMB_QUERY_FILE_STANDARD_INFO:
4228 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4230 SOFF_T(pdata,0,allocation_size);
4231 SOFF_T(pdata,8,file_size);
4232 SIVAL(pdata,16,nlink);
4233 SCVAL(pdata,20,delete_pending?1:0);
4234 SCVAL(pdata,21,(mode&aDIR)?1:0);
4235 SSVAL(pdata,22,0); /* Padding. */
4238 case SMB_FILE_EA_INFORMATION:
4239 case SMB_QUERY_FILE_EA_INFO:
4241 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4242 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4244 SIVAL(pdata,0,ea_size);
4248 /* Get the 8.3 name - used if NT SMB was negotiated. */
4249 case SMB_QUERY_FILE_ALT_NAME_INFO:
4250 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4252 char mangled_name[13];
4253 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4254 if (!name_to_8_3(base_name,mangled_name,
4255 True,conn->params)) {
4258 NT_STATUS_NO_MEMORY);
4260 len = srvstr_push(dstart, req->flags2,
4261 pdata+4, mangled_name,
4262 PTR_DIFF(dend, pdata+4),
4264 data_size = 4 + len;
4269 case SMB_QUERY_FILE_NAME_INFO:
4271 this must be *exactly* right for ACLs on mapped drives to work
4273 len = srvstr_push(dstart, req->flags2,
4275 PTR_DIFF(dend, pdata+4),
4277 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4278 data_size = 4 + len;
4282 case SMB_FILE_ALLOCATION_INFORMATION:
4283 case SMB_QUERY_FILE_ALLOCATION_INFO:
4284 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4286 SOFF_T(pdata,0,allocation_size);
4289 case SMB_FILE_END_OF_FILE_INFORMATION:
4290 case SMB_QUERY_FILE_END_OF_FILEINFO:
4291 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4293 SOFF_T(pdata,0,file_size);
4296 case SMB_QUERY_FILE_ALL_INFO:
4297 case SMB_FILE_ALL_INFORMATION:
4299 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4300 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4301 put_long_date_timespec(pdata,create_time_ts);
4302 put_long_date_timespec(pdata+8,atime_ts);
4303 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4304 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4305 SIVAL(pdata,32,mode);
4306 SIVAL(pdata,36,0); /* padding. */
4308 SOFF_T(pdata,0,allocation_size);
4309 SOFF_T(pdata,8,file_size);
4310 SIVAL(pdata,16,nlink);
4311 SCVAL(pdata,20,delete_pending);
4312 SCVAL(pdata,21,(mode&aDIR)?1:0);
4315 SIVAL(pdata,0,ea_size);
4316 pdata += 4; /* EA info */
4317 len = srvstr_push(dstart, req->flags2,
4319 PTR_DIFF(dend, pdata+4),
4323 data_size = PTR_DIFF(pdata,(*ppdata));
4326 case SMB_FILE_INTERNAL_INFORMATION:
4327 /* This should be an index number - looks like
4330 I think this causes us to fail the IFSKIT
4331 BasicFileInformationTest. -tpot */
4333 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4334 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4335 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4339 case SMB_FILE_ACCESS_INFORMATION:
4340 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4341 SIVAL(pdata,0,access_mask);
4345 case SMB_FILE_NAME_INFORMATION:
4346 /* Pathname with leading '\'. */
4349 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4350 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4351 SIVAL(pdata,0,byte_len);
4352 data_size = 4 + byte_len;
4356 case SMB_FILE_DISPOSITION_INFORMATION:
4357 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4359 SCVAL(pdata,0,delete_pending);
4362 case SMB_FILE_POSITION_INFORMATION:
4363 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4365 SOFF_T(pdata,0,pos);
4368 case SMB_FILE_MODE_INFORMATION:
4369 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4370 SIVAL(pdata,0,mode);
4374 case SMB_FILE_ALIGNMENT_INFORMATION:
4375 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4376 SIVAL(pdata,0,0); /* No alignment needed. */
4381 * NT4 server just returns "invalid query" to this - if we try
4382 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4385 /* The first statement above is false - verified using Thursby
4386 * client against NT4 -- gcolley.
4388 case SMB_QUERY_FILE_STREAM_INFO:
4389 case SMB_FILE_STREAM_INFORMATION: {
4390 unsigned int num_streams;
4391 struct stream_struct *streams;
4394 DEBUG(10,("call_trans2qfilepathinfo: "
4395 "SMB_FILE_STREAM_INFORMATION\n"));
4397 status = SMB_VFS_STREAMINFO(
4398 conn, fsp, fname, talloc_tos(),
4399 &num_streams, &streams);
4401 if (!NT_STATUS_IS_OK(status)) {
4402 DEBUG(10, ("could not get stream info: %s\n",
4403 nt_errstr(status)));
4404 reply_nterror(req, status);
4408 status = marshall_stream_info(num_streams, streams,
4409 pdata, max_data_bytes,
4412 if (!NT_STATUS_IS_OK(status)) {
4413 DEBUG(10, ("marshall_stream_info failed: %s\n",
4414 nt_errstr(status)));
4415 reply_nterror(req, status);
4419 TALLOC_FREE(streams);
4423 case SMB_QUERY_COMPRESSION_INFO:
4424 case SMB_FILE_COMPRESSION_INFORMATION:
4425 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4426 SOFF_T(pdata,0,file_size);
4427 SIVAL(pdata,8,0); /* ??? */
4428 SIVAL(pdata,12,0); /* ??? */
4432 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4433 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4434 put_long_date_timespec(pdata,create_time_ts);
4435 put_long_date_timespec(pdata+8,atime_ts);
4436 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4437 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4438 SOFF_T(pdata,32,allocation_size);
4439 SOFF_T(pdata,40,file_size);
4440 SIVAL(pdata,48,mode);
4441 SIVAL(pdata,52,0); /* ??? */
4445 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4446 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4447 SIVAL(pdata,0,mode);
4453 * CIFS UNIX Extensions.
4456 case SMB_QUERY_FILE_UNIX_BASIC:
4458 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4459 data_size = PTR_DIFF(pdata,(*ppdata));
4463 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4465 for (i=0; i<100; i++)
4466 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4472 case SMB_QUERY_FILE_UNIX_INFO2:
4474 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4475 data_size = PTR_DIFF(pdata,(*ppdata));
4479 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4481 for (i=0; i<100; i++)
4482 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4488 case SMB_QUERY_FILE_UNIX_LINK:
4490 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4493 reply_nterror(req, NT_STATUS_NO_MEMORY);
4497 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4499 if(!S_ISLNK(sbuf.st_mode)) {
4500 reply_unixerror(req, ERRSRV,
4505 reply_unixerror(req, ERRDOS, ERRbadlink);
4508 len = SMB_VFS_READLINK(conn,fullpathname,
4511 reply_unixerror(req, ERRDOS,
4516 len = srvstr_push(dstart, req->flags2,
4518 PTR_DIFF(dend, pdata),
4521 data_size = PTR_DIFF(pdata,(*ppdata));
4526 #if defined(HAVE_POSIX_ACLS)
4527 case SMB_QUERY_POSIX_ACL:
4529 SMB_ACL_T file_acl = NULL;
4530 SMB_ACL_T def_acl = NULL;
4531 uint16 num_file_acls = 0;
4532 uint16 num_def_acls = 0;
4534 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4535 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4537 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4540 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4541 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4545 NT_STATUS_NOT_IMPLEMENTED);
4549 if (S_ISDIR(sbuf.st_mode)) {
4550 if (fsp && fsp->is_directory) {
4551 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4553 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4555 def_acl = free_empty_sys_acl(conn, def_acl);
4558 num_file_acls = count_acl_entries(conn, file_acl);
4559 num_def_acls = count_acl_entries(conn, def_acl);
4561 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4562 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4564 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4565 SMB_POSIX_ACL_HEADER_SIZE) ));
4567 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4570 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4574 NT_STATUS_BUFFER_TOO_SMALL);
4578 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4579 SSVAL(pdata,2,num_file_acls);
4580 SSVAL(pdata,4,num_def_acls);
4581 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4583 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4586 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4589 req, NT_STATUS_INTERNAL_ERROR);
4592 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4594 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4597 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4601 NT_STATUS_INTERNAL_ERROR);
4606 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4609 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4611 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4617 case SMB_QUERY_POSIX_LOCK:
4619 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4621 SMB_BIG_UINT offset;
4623 enum brl_type lock_type;
4625 if (total_data != POSIX_LOCK_DATA_SIZE) {
4627 req, NT_STATUS_INVALID_PARAMETER);
4631 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4632 case POSIX_LOCK_TYPE_READ:
4633 lock_type = READ_LOCK;
4635 case POSIX_LOCK_TYPE_WRITE:
4636 lock_type = WRITE_LOCK;
4638 case POSIX_LOCK_TYPE_UNLOCK:
4640 /* There's no point in asking for an unlock... */
4643 NT_STATUS_INVALID_PARAMETER);
4647 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4648 #if defined(HAVE_LONGLONG)
4649 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4650 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4651 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4652 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4653 #else /* HAVE_LONGLONG */
4654 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4655 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4656 #endif /* HAVE_LONGLONG */
4658 status = query_lock(fsp,
4665 if (ERROR_WAS_LOCK_DENIED(status)) {
4666 /* Here we need to report who has it locked... */
4667 data_size = POSIX_LOCK_DATA_SIZE;
4669 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4670 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4671 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4672 #if defined(HAVE_LONGLONG)
4673 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4674 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4675 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4676 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4677 #else /* HAVE_LONGLONG */
4678 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4679 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4680 #endif /* HAVE_LONGLONG */
4682 } else if (NT_STATUS_IS_OK(status)) {
4683 /* For success we just return a copy of what we sent
4684 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4685 data_size = POSIX_LOCK_DATA_SIZE;
4686 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4687 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4689 reply_nterror(req, status);
4696 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4700 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4706 /****************************************************************************
4707 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4709 ****************************************************************************/
4711 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4712 connection_struct *conn,
4713 const char *oldname_in,
4714 const char *newname_in)
4716 SMB_STRUCT_STAT sbuf1, sbuf2;
4717 char *last_component_oldname = NULL;
4718 char *last_component_newname = NULL;
4719 char *oldname = NULL;
4720 char *newname = NULL;
4721 NTSTATUS status = NT_STATUS_OK;
4726 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4727 &last_component_oldname, &sbuf1);
4728 if (!NT_STATUS_IS_OK(status)) {
4732 status = check_name(conn, oldname);
4733 if (!NT_STATUS_IS_OK(status)) {
4737 /* source must already exist. */
4738 if (!VALID_STAT(sbuf1)) {
4739 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4742 status = unix_convert(ctx, conn, newname_in, False, &newname,
4743 &last_component_newname, &sbuf2);
4744 if (!NT_STATUS_IS_OK(status)) {
4748 status = check_name(conn, newname);
4749 if (!NT_STATUS_IS_OK(status)) {
4753 /* Disallow if newname already exists. */
4754 if (VALID_STAT(sbuf2)) {
4755 return NT_STATUS_OBJECT_NAME_COLLISION;
4758 /* No links from a directory. */
4759 if (S_ISDIR(sbuf1.st_mode)) {
4760 return NT_STATUS_FILE_IS_A_DIRECTORY;
4763 /* Ensure this is within the share. */
4764 status = check_reduced_name(conn, oldname);
4765 if (!NT_STATUS_IS_OK(status)) {
4769 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4771 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4772 status = map_nt_error_from_unix(errno);
4773 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4774 nt_errstr(status), newname, oldname));
4780 /****************************************************************************
4781 Deal with setting the time from any of the setfilepathinfo functions.
4782 ****************************************************************************/
4784 static NTSTATUS smb_set_file_time(connection_struct *conn,
4787 const SMB_STRUCT_STAT *psbuf,
4788 struct timespec ts[2],
4789 bool setting_write_time)
4792 FILE_NOTIFY_CHANGE_LAST_ACCESS
4793 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4795 if (!VALID_STAT(*psbuf)) {
4796 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4799 /* get some defaults (no modifications) if any info is zero or -1. */
4800 if (null_timespec(ts[0])) {
4801 ts[0] = get_atimespec(psbuf);
4802 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4805 if (null_timespec(ts[1])) {
4806 ts[1] = get_mtimespec(psbuf);
4807 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4810 if (!setting_write_time) {
4811 /* ts[1] comes from change time, not write time. */
4812 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4815 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4816 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4819 * Try and set the times of this file if
4820 * they are different from the current values.
4824 struct timespec mts = get_mtimespec(psbuf);
4825 struct timespec ats = get_atimespec(psbuf);
4826 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4827 return NT_STATUS_OK;
4833 * This was a setfileinfo on an open file.
4834 * NT does this a lot. We also need to
4835 * set the time here, as it can be read by
4836 * FindFirst/FindNext and with the patch for bug #2045
4837 * in smbd/fileio.c it ensures that this timestamp is
4838 * kept sticky even after a write. We save the request
4839 * away and will set it on file close and after a write. JRA.
4842 if (!null_timespec(ts[1])) {
4843 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4844 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4845 fsp_set_pending_modtime(fsp, ts[1]);
4849 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4851 if(file_ntimes(conn, fname, ts)!=0) {
4852 return map_nt_error_from_unix(errno);
4854 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4856 return NT_STATUS_OK;
4859 /****************************************************************************
4860 Deal with setting the dosmode from any of the setfilepathinfo functions.
4861 ****************************************************************************/
4863 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4865 SMB_STRUCT_STAT *psbuf,
4868 if (!VALID_STAT(*psbuf)) {
4869 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4873 if (S_ISDIR(psbuf->st_mode)) {
4880 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4882 /* check the mode isn't different, before changing it */
4883 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4885 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4886 fname, (unsigned int)dosmode ));
4888 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4889 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4890 fname, strerror(errno)));
4891 return map_nt_error_from_unix(errno);
4894 return NT_STATUS_OK;
4897 /****************************************************************************
4898 Deal with setting the size from any of the setfilepathinfo functions.
4899 ****************************************************************************/
4901 static NTSTATUS smb_set_file_size(connection_struct *conn,
4902 struct smb_request *req,
4905 SMB_STRUCT_STAT *psbuf,
4908 NTSTATUS status = NT_STATUS_OK;
4909 files_struct *new_fsp = NULL;
4911 if (!VALID_STAT(*psbuf)) {
4912 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4915 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4917 if (size == get_file_size(*psbuf)) {
4918 return NT_STATUS_OK;
4921 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4922 fname, (double)size ));
4924 if (fsp && fsp->fh->fd != -1) {
4925 /* Handle based call. */
4926 if (vfs_set_filelen(fsp, size) == -1) {
4927 return map_nt_error_from_unix(errno);
4929 return NT_STATUS_OK;
4932 status = open_file_ntcreate(conn, req, fname, psbuf,
4933 FILE_WRITE_ATTRIBUTES,
4934 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4937 FILE_ATTRIBUTE_NORMAL,
4938 FORCE_OPLOCK_BREAK_TO_NONE,
4941 if (!NT_STATUS_IS_OK(status)) {
4942 /* NB. We check for open_was_deferred in the caller. */
4946 if (vfs_set_filelen(new_fsp, size) == -1) {
4947 status = map_nt_error_from_unix(errno);
4948 close_file(new_fsp,NORMAL_CLOSE);
4952 close_file(new_fsp,NORMAL_CLOSE);
4953 return NT_STATUS_OK;
4956 /****************************************************************************
4957 Deal with SMB_INFO_SET_EA.
4958 ****************************************************************************/
4960 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4966 struct ea_list *ea_list = NULL;
4967 TALLOC_CTX *ctx = NULL;
4968 NTSTATUS status = NT_STATUS_OK;
4970 if (total_data < 10) {
4972 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4973 length. They seem to have no effect. Bug #3212. JRA */
4975 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4976 /* We're done. We only get EA info in this call. */
4977 return NT_STATUS_OK;
4980 return NT_STATUS_INVALID_PARAMETER;
4983 if (IVAL(pdata,0) > total_data) {
4984 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4985 IVAL(pdata,0), (unsigned int)total_data));
4986 return NT_STATUS_INVALID_PARAMETER;
4990 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4992 return NT_STATUS_INVALID_PARAMETER;
4994 status = set_ea(conn, fsp, fname, ea_list);
4999 /****************************************************************************
5000 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5001 ****************************************************************************/
5003 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5008 SMB_STRUCT_STAT *psbuf)
5010 NTSTATUS status = NT_STATUS_OK;
5011 bool delete_on_close;
5014 if (total_data < 1) {
5015 return NT_STATUS_INVALID_PARAMETER;
5019 return NT_STATUS_INVALID_HANDLE;
5022 delete_on_close = (CVAL(pdata,0) ? True : False);
5023 dosmode = dos_mode(conn, fname, psbuf);
5025 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5026 "delete_on_close = %u\n",
5028 (unsigned int)dosmode,
5029 (unsigned int)delete_on_close ));
5031 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5033 if (!NT_STATUS_IS_OK(status)) {
5037 /* The set is across all open files on this dev/inode pair. */
5038 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
5039 return NT_STATUS_ACCESS_DENIED;
5041 return NT_STATUS_OK;
5044 /****************************************************************************
5045 Deal with SMB_FILE_POSITION_INFORMATION.
5046 ****************************************************************************/
5048 static NTSTATUS smb_file_position_information(connection_struct *conn,
5053 SMB_BIG_UINT position_information;
5055 if (total_data < 8) {
5056 return NT_STATUS_INVALID_PARAMETER;
5060 /* Ignore on pathname based set. */
5061 return NT_STATUS_OK;
5064 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5065 #ifdef LARGE_SMB_OFF_T
5066 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5067 #else /* LARGE_SMB_OFF_T */
5068 if (IVAL(pdata,4) != 0) {
5069 /* more than 32 bits? */
5070 return NT_STATUS_INVALID_PARAMETER;
5072 #endif /* LARGE_SMB_OFF_T */
5074 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5075 fsp->fsp_name, (double)position_information ));
5076 fsp->fh->position_information = position_information;
5077 return NT_STATUS_OK;
5080 /****************************************************************************
5081 Deal with SMB_FILE_MODE_INFORMATION.
5082 ****************************************************************************/
5084 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5090 if (total_data < 4) {
5091 return NT_STATUS_INVALID_PARAMETER;
5093 mode = IVAL(pdata,0);
5094 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5095 return NT_STATUS_INVALID_PARAMETER;
5097 return NT_STATUS_OK;
5100 /****************************************************************************
5101 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5102 ****************************************************************************/
5104 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5105 struct smb_request *req,
5110 char *link_target = NULL;
5111 const char *newname = fname;
5112 NTSTATUS status = NT_STATUS_OK;
5113 TALLOC_CTX *ctx = talloc_tos();
5115 /* Set a symbolic link. */
5116 /* Don't allow this if follow links is false. */
5118 if (total_data == 0) {
5119 return NT_STATUS_INVALID_PARAMETER;
5122 if (!lp_symlinks(SNUM(conn))) {
5123 return NT_STATUS_ACCESS_DENIED;
5126 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5127 total_data, STR_TERMINATE);
5130 return NT_STATUS_INVALID_PARAMETER;
5133 /* !widelinks forces the target path to be within the share. */
5134 /* This means we can interpret the target as a pathname. */
5135 if (!lp_widelinks(SNUM(conn))) {
5136 char *rel_name = NULL;
5137 char *last_dirp = NULL;
5139 if (*link_target == '/') {
5140 /* No absolute paths allowed. */
5141 return NT_STATUS_ACCESS_DENIED;
5143 rel_name = talloc_strdup(ctx,newname);
5145 return NT_STATUS_NO_MEMORY;
5147 last_dirp = strrchr_m(rel_name, '/');
5149 last_dirp[1] = '\0';
5151 rel_name = talloc_strdup(ctx,"./");
5153 return NT_STATUS_NO_MEMORY;
5156 rel_name = talloc_asprintf_append(rel_name,
5160 return NT_STATUS_NO_MEMORY;
5163 status = check_name(conn, rel_name);
5164 if (!NT_STATUS_IS_OK(status)) {
5169 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5170 newname, link_target ));
5172 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5173 return map_nt_error_from_unix(errno);
5176 return NT_STATUS_OK;
5179 /****************************************************************************
5180 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5181 ****************************************************************************/
5183 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5184 struct smb_request *req,
5185 const char *pdata, int total_data,
5188 char *oldname = NULL;
5189 TALLOC_CTX *ctx = talloc_tos();
5190 NTSTATUS status = NT_STATUS_OK;
5192 /* Set a hard link. */
5193 if (total_data == 0) {
5194 return NT_STATUS_INVALID_PARAMETER;
5197 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5198 total_data, STR_TERMINATE, &status);
5199 if (!NT_STATUS_IS_OK(status)) {
5203 status = resolve_dfspath(ctx, conn,
5204 req->flags2 & FLAGS2_DFS_PATHNAMES,
5207 if (!NT_STATUS_IS_OK(status)) {
5211 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5214 return hardlink_internals(ctx, conn, oldname, fname);
5217 /****************************************************************************
5218 Deal with SMB_FILE_RENAME_INFORMATION.
5219 ****************************************************************************/
5221 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5222 struct smb_request *req,
5231 char *newname = NULL;
5232 char *base_name = NULL;
5233 bool dest_has_wcard = False;
5234 NTSTATUS status = NT_STATUS_OK;
5236 TALLOC_CTX *ctx = talloc_tos();
5238 if (total_data < 13) {
5239 return NT_STATUS_INVALID_PARAMETER;
5242 overwrite = (CVAL(pdata,0) ? True : False);
5243 root_fid = IVAL(pdata,4);
5244 len = IVAL(pdata,8);
5246 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5247 return NT_STATUS_INVALID_PARAMETER;
5250 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5253 if (!NT_STATUS_IS_OK(status)) {
5257 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5260 status = resolve_dfspath_wcard(ctx, conn,
5261 req->flags2 & FLAGS2_DFS_PATHNAMES,
5265 if (!NT_STATUS_IS_OK(status)) {
5269 /* Check the new name has no '/' characters. */
5270 if (strchr_m(newname, '/')) {
5271 return NT_STATUS_NOT_SUPPORTED;
5274 /* Create the base directory. */
5275 base_name = talloc_strdup(ctx, fname);
5277 return NT_STATUS_NO_MEMORY;
5279 p = strrchr_m(base_name, '/');
5283 base_name = talloc_strdup(ctx, "./");
5285 return NT_STATUS_NO_MEMORY;
5288 /* Append the new name. */
5289 base_name = talloc_asprintf_append(base_name,
5293 return NT_STATUS_NO_MEMORY;
5297 SMB_STRUCT_STAT sbuf;
5298 char *newname_last_component = NULL;
5302 status = unix_convert(ctx, conn, newname, False,
5304 &newname_last_component,
5307 /* If an error we expect this to be
5308 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5310 if (!NT_STATUS_IS_OK(status)
5311 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5316 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5317 fsp->fnum, fsp->fsp_name, base_name ));
5318 status = rename_internals_fsp(conn, fsp, base_name,
5319 newname_last_component, 0,
5322 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5323 fname, base_name ));
5324 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5325 overwrite, False, dest_has_wcard,
5326 FILE_WRITE_ATTRIBUTES);
5332 /****************************************************************************
5333 Deal with SMB_SET_POSIX_ACL.
5334 ****************************************************************************/
5336 #if defined(HAVE_POSIX_ACLS)
5337 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5342 SMB_STRUCT_STAT *psbuf)
5344 uint16 posix_acl_version;
5345 uint16 num_file_acls;
5346 uint16 num_def_acls;
5347 bool valid_file_acls = True;
5348 bool valid_def_acls = True;
5350 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5351 return NT_STATUS_INVALID_PARAMETER;
5353 posix_acl_version = SVAL(pdata,0);
5354 num_file_acls = SVAL(pdata,2);
5355 num_def_acls = SVAL(pdata,4);
5357 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5358 valid_file_acls = False;
5362 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5363 valid_def_acls = False;
5367 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5368 return NT_STATUS_INVALID_PARAMETER;
5371 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5372 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5373 return NT_STATUS_INVALID_PARAMETER;
5376 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5377 fname ? fname : fsp->fsp_name,
5378 (unsigned int)num_file_acls,
5379 (unsigned int)num_def_acls));
5381 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5382 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5383 return map_nt_error_from_unix(errno);
5386 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5387 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5388 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5389 return map_nt_error_from_unix(errno);
5391 return NT_STATUS_OK;
5395 /****************************************************************************
5396 Deal with SMB_SET_POSIX_LOCK.
5397 ****************************************************************************/
5399 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5400 const struct smb_request *req,
5406 SMB_BIG_UINT offset;
5408 bool blocking_lock = False;
5409 enum brl_type lock_type;
5411 NTSTATUS status = NT_STATUS_OK;
5413 if (fsp == NULL || fsp->fh->fd == -1) {
5414 return NT_STATUS_INVALID_HANDLE;
5417 if (total_data != POSIX_LOCK_DATA_SIZE) {
5418 return NT_STATUS_INVALID_PARAMETER;
5421 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5422 case POSIX_LOCK_TYPE_READ:
5423 lock_type = READ_LOCK;
5425 case POSIX_LOCK_TYPE_WRITE:
5426 /* Return the right POSIX-mappable error code for files opened read-only. */
5427 if (!fsp->can_write) {
5428 return NT_STATUS_INVALID_HANDLE;
5430 lock_type = WRITE_LOCK;
5432 case POSIX_LOCK_TYPE_UNLOCK:
5433 lock_type = UNLOCK_LOCK;
5436 return NT_STATUS_INVALID_PARAMETER;
5439 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5440 blocking_lock = False;
5441 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5442 blocking_lock = True;
5444 return NT_STATUS_INVALID_PARAMETER;
5447 if (!lp_blocking_locks(SNUM(conn))) {
5448 blocking_lock = False;
5451 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5452 #if defined(HAVE_LONGLONG)
5453 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5454 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5455 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5456 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5457 #else /* HAVE_LONGLONG */
5458 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5459 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5460 #endif /* HAVE_LONGLONG */
5462 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5463 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5465 (unsigned int)lock_type,
5466 (unsigned int)lock_pid,
5470 if (lock_type == UNLOCK_LOCK) {
5471 status = do_unlock(smbd_messaging_context(),
5478 uint32 block_smbpid;
5480 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5491 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5493 * A blocking lock was requested. Package up
5494 * this smb into a queued request and push it
5495 * onto the blocking lock queue.
5497 if(push_blocking_lock_request(br_lck,
5500 -1, /* infinite timeout. */
5508 TALLOC_FREE(br_lck);
5512 TALLOC_FREE(br_lck);
5518 /****************************************************************************
5519 Deal with SMB_INFO_STANDARD.
5520 ****************************************************************************/
5522 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5527 const SMB_STRUCT_STAT *psbuf)
5529 struct timespec ts[2];
5531 if (total_data < 12) {
5532 return NT_STATUS_INVALID_PARAMETER;
5536 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5538 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5540 DEBUG(10,("smb_set_info_standard: file %s\n",
5541 fname ? fname : fsp->fsp_name ));
5543 return smb_set_file_time(conn,
5551 /****************************************************************************
5552 Deal with SMB_SET_FILE_BASIC_INFO.
5553 ****************************************************************************/
5555 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5560 SMB_STRUCT_STAT *psbuf)
5562 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5563 struct timespec write_time;
5564 struct timespec changed_time;
5566 struct timespec ts[2];
5567 NTSTATUS status = NT_STATUS_OK;
5568 bool setting_write_time = true;
5570 if (total_data < 36) {
5571 return NT_STATUS_INVALID_PARAMETER;
5574 /* Set the attributes */
5575 dosmode = IVAL(pdata,32);
5576 status = smb_set_file_dosmode(conn,
5580 if (!NT_STATUS_IS_OK(status)) {
5584 /* Ignore create time at offset pdata. */
5587 ts[0] = interpret_long_date(pdata+8);
5589 write_time = interpret_long_date(pdata+16);
5590 changed_time = interpret_long_date(pdata+24);
5593 ts[1] = timespec_min(&write_time, &changed_time);
5595 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5599 /* Prefer a defined time to an undefined one. */
5600 if (null_timespec(ts[1])) {
5601 if (null_timespec(write_time)) {
5602 ts[1] = changed_time;
5603 setting_write_time = false;
5609 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5610 fname ? fname : fsp->fsp_name ));
5612 return smb_set_file_time(conn,
5617 setting_write_time);
5620 /****************************************************************************
5621 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5622 ****************************************************************************/
5624 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5625 struct smb_request *req,
5630 SMB_STRUCT_STAT *psbuf)
5632 SMB_BIG_UINT allocation_size = 0;
5633 NTSTATUS status = NT_STATUS_OK;
5634 files_struct *new_fsp = NULL;
5636 if (!VALID_STAT(*psbuf)) {
5637 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5640 if (total_data < 8) {
5641 return NT_STATUS_INVALID_PARAMETER;
5644 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5645 #ifdef LARGE_SMB_OFF_T
5646 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5647 #else /* LARGE_SMB_OFF_T */
5648 if (IVAL(pdata,4) != 0) {
5649 /* more than 32 bits? */
5650 return NT_STATUS_INVALID_PARAMETER;
5652 #endif /* LARGE_SMB_OFF_T */
5654 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5655 fname, (double)allocation_size ));
5657 if (allocation_size) {
5658 allocation_size = smb_roundup(conn, allocation_size);
5661 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5662 fname, (double)allocation_size ));
5664 if (fsp && fsp->fh->fd != -1) {
5665 /* Open file handle. */
5666 /* Only change if needed. */
5667 if (allocation_size != get_file_size(*psbuf)) {
5668 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5669 return map_nt_error_from_unix(errno);
5672 /* But always update the time. */
5673 if (null_timespec(fsp->pending_modtime)) {
5675 * This is equivalent to a write. Ensure it's seen immediately
5676 * if there are no pending writes.
5678 set_filetime(fsp->conn, fsp->fsp_name,
5679 timespec_current());
5681 return NT_STATUS_OK;
5684 /* Pathname or stat or directory file. */
5686 status = open_file_ntcreate(conn, req, fname, psbuf,
5688 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5691 FILE_ATTRIBUTE_NORMAL,
5692 FORCE_OPLOCK_BREAK_TO_NONE,
5695 if (!NT_STATUS_IS_OK(status)) {
5696 /* NB. We check for open_was_deferred in the caller. */
5700 /* Only change if needed. */
5701 if (allocation_size != get_file_size(*psbuf)) {
5702 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5703 status = map_nt_error_from_unix(errno);
5704 close_file(new_fsp,NORMAL_CLOSE);
5709 /* Changing the allocation size should set the last mod time. */
5710 /* Don't need to call set_filetime as this will be flushed on
5713 fsp_set_pending_modtime(new_fsp, timespec_current());
5715 close_file(new_fsp,NORMAL_CLOSE);
5716 return NT_STATUS_OK;
5719 /****************************************************************************
5720 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5721 ****************************************************************************/
5723 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5724 struct smb_request *req,
5729 SMB_STRUCT_STAT *psbuf)
5733 if (total_data < 8) {
5734 return NT_STATUS_INVALID_PARAMETER;
5737 size = IVAL(pdata,0);
5738 #ifdef LARGE_SMB_OFF_T
5739 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5740 #else /* LARGE_SMB_OFF_T */
5741 if (IVAL(pdata,4) != 0) {
5742 /* more than 32 bits? */
5743 return NT_STATUS_INVALID_PARAMETER;
5745 #endif /* LARGE_SMB_OFF_T */
5746 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5747 "file %s to %.0f\n", fname, (double)size ));
5749 return smb_set_file_size(conn, req,
5756 /****************************************************************************
5757 Allow a UNIX info mknod.
5758 ****************************************************************************/
5760 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5764 SMB_STRUCT_STAT *psbuf)
5766 uint32 file_type = IVAL(pdata,56);
5767 #if defined(HAVE_MAKEDEV)
5768 uint32 dev_major = IVAL(pdata,60);
5769 uint32 dev_minor = IVAL(pdata,68);
5771 SMB_DEV_T dev = (SMB_DEV_T)0;
5772 uint32 raw_unixmode = IVAL(pdata,84);
5776 if (total_data < 100) {
5777 return NT_STATUS_INVALID_PARAMETER;
5780 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5781 if (!NT_STATUS_IS_OK(status)) {
5785 #if defined(HAVE_MAKEDEV)
5786 dev = makedev(dev_major, dev_minor);
5789 switch (file_type) {
5790 #if defined(S_IFIFO)
5791 case UNIX_TYPE_FIFO:
5792 unixmode |= S_IFIFO;
5795 #if defined(S_IFSOCK)
5796 case UNIX_TYPE_SOCKET:
5797 unixmode |= S_IFSOCK;
5800 #if defined(S_IFCHR)
5801 case UNIX_TYPE_CHARDEV:
5802 unixmode |= S_IFCHR;
5805 #if defined(S_IFBLK)
5806 case UNIX_TYPE_BLKDEV:
5807 unixmode |= S_IFBLK;
5811 return NT_STATUS_INVALID_PARAMETER;
5814 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5815 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5817 /* Ok - do the mknod. */
5818 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5819 return map_nt_error_from_unix(errno);
5822 /* If any of the other "set" calls fail we
5823 * don't want to end up with a half-constructed mknod.
5826 if (lp_inherit_perms(SNUM(conn))) {
5828 conn, parent_dirname(fname),
5832 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5833 status = map_nt_error_from_unix(errno);
5834 SMB_VFS_UNLINK(conn,fname);
5837 return NT_STATUS_OK;
5840 /****************************************************************************
5841 Deal with SMB_SET_FILE_UNIX_BASIC.
5842 ****************************************************************************/
5844 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5845 struct smb_request *req,
5850 SMB_STRUCT_STAT *psbuf)
5852 struct timespec ts[2];
5853 uint32 raw_unixmode;
5856 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5857 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5858 NTSTATUS status = NT_STATUS_OK;
5859 bool delete_on_fail = False;
5860 enum perm_type ptype;
5862 if (total_data < 100) {
5863 return NT_STATUS_INVALID_PARAMETER;
5866 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5867 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5868 size=IVAL(pdata,0); /* first 8 Bytes are size */
5869 #ifdef LARGE_SMB_OFF_T
5870 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5871 #else /* LARGE_SMB_OFF_T */
5872 if (IVAL(pdata,4) != 0) {
5873 /* more than 32 bits? */
5874 return NT_STATUS_INVALID_PARAMETER;
5876 #endif /* LARGE_SMB_OFF_T */
5879 ts[0] = interpret_long_date(pdata+24); /* access_time */
5880 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5881 set_owner = (uid_t)IVAL(pdata,40);
5882 set_grp = (gid_t)IVAL(pdata,48);
5883 raw_unixmode = IVAL(pdata,84);
5885 if (VALID_STAT(*psbuf)) {
5886 if (S_ISDIR(psbuf->st_mode)) {
5887 ptype = PERM_EXISTING_DIR;
5889 ptype = PERM_EXISTING_FILE;
5892 ptype = PERM_NEW_FILE;
5895 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5896 if (!NT_STATUS_IS_OK(status)) {
5900 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5901 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5902 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5904 if (!VALID_STAT(*psbuf)) {
5906 * The only valid use of this is to create character and block
5907 * devices, and named pipes. This is deprecated (IMHO) and
5908 * a new info level should be used for mknod. JRA.
5911 status = smb_unix_mknod(conn,
5916 if (!NT_STATUS_IS_OK(status)) {
5920 /* Ensure we don't try and change anything else. */
5921 raw_unixmode = SMB_MODE_NO_CHANGE;
5922 size = get_file_size(*psbuf);
5923 ts[0] = get_atimespec(psbuf);
5924 ts[1] = get_mtimespec(psbuf);
5926 * We continue here as we might want to change the
5929 delete_on_fail = True;
5933 /* Horrible backwards compatibility hack as an old server bug
5934 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5938 size = get_file_size(*psbuf);
5943 * Deal with the UNIX specific mode set.
5946 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5947 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5948 (unsigned int)unixmode, fname ));
5949 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5950 return map_nt_error_from_unix(errno);
5955 * Deal with the UNIX specific uid set.
5958 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5961 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5962 (unsigned int)set_owner, fname ));
5964 if (S_ISLNK(psbuf->st_mode)) {
5965 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5967 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5971 status = map_nt_error_from_unix(errno);
5972 if (delete_on_fail) {
5973 SMB_VFS_UNLINK(conn,fname);
5980 * Deal with the UNIX specific gid set.
5983 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5984 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5985 (unsigned int)set_owner, fname ));
5986 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5987 status = map_nt_error_from_unix(errno);
5988 if (delete_on_fail) {
5989 SMB_VFS_UNLINK(conn,fname);
5995 /* Deal with any size changes. */
5997 status = smb_set_file_size(conn, req,
6002 if (!NT_STATUS_IS_OK(status)) {
6006 /* Deal with any time changes. */
6008 return smb_set_file_time(conn,
6016 /****************************************************************************
6017 Deal with SMB_SET_FILE_UNIX_INFO2.
6018 ****************************************************************************/
6020 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6021 struct smb_request *req,
6026 SMB_STRUCT_STAT *psbuf)
6032 if (total_data < 116) {
6033 return NT_STATUS_INVALID_PARAMETER;
6036 /* Start by setting all the fields that are common between UNIX_BASIC
6039 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6041 if (!NT_STATUS_IS_OK(status)) {
6045 smb_fflags = IVAL(pdata, 108);
6046 smb_fmask = IVAL(pdata, 112);
6048 /* NB: We should only attempt to alter the file flags if the client
6049 * sends a non-zero mask.
6051 if (smb_fmask != 0) {
6052 int stat_fflags = 0;
6054 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6056 /* Client asked to alter a flag we don't understand. */
6057 return NT_STATUS_INVALID_PARAMETER;
6060 if (fsp && fsp->fh->fd != -1) {
6061 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6062 return NT_STATUS_NOT_SUPPORTED;
6064 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6065 return map_nt_error_from_unix(errno);
6070 /* XXX: need to add support for changing the create_time here. You
6071 * can do this for paths on Darwin with setattrlist(2). The right way
6072 * to hook this up is probably by extending the VFS utimes interface.
6075 return NT_STATUS_OK;
6078 /****************************************************************************
6079 Create a directory with POSIX semantics.
6080 ****************************************************************************/
6082 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6083 struct smb_request *req,
6087 SMB_STRUCT_STAT *psbuf,
6088 int *pdata_return_size)
6090 NTSTATUS status = NT_STATUS_OK;
6091 uint32 raw_unixmode = 0;
6092 uint32 mod_unixmode = 0;
6093 mode_t unixmode = (mode_t)0;
6094 files_struct *fsp = NULL;
6095 uint16 info_level_return = 0;
6097 char *pdata = *ppdata;
6099 if (total_data < 18) {
6100 return NT_STATUS_INVALID_PARAMETER;
6103 raw_unixmode = IVAL(pdata,8);
6104 /* Next 4 bytes are not yet defined. */
6106 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6107 if (!NT_STATUS_IS_OK(status)) {
6111 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6113 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6114 fname, (unsigned int)unixmode ));
6116 status = open_directory(conn, req,
6119 FILE_READ_ATTRIBUTES, /* Just a stat open */
6120 FILE_SHARE_NONE, /* Ignored for stat opens */
6127 if (NT_STATUS_IS_OK(status)) {
6128 close_file(fsp, NORMAL_CLOSE);
6131 info_level_return = SVAL(pdata,16);
6133 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6134 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6135 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6136 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6138 *pdata_return_size = 12;
6141 /* Realloc the data size */
6142 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6143 if (*ppdata == NULL) {
6144 *pdata_return_size = 0;
6145 return NT_STATUS_NO_MEMORY;
6149 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6150 SSVAL(pdata,2,0); /* No fnum. */
6151 SIVAL(pdata,4,info); /* Was directory created. */
6153 switch (info_level_return) {
6154 case SMB_QUERY_FILE_UNIX_BASIC:
6155 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6156 SSVAL(pdata,10,0); /* Padding. */
6157 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6159 case SMB_QUERY_FILE_UNIX_INFO2:
6160 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6161 SSVAL(pdata,10,0); /* Padding. */
6162 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6165 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6166 SSVAL(pdata,10,0); /* Padding. */
6173 /****************************************************************************
6174 Open/Create a file with POSIX semantics.
6175 ****************************************************************************/
6177 static NTSTATUS smb_posix_open(connection_struct *conn,
6178 struct smb_request *req,
6182 SMB_STRUCT_STAT *psbuf,
6183 int *pdata_return_size)
6185 bool extended_oplock_granted = False;
6186 char *pdata = *ppdata;
6188 uint32 wire_open_mode = 0;
6189 uint32 raw_unixmode = 0;
6190 uint32 mod_unixmode = 0;
6191 uint32 create_disp = 0;
6192 uint32 access_mask = 0;
6193 uint32 create_options = 0;
6194 NTSTATUS status = NT_STATUS_OK;
6195 mode_t unixmode = (mode_t)0;
6196 files_struct *fsp = NULL;
6197 int oplock_request = 0;
6199 uint16 info_level_return = 0;
6201 if (total_data < 18) {
6202 return NT_STATUS_INVALID_PARAMETER;
6205 flags = IVAL(pdata,0);
6206 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6207 if (oplock_request) {
6208 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6211 wire_open_mode = IVAL(pdata,4);
6213 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6214 return smb_posix_mkdir(conn, req,
6222 switch (wire_open_mode & SMB_ACCMODE) {
6224 access_mask = FILE_READ_DATA;
6227 access_mask = FILE_WRITE_DATA;
6230 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6233 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6234 (unsigned int)wire_open_mode ));
6235 return NT_STATUS_INVALID_PARAMETER;
6238 wire_open_mode &= ~SMB_ACCMODE;
6240 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6241 create_disp = FILE_CREATE;
6242 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6243 create_disp = FILE_OVERWRITE_IF;
6244 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6245 create_disp = FILE_OPEN_IF;
6247 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6248 (unsigned int)wire_open_mode ));
6249 return NT_STATUS_INVALID_PARAMETER;
6252 raw_unixmode = IVAL(pdata,8);
6253 /* Next 4 bytes are not yet defined. */
6255 status = unix_perms_from_wire(conn,
6258 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6261 if (!NT_STATUS_IS_OK(status)) {
6265 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6267 if (wire_open_mode & SMB_O_SYNC) {
6268 create_options |= FILE_WRITE_THROUGH;
6270 if (wire_open_mode & SMB_O_APPEND) {
6271 access_mask |= FILE_APPEND_DATA;
6273 if (wire_open_mode & SMB_O_DIRECT) {
6274 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6277 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6279 (unsigned int)wire_open_mode,
6280 (unsigned int)unixmode ));
6282 status = open_file_ntcreate(conn, req,
6286 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6288 0, /* no create options yet. */
6294 if (!NT_STATUS_IS_OK(status)) {
6298 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6299 extended_oplock_granted = True;
6302 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6303 extended_oplock_granted = True;
6306 info_level_return = SVAL(pdata,16);
6308 /* Allocate the correct return size. */
6310 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6311 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6312 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6313 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6315 *pdata_return_size = 12;
6318 /* Realloc the data size */
6319 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6320 if (*ppdata == NULL) {
6321 close_file(fsp,ERROR_CLOSE);
6322 *pdata_return_size = 0;
6323 return NT_STATUS_NO_MEMORY;
6327 if (extended_oplock_granted) {
6328 if (flags & REQUEST_BATCH_OPLOCK) {
6329 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6331 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6333 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6334 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6336 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6339 SSVAL(pdata,2,fsp->fnum);
6340 SIVAL(pdata,4,info); /* Was file created etc. */
6342 switch (info_level_return) {
6343 case SMB_QUERY_FILE_UNIX_BASIC:
6344 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6345 SSVAL(pdata,10,0); /* padding. */
6346 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6348 case SMB_QUERY_FILE_UNIX_INFO2:
6349 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6350 SSVAL(pdata,10,0); /* padding. */
6351 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6354 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6355 SSVAL(pdata,10,0); /* padding. */
6358 return NT_STATUS_OK;
6361 /****************************************************************************
6362 Delete a file with POSIX semantics.
6363 ****************************************************************************/
6365 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6366 struct smb_request *req,
6370 SMB_STRUCT_STAT *psbuf)
6372 NTSTATUS status = NT_STATUS_OK;
6373 files_struct *fsp = NULL;
6378 struct share_mode_lock *lck = NULL;
6380 if (total_data < 2) {
6381 return NT_STATUS_INVALID_PARAMETER;
6384 flags = SVAL(pdata,0);
6386 if (!VALID_STAT(*psbuf)) {
6387 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6390 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6391 !VALID_STAT_OF_DIR(*psbuf)) {
6392 return NT_STATUS_NOT_A_DIRECTORY;
6395 DEBUG(10,("smb_posix_unlink: %s %s\n",
6396 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6399 if (VALID_STAT_OF_DIR(*psbuf)) {
6400 status = open_directory(conn, req,
6404 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6407 FILE_FLAG_POSIX_SEMANTICS|0777,
6412 status = open_file_ntcreate(conn, req,
6416 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6419 FILE_FLAG_POSIX_SEMANTICS|0777,
6420 0, /* No oplock, but break existing ones. */
6425 if (!NT_STATUS_IS_OK(status)) {
6430 * Don't lie to client. If we can't really delete due to
6431 * non-POSIX opens return SHARING_VIOLATION.
6434 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6437 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6438 "lock for file %s\n", fsp->fsp_name));
6439 close_file(fsp, NORMAL_CLOSE);
6440 return NT_STATUS_INVALID_PARAMETER;
6444 * See if others still have the file open. If this is the case, then
6445 * don't delete. If all opens are POSIX delete we can set the delete
6446 * on close disposition.
6448 for (i=0; i<lck->num_share_modes; i++) {
6449 struct share_mode_entry *e = &lck->share_modes[i];
6450 if (is_valid_share_mode_entry(e)) {
6451 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6454 /* Fail with sharing violation. */
6455 close_file(fsp, NORMAL_CLOSE);
6457 return NT_STATUS_SHARING_VIOLATION;
6462 * Set the delete on close.
6464 status = smb_set_file_disposition_info(conn,
6471 if (!NT_STATUS_IS_OK(status)) {
6472 close_file(fsp, NORMAL_CLOSE);
6477 return close_file(fsp, NORMAL_CLOSE);
6480 /****************************************************************************
6481 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6482 ****************************************************************************/
6484 static void call_trans2setfilepathinfo(connection_struct *conn,
6485 struct smb_request *req,
6486 unsigned int tran_call,
6487 char **pparams, int total_params,
6488 char **ppdata, int total_data,
6489 unsigned int max_data_bytes)
6491 char *params = *pparams;
6492 char *pdata = *ppdata;
6494 SMB_STRUCT_STAT sbuf;
6496 files_struct *fsp = NULL;
6497 NTSTATUS status = NT_STATUS_OK;
6498 int data_return_size = 0;
6499 TALLOC_CTX *ctx = talloc_tos();
6502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6508 if (tran_call == TRANSACT2_SETFILEINFO) {
6509 if (total_params < 4) {
6510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6514 fsp = file_fsp(SVAL(params,0));
6515 /* Basic check for non-null fsp. */
6516 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6519 info_level = SVAL(params,2);
6521 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6523 reply_nterror(req, NT_STATUS_NO_MEMORY);
6527 if(fsp->is_directory || fsp->fh->fd == -1) {
6529 * This is actually a SETFILEINFO on a directory
6530 * handle (returned from an NT SMB). NT5.0 seems
6531 * to do this call. JRA.
6533 if (INFO_LEVEL_IS_UNIX(info_level)) {
6534 /* Always do lstat for UNIX calls. */
6535 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6536 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6537 reply_unixerror(req,ERRDOS,ERRbadpath);
6541 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6542 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6543 reply_unixerror(req,ERRDOS,ERRbadpath);
6547 } else if (fsp->print_file) {
6549 * Doing a DELETE_ON_CLOSE should cancel a print job.
6551 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6552 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6554 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6557 send_trans2_replies(conn, req, params, 2,
6562 reply_unixerror(req, ERRDOS, ERRbadpath);
6567 * Original code - this is an open file.
6569 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6573 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6574 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6575 reply_unixerror(req, ERRDOS, ERRbadfid);
6581 if (total_params < 7) {
6582 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6586 info_level = SVAL(params,0);
6587 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6588 total_params - 6, STR_TERMINATE,
6590 if (!NT_STATUS_IS_OK(status)) {
6591 reply_nterror(req, status);
6595 status = resolve_dfspath(ctx, conn,
6596 req->flags2 & FLAGS2_DFS_PATHNAMES,
6599 if (!NT_STATUS_IS_OK(status)) {
6600 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6601 reply_botherror(req,
6602 NT_STATUS_PATH_NOT_COVERED,
6603 ERRSRV, ERRbadpath);
6606 reply_nterror(req, status);
6610 status = unix_convert(ctx, conn, fname, False,
6611 &fname, NULL, &sbuf);
6612 if (!NT_STATUS_IS_OK(status)) {
6613 reply_nterror(req, status);
6617 status = check_name(conn, fname);
6618 if (!NT_STATUS_IS_OK(status)) {
6619 reply_nterror(req, status);
6623 if (INFO_LEVEL_IS_UNIX(info_level)) {
6625 * For CIFS UNIX extensions the target name may not exist.
6628 /* Always do lstat for UNIX calls. */
6629 SMB_VFS_LSTAT(conn,fname,&sbuf);
6631 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6632 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6633 reply_unixerror(req, ERRDOS, ERRbadpath);
6638 if (!CAN_WRITE(conn)) {
6639 reply_doserror(req, ERRSRV, ERRaccess);
6643 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6644 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6648 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6649 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6651 /* Realloc the parameter size */
6652 *pparams = (char *)SMB_REALLOC(*pparams,2);
6653 if (*pparams == NULL) {
6654 reply_nterror(req, NT_STATUS_NO_MEMORY);
6661 if (fsp && !null_timespec(fsp->pending_modtime)) {
6662 /* the pending modtime overrides the current modtime */
6663 set_mtimespec(&sbuf, fsp->pending_modtime);
6666 switch (info_level) {
6668 case SMB_INFO_STANDARD:
6670 status = smb_set_info_standard(conn,
6679 case SMB_INFO_SET_EA:
6681 status = smb_info_set_ea(conn,
6689 case SMB_SET_FILE_BASIC_INFO:
6690 case SMB_FILE_BASIC_INFORMATION:
6692 status = smb_set_file_basic_info(conn,
6701 case SMB_FILE_ALLOCATION_INFORMATION:
6702 case SMB_SET_FILE_ALLOCATION_INFO:
6704 status = smb_set_file_allocation_info(conn, req,
6713 case SMB_FILE_END_OF_FILE_INFORMATION:
6714 case SMB_SET_FILE_END_OF_FILE_INFO:
6716 status = smb_set_file_end_of_file_info(conn, req,
6725 case SMB_FILE_DISPOSITION_INFORMATION:
6726 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6729 /* JRA - We used to just ignore this on a path ?
6730 * Shouldn't this be invalid level on a pathname
6733 if (tran_call != TRANSACT2_SETFILEINFO) {
6734 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6737 status = smb_set_file_disposition_info(conn,
6746 case SMB_FILE_POSITION_INFORMATION:
6748 status = smb_file_position_information(conn,
6755 /* From tridge Samba4 :
6756 * MODE_INFORMATION in setfileinfo (I have no
6757 * idea what "mode information" on a file is - it takes a value of 0,
6758 * 2, 4 or 6. What could it be?).
6761 case SMB_FILE_MODE_INFORMATION:
6763 status = smb_file_mode_information(conn,
6770 * CIFS UNIX extensions.
6773 case SMB_SET_FILE_UNIX_BASIC:
6775 status = smb_set_file_unix_basic(conn, req,
6784 case SMB_SET_FILE_UNIX_INFO2:
6786 status = smb_set_file_unix_info2(conn, req,
6795 case SMB_SET_FILE_UNIX_LINK:
6797 if (tran_call != TRANSACT2_SETPATHINFO) {
6798 /* We must have a pathname for this. */
6799 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6802 status = smb_set_file_unix_link(conn, req, pdata,
6807 case SMB_SET_FILE_UNIX_HLINK:
6809 if (tran_call != TRANSACT2_SETPATHINFO) {
6810 /* We must have a pathname for this. */
6811 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6814 status = smb_set_file_unix_hlink(conn, req,
6820 case SMB_FILE_RENAME_INFORMATION:
6822 status = smb_file_rename_information(conn, req,
6828 #if defined(HAVE_POSIX_ACLS)
6829 case SMB_SET_POSIX_ACL:
6831 status = smb_set_posix_acl(conn,
6841 case SMB_SET_POSIX_LOCK:
6843 if (tran_call != TRANSACT2_SETFILEINFO) {
6844 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6847 status = smb_set_posix_lock(conn, req,
6848 pdata, total_data, fsp);
6852 case SMB_POSIX_PATH_OPEN:
6854 if (tran_call != TRANSACT2_SETPATHINFO) {
6855 /* We must have a pathname for this. */
6856 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6860 status = smb_posix_open(conn, req,
6869 case SMB_POSIX_PATH_UNLINK:
6871 if (tran_call != TRANSACT2_SETPATHINFO) {
6872 /* We must have a pathname for this. */
6873 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6877 status = smb_posix_unlink(conn, req,
6886 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6891 if (!NT_STATUS_IS_OK(status)) {
6892 if (open_was_deferred(req->mid)) {
6893 /* We have re-scheduled this call. */
6896 if (blocking_lock_was_deferred(req->mid)) {
6897 /* We have re-scheduled this call. */
6900 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6901 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6902 ERRSRV, ERRbadpath);
6905 if (info_level == SMB_POSIX_PATH_OPEN) {
6906 reply_openerror(req, status);
6910 reply_nterror(req, status);
6915 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6921 /****************************************************************************
6922 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6923 ****************************************************************************/
6925 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6926 char **pparams, int total_params,
6927 char **ppdata, int total_data,
6928 unsigned int max_data_bytes)
6930 char *params = *pparams;
6931 char *pdata = *ppdata;
6932 char *directory = NULL;
6933 SMB_STRUCT_STAT sbuf;
6934 NTSTATUS status = NT_STATUS_OK;
6935 struct ea_list *ea_list = NULL;
6936 TALLOC_CTX *ctx = talloc_tos();
6938 if (!CAN_WRITE(conn)) {
6939 reply_doserror(req, ERRSRV, ERRaccess);
6943 if (total_params < 5) {
6944 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6948 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6949 total_params - 4, STR_TERMINATE,
6951 if (!NT_STATUS_IS_OK(status)) {
6952 reply_nterror(req, status);
6956 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6958 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6959 if (!NT_STATUS_IS_OK(status)) {
6960 reply_nterror(req, status);
6964 status = check_name(conn, directory);
6965 if (!NT_STATUS_IS_OK(status)) {
6966 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6967 reply_nterror(req, status);
6971 /* Any data in this call is an EA list. */
6972 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6973 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6978 * OS/2 workplace shell seems to send SET_EA requests of "null"
6979 * length (4 bytes containing IVAL 4).
6980 * They seem to have no effect. Bug #3212. JRA.
6983 if (total_data != 4) {
6984 if (total_data < 10) {
6985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6989 if (IVAL(pdata,0) > total_data) {
6990 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6991 IVAL(pdata,0), (unsigned int)total_data));
6992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6996 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7002 } else if (IVAL(pdata,0) != 4) {
7003 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7007 status = create_directory(conn, req, directory);
7009 if (!NT_STATUS_IS_OK(status)) {
7010 reply_nterror(req, status);
7014 /* Try and set any given EA. */
7016 status = set_ea(conn, NULL, directory, ea_list);
7017 if (!NT_STATUS_IS_OK(status)) {
7018 reply_nterror(req, status);
7023 /* Realloc the parameter and data sizes */
7024 *pparams = (char *)SMB_REALLOC(*pparams,2);
7025 if(*pparams == NULL) {
7026 reply_nterror(req, NT_STATUS_NO_MEMORY);
7033 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7038 /****************************************************************************
7039 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7040 We don't actually do this - we just send a null response.
7041 ****************************************************************************/
7043 static void call_trans2findnotifyfirst(connection_struct *conn,
7044 struct smb_request *req,
7045 char **pparams, int total_params,
7046 char **ppdata, int total_data,
7047 unsigned int max_data_bytes)
7049 static uint16 fnf_handle = 257;
7050 char *params = *pparams;
7053 if (total_params < 6) {
7054 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7058 info_level = SVAL(params,4);
7059 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7061 switch (info_level) {
7066 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7070 /* Realloc the parameter and data sizes */
7071 *pparams = (char *)SMB_REALLOC(*pparams,6);
7072 if (*pparams == NULL) {
7073 reply_nterror(req, NT_STATUS_NO_MEMORY);
7078 SSVAL(params,0,fnf_handle);
7079 SSVAL(params,2,0); /* No changes */
7080 SSVAL(params,4,0); /* No EA errors */
7087 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7092 /****************************************************************************
7093 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7094 changes). Currently this does nothing.
7095 ****************************************************************************/
7097 static void call_trans2findnotifynext(connection_struct *conn,
7098 struct smb_request *req,
7099 char **pparams, int total_params,
7100 char **ppdata, int total_data,
7101 unsigned int max_data_bytes)
7103 char *params = *pparams;
7105 DEBUG(3,("call_trans2findnotifynext\n"));
7107 /* Realloc the parameter and data sizes */
7108 *pparams = (char *)SMB_REALLOC(*pparams,4);
7109 if (*pparams == NULL) {
7110 reply_nterror(req, NT_STATUS_NO_MEMORY);
7115 SSVAL(params,0,0); /* No changes */
7116 SSVAL(params,2,0); /* No EA errors */
7118 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7123 /****************************************************************************
7124 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7125 ****************************************************************************/
7127 static void call_trans2getdfsreferral(connection_struct *conn,
7128 struct smb_request *req,
7129 char **pparams, int total_params,
7130 char **ppdata, int total_data,
7131 unsigned int max_data_bytes)
7133 char *params = *pparams;
7134 char *pathname = NULL;
7136 int max_referral_level;
7137 NTSTATUS status = NT_STATUS_OK;
7138 TALLOC_CTX *ctx = talloc_tos();
7140 DEBUG(10,("call_trans2getdfsreferral\n"));
7142 if (total_params < 3) {
7143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7147 max_referral_level = SVAL(params,0);
7149 if(!lp_host_msdfs()) {
7150 reply_doserror(req, ERRDOS, ERRbadfunc);
7154 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7155 total_params - 2, STR_TERMINATE);
7157 reply_nterror(req, NT_STATUS_NOT_FOUND);
7160 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7161 ppdata,&status)) < 0) {
7162 reply_nterror(req, status);
7166 SSVAL(req->inbuf, smb_flg2,
7167 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7168 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7173 #define LMCAT_SPL 0x53
7174 #define LMFUNC_GETJOBID 0x60
7176 /****************************************************************************
7177 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7178 ****************************************************************************/
7180 static void call_trans2ioctl(connection_struct *conn,
7181 struct smb_request *req,
7182 char **pparams, int total_params,
7183 char **ppdata, int total_data,
7184 unsigned int max_data_bytes)
7186 char *pdata = *ppdata;
7187 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7189 /* check for an invalid fid before proceeding */
7192 reply_doserror(req, ERRDOS, ERRbadfid);
7196 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7197 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7198 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7199 if (*ppdata == NULL) {
7200 reply_nterror(req, NT_STATUS_NO_MEMORY);
7205 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7206 CAN ACCEPT THIS IN UNICODE. JRA. */
7208 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7209 srvstr_push(pdata, req->flags2, pdata + 2,
7210 global_myname(), 15,
7211 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7212 srvstr_push(pdata, req->flags2, pdata+18,
7213 lp_servicename(SNUM(conn)), 13,
7214 STR_ASCII|STR_TERMINATE); /* Service name */
7215 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7220 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7221 reply_doserror(req, ERRSRV, ERRerror);
7224 /****************************************************************************
7225 Reply to a SMBfindclose (stop trans2 directory search).
7226 ****************************************************************************/
7228 void reply_findclose(struct smb_request *req)
7232 START_PROFILE(SMBfindclose);
7235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7236 END_PROFILE(SMBfindclose);
7240 dptr_num = SVALS(req->inbuf,smb_vwv0);
7242 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7244 dptr_close(&dptr_num);
7246 reply_outbuf(req, 0, 0);
7248 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7250 END_PROFILE(SMBfindclose);
7254 /****************************************************************************
7255 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7256 ****************************************************************************/
7258 void reply_findnclose(struct smb_request *req)
7262 START_PROFILE(SMBfindnclose);
7265 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7266 END_PROFILE(SMBfindnclose);
7270 dptr_num = SVAL(req->inbuf,smb_vwv0);
7272 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7274 /* We never give out valid handles for a
7275 findnotifyfirst - so any dptr_num is ok here.
7278 reply_outbuf(req, 0, 0);
7280 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7282 END_PROFILE(SMBfindnclose);
7286 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7287 struct trans_state *state)
7289 if (Protocol >= PROTOCOL_NT1) {
7290 req->flags2 |= 0x40; /* IS_LONG_NAME */
7291 SSVAL(req->inbuf,smb_flg2,req->flags2);
7294 if (conn->encrypt_level == Required && !req->encrypted) {
7295 if (state->call != TRANSACT2_QFSINFO &&
7296 state->call != TRANSACT2_SETFSINFO) {
7297 DEBUG(0,("handle_trans2: encryption required "
7299 (unsigned int)state->call));
7300 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7305 /* Now we must call the relevant TRANS2 function */
7306 switch(state->call) {
7307 case TRANSACT2_OPEN:
7309 START_PROFILE(Trans2_open);
7310 call_trans2open(conn, req,
7311 &state->param, state->total_param,
7312 &state->data, state->total_data,
7313 state->max_data_return);
7314 END_PROFILE(Trans2_open);
7318 case TRANSACT2_FINDFIRST:
7320 START_PROFILE(Trans2_findfirst);
7321 call_trans2findfirst(conn, req,
7322 &state->param, state->total_param,
7323 &state->data, state->total_data,
7324 state->max_data_return);
7325 END_PROFILE(Trans2_findfirst);
7329 case TRANSACT2_FINDNEXT:
7331 START_PROFILE(Trans2_findnext);
7332 call_trans2findnext(conn, req,
7333 &state->param, state->total_param,
7334 &state->data, state->total_data,
7335 state->max_data_return);
7336 END_PROFILE(Trans2_findnext);
7340 case TRANSACT2_QFSINFO:
7342 START_PROFILE(Trans2_qfsinfo);
7343 call_trans2qfsinfo(conn, req,
7344 &state->param, state->total_param,
7345 &state->data, state->total_data,
7346 state->max_data_return);
7347 END_PROFILE(Trans2_qfsinfo);
7351 case TRANSACT2_SETFSINFO:
7353 START_PROFILE(Trans2_setfsinfo);
7354 call_trans2setfsinfo(conn, req,
7355 &state->param, state->total_param,
7356 &state->data, state->total_data,
7357 state->max_data_return);
7358 END_PROFILE(Trans2_setfsinfo);
7362 case TRANSACT2_QPATHINFO:
7363 case TRANSACT2_QFILEINFO:
7365 START_PROFILE(Trans2_qpathinfo);
7366 call_trans2qfilepathinfo(conn, req, state->call,
7367 &state->param, state->total_param,
7368 &state->data, state->total_data,
7369 state->max_data_return);
7370 END_PROFILE(Trans2_qpathinfo);
7374 case TRANSACT2_SETPATHINFO:
7375 case TRANSACT2_SETFILEINFO:
7377 START_PROFILE(Trans2_setpathinfo);
7378 call_trans2setfilepathinfo(conn, req, state->call,
7379 &state->param, state->total_param,
7380 &state->data, state->total_data,
7381 state->max_data_return);
7382 END_PROFILE(Trans2_setpathinfo);
7386 case TRANSACT2_FINDNOTIFYFIRST:
7388 START_PROFILE(Trans2_findnotifyfirst);
7389 call_trans2findnotifyfirst(conn, req,
7390 &state->param, state->total_param,
7391 &state->data, state->total_data,
7392 state->max_data_return);
7393 END_PROFILE(Trans2_findnotifyfirst);
7397 case TRANSACT2_FINDNOTIFYNEXT:
7399 START_PROFILE(Trans2_findnotifynext);
7400 call_trans2findnotifynext(conn, req,
7401 &state->param, state->total_param,
7402 &state->data, state->total_data,
7403 state->max_data_return);
7404 END_PROFILE(Trans2_findnotifynext);
7408 case TRANSACT2_MKDIR:
7410 START_PROFILE(Trans2_mkdir);
7411 call_trans2mkdir(conn, req,
7412 &state->param, state->total_param,
7413 &state->data, state->total_data,
7414 state->max_data_return);
7415 END_PROFILE(Trans2_mkdir);
7419 case TRANSACT2_GET_DFS_REFERRAL:
7421 START_PROFILE(Trans2_get_dfs_referral);
7422 call_trans2getdfsreferral(conn, req,
7423 &state->param, state->total_param,
7424 &state->data, state->total_data,
7425 state->max_data_return);
7426 END_PROFILE(Trans2_get_dfs_referral);
7430 case TRANSACT2_IOCTL:
7432 START_PROFILE(Trans2_ioctl);
7433 call_trans2ioctl(conn, req,
7434 &state->param, state->total_param,
7435 &state->data, state->total_data,
7436 state->max_data_return);
7437 END_PROFILE(Trans2_ioctl);
7442 /* Error in request */
7443 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7444 reply_doserror(req, ERRSRV,ERRerror);
7448 /****************************************************************************
7449 Reply to a SMBtrans2.
7450 ****************************************************************************/
7452 void reply_trans2(struct smb_request *req)
7454 connection_struct *conn = req->conn;
7459 unsigned int tran_call;
7461 struct trans_state *state;
7464 START_PROFILE(SMBtrans2);
7466 if (req->wct < 14) {
7467 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7468 END_PROFILE(SMBtrans2);
7472 dsoff = SVAL(req->inbuf, smb_dsoff);
7473 dscnt = SVAL(req->inbuf, smb_dscnt);
7474 psoff = SVAL(req->inbuf, smb_psoff);
7475 pscnt = SVAL(req->inbuf, smb_pscnt);
7476 tran_call = SVAL(req->inbuf, smb_setup0);
7477 size = smb_len(req->inbuf) + 4;
7479 result = allow_new_trans(conn->pending_trans, req->mid);
7480 if (!NT_STATUS_IS_OK(result)) {
7481 DEBUG(2, ("Got invalid trans2 request: %s\n",
7482 nt_errstr(result)));
7483 reply_nterror(req, result);
7484 END_PROFILE(SMBtrans2);
7489 switch (tran_call) {
7490 /* List the allowed trans2 calls on IPC$ */
7491 case TRANSACT2_OPEN:
7492 case TRANSACT2_GET_DFS_REFERRAL:
7493 case TRANSACT2_QFILEINFO:
7494 case TRANSACT2_QFSINFO:
7495 case TRANSACT2_SETFSINFO:
7498 reply_doserror(req, ERRSRV, ERRaccess);
7499 END_PROFILE(SMBtrans2);
7504 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7505 DEBUG(0, ("talloc failed\n"));
7506 reply_nterror(req, NT_STATUS_NO_MEMORY);
7507 END_PROFILE(SMBtrans2);
7511 state->cmd = SMBtrans2;
7513 state->mid = req->mid;
7514 state->vuid = req->vuid;
7515 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7516 state->setup = NULL;
7517 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7518 state->param = NULL;
7519 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7521 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7522 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7523 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7524 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7525 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7527 state->call = tran_call;
7529 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7530 is so as a sanity check */
7531 if (state->setup_count != 1) {
7533 * Need to have rc=0 for ioctl to get job id for OS/2.
7534 * Network printing will fail if function is not successful.
7535 * Similar function in reply.c will be used if protocol
7536 * is LANMAN1.0 instead of LM1.2X002.
7537 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7538 * outbuf doesn't have to be set(only job id is used).
7540 if ( (state->setup_count == 4)
7541 && (tran_call == TRANSACT2_IOCTL)
7542 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7543 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7544 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7546 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7547 DEBUG(2,("Transaction is %d\n",tran_call));
7549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7550 END_PROFILE(SMBtrans2);
7555 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7558 if (state->total_data) {
7559 /* Can't use talloc here, the core routines do realloc on the
7560 * params and data. */
7561 state->data = (char *)SMB_MALLOC(state->total_data);
7562 if (state->data == NULL) {
7563 DEBUG(0,("reply_trans2: data malloc fail for %u "
7564 "bytes !\n", (unsigned int)state->total_data));
7566 reply_nterror(req, NT_STATUS_NO_MEMORY);
7567 END_PROFILE(SMBtrans2);
7570 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7572 if ((smb_base(req->inbuf)+dsoff+dscnt
7573 > (char *)req->inbuf + size) ||
7574 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7577 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7580 if (state->total_param) {
7581 /* Can't use talloc here, the core routines do realloc on the
7582 * params and data. */
7583 state->param = (char *)SMB_MALLOC(state->total_param);
7584 if (state->param == NULL) {
7585 DEBUG(0,("reply_trans: param malloc fail for %u "
7586 "bytes !\n", (unsigned int)state->total_param));
7587 SAFE_FREE(state->data);
7589 reply_nterror(req, NT_STATUS_NO_MEMORY);
7590 END_PROFILE(SMBtrans2);
7593 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7595 if ((smb_base(req->inbuf)+psoff+pscnt
7596 > (char *)req->inbuf + size) ||
7597 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7600 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7603 state->received_data = dscnt;
7604 state->received_param = pscnt;
7606 if ((state->received_param == state->total_param) &&
7607 (state->received_data == state->total_data)) {
7609 handle_trans2(conn, req, state);
7611 SAFE_FREE(state->data);
7612 SAFE_FREE(state->param);
7614 END_PROFILE(SMBtrans2);
7618 DLIST_ADD(conn->pending_trans, state);
7620 /* We need to send an interim response then receive the rest
7621 of the parameter/data bytes */
7622 reply_outbuf(req, 0, 0);
7623 show_msg((char *)req->outbuf);
7624 END_PROFILE(SMBtrans2);
7629 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7630 SAFE_FREE(state->data);
7631 SAFE_FREE(state->param);
7633 END_PROFILE(SMBtrans2);
7634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7638 /****************************************************************************
7639 Reply to a SMBtranss2
7640 ****************************************************************************/
7642 void reply_transs2(struct smb_request *req)
7644 connection_struct *conn = req->conn;
7645 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7646 struct trans_state *state;
7649 START_PROFILE(SMBtranss2);
7651 show_msg((char *)req->inbuf);
7654 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7655 END_PROFILE(SMBtranss2);
7659 size = smb_len(req->inbuf)+4;
7661 for (state = conn->pending_trans; state != NULL;
7662 state = state->next) {
7663 if (state->mid == req->mid) {
7668 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7669 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7670 END_PROFILE(SMBtranss2);
7674 /* Revise state->total_param and state->total_data in case they have
7675 changed downwards */
7677 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7678 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7679 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7680 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7682 pcnt = SVAL(req->inbuf, smb_spscnt);
7683 poff = SVAL(req->inbuf, smb_spsoff);
7684 pdisp = SVAL(req->inbuf, smb_spsdisp);
7686 dcnt = SVAL(req->inbuf, smb_sdscnt);
7687 doff = SVAL(req->inbuf, smb_sdsoff);
7688 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7690 state->received_param += pcnt;
7691 state->received_data += dcnt;
7693 if ((state->received_data > state->total_data) ||
7694 (state->received_param > state->total_param))
7698 if (pdisp+pcnt > state->total_param)
7700 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7702 if (pdisp > state->total_param)
7704 if ((smb_base(req->inbuf) + poff + pcnt
7705 > (char *)req->inbuf + size) ||
7706 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7708 if (state->param + pdisp < state->param)
7711 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7716 if (ddisp+dcnt > state->total_data)
7718 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7720 if (ddisp > state->total_data)
7722 if ((smb_base(req->inbuf) + doff + dcnt
7723 > (char *)req->inbuf + size) ||
7724 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7726 if (state->data + ddisp < state->data)
7729 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7733 if ((state->received_param < state->total_param) ||
7734 (state->received_data < state->total_data)) {
7735 END_PROFILE(SMBtranss2);
7740 * construct_reply_common will copy smb_com from inbuf to
7741 * outbuf. SMBtranss2 is wrong here.
7743 SCVAL(req->inbuf,smb_com,SMBtrans2);
7745 handle_trans2(conn, req, state);
7747 DLIST_REMOVE(conn->pending_trans, state);
7748 SAFE_FREE(state->data);
7749 SAFE_FREE(state->param);
7752 END_PROFILE(SMBtranss2);
7757 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7758 DLIST_REMOVE(conn->pending_trans, state);
7759 SAFE_FREE(state->data);
7760 SAFE_FREE(state->param);
7762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7763 END_PROFILE(SMBtranss2);