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 Needed to show the msdfs symlinks as directories. Modifies psbuf
1200 to be a directory if it's a msdfs link.
1201 ****************************************************************************/
1203 static bool check_msdfs_link(connection_struct *conn,
1204 const char *pathname,
1205 SMB_STRUCT_STAT *psbuf)
1207 int saved_errno = errno;
1208 if(lp_host_msdfs() &&
1209 lp_msdfs_root(SNUM(conn)) &&
1210 is_msdfs_link(conn, pathname, psbuf)) {
1212 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1215 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1216 errno = saved_errno;
1219 errno = saved_errno;
1224 /****************************************************************************
1225 Get a level dependent lanman2 dir entry.
1226 ****************************************************************************/
1228 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1229 connection_struct *conn,
1231 const char *path_mask,
1234 int requires_resume_key,
1240 int space_remaining,
1242 bool *got_exact_match,
1243 int *last_entry_off,
1244 struct ea_list *name_list)
1248 SMB_STRUCT_STAT sbuf;
1249 const char *mask = NULL;
1250 char *pathreal = NULL;
1251 const char *fname = NULL;
1252 char *p, *q, *pdata = *ppdata;
1256 SMB_OFF_T file_size = 0;
1257 SMB_BIG_UINT allocation_size = 0;
1259 struct timespec mdate_ts, adate_ts, create_date_ts;
1260 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1262 char *last_entry_ptr;
1264 uint32 nt_extmode; /* Used for NT connections instead of mode */
1265 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1266 bool check_mangled_names = lp_manglednames(conn->params);
1267 char mangled_name[13]; /* mangled 8.3 name. */
1269 *out_of_space = False;
1270 *got_exact_match = False;
1272 ZERO_STRUCT(mdate_ts);
1273 ZERO_STRUCT(adate_ts);
1274 ZERO_STRUCT(create_date_ts);
1276 if (!conn->dirptr) {
1280 p = strrchr_m(path_mask,'/');
1283 mask = talloc_strdup(ctx,"*.*");
1293 bool ms_dfs_link = False;
1295 /* Needed if we run out of space */
1296 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1297 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1300 * Due to bugs in NT client redirectors we are not using
1301 * resume keys any more - set them to zero.
1302 * Check out the related comments in findfirst/findnext.
1308 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1309 (long)conn->dirptr,curr_dirpos));
1316 * fname may get mangled, dname is never mangled.
1317 * Whenever we're accessing the filesystem we use
1318 * pathreal which is composed from dname.
1324 /* Mangle fname if it's an illegal name. */
1325 if (mangle_must_mangle(dname,conn->params)) {
1326 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1327 continue; /* Error - couldn't mangle. */
1329 fname = mangled_name;
1332 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1333 got_match = mask_match(fname, mask, conn->case_sensitive);
1336 if(!got_match && check_mangled_names &&
1337 !mangle_is_8_3(fname, False, conn->params)) {
1339 * It turns out that NT matches wildcards against
1340 * both long *and* short names. This may explain some
1341 * of the wildcard wierdness from old DOS clients
1342 * that some people have been seeing.... JRA.
1344 /* Force the mangling into 8.3. */
1345 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1346 continue; /* Error - couldn't mangle. */
1349 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1350 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1355 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1357 if (dont_descend && !isdots) {
1363 pathreal = talloc_asprintf(ctx,
1368 pathreal = talloc_asprintf(ctx,
1378 if (INFO_LEVEL_IS_UNIX(info_level)) {
1379 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1380 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1381 pathreal,strerror(errno)));
1382 TALLOC_FREE(pathreal);
1385 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1386 /* Needed to show the msdfs symlinks as
1389 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1391 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1392 pathreal,strerror(errno)));
1393 TALLOC_FREE(pathreal);
1399 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1401 mode = dos_mode(conn,pathreal,&sbuf);
1404 if (!dir_check_ftype(conn,mode,dirtype)) {
1405 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1406 TALLOC_FREE(pathreal);
1410 if (!(mode & aDIR)) {
1411 file_size = get_file_size(sbuf);
1413 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1415 mdate_ts = get_mtimespec(&sbuf);
1416 adate_ts = get_atimespec(&sbuf);
1417 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1419 if (ask_sharemode) {
1420 struct timespec write_time_ts;
1421 struct file_id fileid;
1423 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1424 get_file_infos(fileid, NULL, &write_time_ts);
1425 if (!null_timespec(write_time_ts)) {
1426 mdate_ts = write_time_ts;
1430 if (lp_dos_filetime_resolution(SNUM(conn))) {
1431 dos_filetime_timespec(&create_date_ts);
1432 dos_filetime_timespec(&mdate_ts);
1433 dos_filetime_timespec(&adate_ts);
1436 create_date = convert_timespec_to_time_t(create_date_ts);
1437 mdate = convert_timespec_to_time_t(mdate_ts);
1438 adate = convert_timespec_to_time_t(adate_ts);
1440 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1444 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1451 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1453 switch (info_level) {
1454 case SMB_FIND_INFO_STANDARD:
1455 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1456 if(requires_resume_key) {
1460 srv_put_dos_date2(p,0,create_date);
1461 srv_put_dos_date2(p,4,adate);
1462 srv_put_dos_date2(p,8,mdate);
1463 SIVAL(p,12,(uint32)file_size);
1464 SIVAL(p,16,(uint32)allocation_size);
1468 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1469 p += ucs2_align(base_data, p, 0);
1471 len = srvstr_push(base_data, flags2, p,
1472 fname, PTR_DIFF(end_data, p),
1474 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1476 SCVAL(nameptr, -1, len - 2);
1478 SCVAL(nameptr, -1, 0);
1482 SCVAL(nameptr, -1, len - 1);
1484 SCVAL(nameptr, -1, 0);
1490 case SMB_FIND_EA_SIZE:
1491 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1492 if(requires_resume_key) {
1496 srv_put_dos_date2(p,0,create_date);
1497 srv_put_dos_date2(p,4,adate);
1498 srv_put_dos_date2(p,8,mdate);
1499 SIVAL(p,12,(uint32)file_size);
1500 SIVAL(p,16,(uint32)allocation_size);
1503 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1504 SIVAL(p,22,ea_size); /* Extended attributes */
1508 len = srvstr_push(base_data, flags2,
1509 p, fname, PTR_DIFF(end_data, p),
1510 STR_TERMINATE | STR_NOALIGN);
1511 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1524 SCVAL(nameptr,0,len);
1526 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1529 case SMB_FIND_EA_LIST:
1531 struct ea_list *file_list = NULL;
1534 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1538 if(requires_resume_key) {
1542 srv_put_dos_date2(p,0,create_date);
1543 srv_put_dos_date2(p,4,adate);
1544 srv_put_dos_date2(p,8,mdate);
1545 SIVAL(p,12,(uint32)file_size);
1546 SIVAL(p,16,(uint32)allocation_size);
1548 p += 22; /* p now points to the EA area. */
1550 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1551 name_list = ea_list_union(name_list, file_list, &ea_len);
1553 /* We need to determine if this entry will fit in the space available. */
1554 /* Max string size is 255 bytes. */
1555 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1556 /* Move the dirptr back to prev_dirpos */
1557 dptr_SeekDir(conn->dirptr, prev_dirpos);
1558 *out_of_space = True;
1559 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1560 return False; /* Not finished - just out of space */
1563 /* Push the ea_data followed by the name. */
1564 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1566 len = srvstr_push(base_data, flags2,
1567 p + 1, fname, PTR_DIFF(end_data, p+1),
1568 STR_TERMINATE | STR_NOALIGN);
1569 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1582 SCVAL(nameptr,0,len);
1584 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1588 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1589 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1590 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1592 SIVAL(p,0,reskey); p += 4;
1593 put_long_date_timespec(p,create_date_ts); p += 8;
1594 put_long_date_timespec(p,adate_ts); p += 8;
1595 put_long_date_timespec(p,mdate_ts); p += 8;
1596 put_long_date_timespec(p,mdate_ts); p += 8;
1597 SOFF_T(p,0,file_size); p += 8;
1598 SOFF_T(p,0,allocation_size); p += 8;
1599 SIVAL(p,0,nt_extmode); p += 4;
1600 q = p; p += 4; /* q is placeholder for name length. */
1602 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1603 SIVAL(p,0,ea_size); /* Extended attributes */
1606 /* Clear the short name buffer. This is
1607 * IMPORTANT as not doing so will trigger
1608 * a Win2k client bug. JRA.
1610 if (!was_8_3 && check_mangled_names) {
1611 if (!name_to_8_3(fname,mangled_name,True,
1613 /* Error - mangle failed ! */
1614 memset(mangled_name,'\0',12);
1616 mangled_name[12] = 0;
1617 len = srvstr_push(base_data, flags2,
1618 p+2, mangled_name, 24,
1619 STR_UPPER|STR_UNICODE);
1621 memset(p + 2 + len,'\0',24 - len);
1628 len = srvstr_push(base_data, flags2, p,
1629 fname, PTR_DIFF(end_data, p),
1630 STR_TERMINATE_ASCII);
1633 SIVAL(p,0,0); /* Ensure any padding is null. */
1634 len = PTR_DIFF(p, pdata);
1635 len = (len + 3) & ~3;
1640 case SMB_FIND_FILE_DIRECTORY_INFO:
1641 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1643 SIVAL(p,0,reskey); p += 4;
1644 put_long_date_timespec(p,create_date_ts); p += 8;
1645 put_long_date_timespec(p,adate_ts); p += 8;
1646 put_long_date_timespec(p,mdate_ts); p += 8;
1647 put_long_date_timespec(p,mdate_ts); p += 8;
1648 SOFF_T(p,0,file_size); p += 8;
1649 SOFF_T(p,0,allocation_size); p += 8;
1650 SIVAL(p,0,nt_extmode); p += 4;
1651 len = srvstr_push(base_data, flags2,
1652 p + 4, fname, PTR_DIFF(end_data, p+4),
1653 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_FULL_DIRECTORY_INFO:
1664 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1666 SIVAL(p,0,reskey); p += 4;
1667 put_long_date_timespec(p,create_date_ts); p += 8;
1668 put_long_date_timespec(p,adate_ts); p += 8;
1669 put_long_date_timespec(p,mdate_ts); p += 8;
1670 put_long_date_timespec(p,mdate_ts); p += 8;
1671 SOFF_T(p,0,file_size); p += 8;
1672 SOFF_T(p,0,allocation_size); p += 8;
1673 SIVAL(p,0,nt_extmode); p += 4;
1674 q = p; p += 4; /* q is placeholder for name length. */
1676 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1677 SIVAL(p,0,ea_size); /* Extended attributes */
1680 len = srvstr_push(base_data, flags2, p,
1681 fname, PTR_DIFF(end_data, p),
1682 STR_TERMINATE_ASCII);
1686 SIVAL(p,0,0); /* Ensure any padding is null. */
1687 len = PTR_DIFF(p, pdata);
1688 len = (len + 3) & ~3;
1693 case SMB_FIND_FILE_NAMES_INFO:
1694 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1696 SIVAL(p,0,reskey); p += 4;
1698 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1699 acl on a dir (tridge) */
1700 len = srvstr_push(base_data, flags2, p,
1701 fname, PTR_DIFF(end_data, p),
1702 STR_TERMINATE_ASCII);
1705 SIVAL(p,0,0); /* Ensure any padding is null. */
1706 len = PTR_DIFF(p, pdata);
1707 len = (len + 3) & ~3;
1712 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1713 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1715 SIVAL(p,0,reskey); p += 4;
1716 put_long_date_timespec(p,create_date_ts); p += 8;
1717 put_long_date_timespec(p,adate_ts); p += 8;
1718 put_long_date_timespec(p,mdate_ts); p += 8;
1719 put_long_date_timespec(p,mdate_ts); p += 8;
1720 SOFF_T(p,0,file_size); p += 8;
1721 SOFF_T(p,0,allocation_size); p += 8;
1722 SIVAL(p,0,nt_extmode); p += 4;
1723 q = p; p += 4; /* q is placeholder for name length. */
1725 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1726 SIVAL(p,0,ea_size); /* Extended attributes */
1729 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1730 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1731 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1732 len = srvstr_push(base_data, flags2, p,
1733 fname, PTR_DIFF(end_data, p),
1734 STR_TERMINATE_ASCII);
1737 SIVAL(p,0,0); /* Ensure any padding is null. */
1738 len = PTR_DIFF(p, pdata);
1739 len = (len + 3) & ~3;
1744 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1745 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1746 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1748 SIVAL(p,0,reskey); p += 4;
1749 put_long_date_timespec(p,create_date_ts); p += 8;
1750 put_long_date_timespec(p,adate_ts); p += 8;
1751 put_long_date_timespec(p,mdate_ts); p += 8;
1752 put_long_date_timespec(p,mdate_ts); p += 8;
1753 SOFF_T(p,0,file_size); p += 8;
1754 SOFF_T(p,0,allocation_size); p += 8;
1755 SIVAL(p,0,nt_extmode); p += 4;
1756 q = p; p += 4; /* q is placeholder for name length */
1758 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1759 SIVAL(p,0,ea_size); /* Extended attributes */
1762 /* Clear the short name buffer. This is
1763 * IMPORTANT as not doing so will trigger
1764 * a Win2k client bug. JRA.
1766 if (!was_8_3 && check_mangled_names) {
1767 if (!name_to_8_3(fname,mangled_name,True,
1769 /* Error - mangle failed ! */
1770 memset(mangled_name,'\0',12);
1772 mangled_name[12] = 0;
1773 len = srvstr_push(base_data, flags2,
1774 p+2, mangled_name, 24,
1775 STR_UPPER|STR_UNICODE);
1778 memset(p + 2 + len,'\0',24 - len);
1785 SSVAL(p,0,0); p += 2; /* Reserved ? */
1786 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1787 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1788 len = srvstr_push(base_data, flags2, p,
1789 fname, PTR_DIFF(end_data, p),
1790 STR_TERMINATE_ASCII);
1793 SIVAL(p,0,0); /* Ensure any padding is null. */
1794 len = PTR_DIFF(p, pdata);
1795 len = (len + 3) & ~3;
1800 /* CIFS UNIX Extension. */
1802 case SMB_FIND_FILE_UNIX:
1803 case SMB_FIND_FILE_UNIX_INFO2:
1805 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1807 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1809 if (info_level == SMB_FIND_FILE_UNIX) {
1810 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1811 p = store_file_unix_basic(conn, p,
1813 len = srvstr_push(base_data, flags2, p,
1814 fname, PTR_DIFF(end_data, p),
1817 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1818 p = store_file_unix_basic_info2(conn, p,
1822 len = srvstr_push(base_data, flags2, p, fname,
1823 PTR_DIFF(end_data, p), 0);
1824 SIVAL(nameptr, 0, len);
1828 SIVAL(p,0,0); /* Ensure any padding is null. */
1830 len = PTR_DIFF(p, pdata);
1831 len = (len + 3) & ~3;
1832 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1834 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1843 if (PTR_DIFF(p,pdata) > space_remaining) {
1844 /* Move the dirptr back to prev_dirpos */
1845 dptr_SeekDir(conn->dirptr, prev_dirpos);
1846 *out_of_space = True;
1847 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1848 return False; /* Not finished - just out of space */
1851 /* Setup the last entry pointer, as an offset from base_data */
1852 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1853 /* Advance the data pointer to the next slot */
1859 /****************************************************************************
1860 Reply to a TRANS2_FINDFIRST.
1861 ****************************************************************************/
1863 static void call_trans2findfirst(connection_struct *conn,
1864 struct smb_request *req,
1865 char **pparams, int total_params,
1866 char **ppdata, int total_data,
1867 unsigned int max_data_bytes)
1869 /* We must be careful here that we don't return more than the
1870 allowed number of data bytes. If this means returning fewer than
1871 maxentries then so be it. We assume that the redirector has
1872 enough room for the fixed number of parameter bytes it has
1874 char *params = *pparams;
1875 char *pdata = *ppdata;
1879 uint16 findfirst_flags;
1880 bool close_after_first;
1882 bool requires_resume_key;
1884 char *directory = NULL;
1885 const char *mask = NULL;
1887 int last_entry_off=0;
1891 bool finished = False;
1892 bool dont_descend = False;
1893 bool out_of_space = False;
1894 int space_remaining;
1895 bool mask_contains_wcard = False;
1896 SMB_STRUCT_STAT sbuf;
1897 struct ea_list *ea_list = NULL;
1898 NTSTATUS ntstatus = NT_STATUS_OK;
1899 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1900 TALLOC_CTX *ctx = talloc_tos();
1902 if (total_params < 13) {
1903 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1907 dirtype = SVAL(params,0);
1908 maxentries = SVAL(params,2);
1909 findfirst_flags = SVAL(params,4);
1910 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1911 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1912 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1913 info_level = SVAL(params,6);
1915 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1916 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1917 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1918 info_level, max_data_bytes));
1921 /* W2K3 seems to treat zero as 1. */
1925 switch (info_level) {
1926 case SMB_FIND_INFO_STANDARD:
1927 case SMB_FIND_EA_SIZE:
1928 case SMB_FIND_EA_LIST:
1929 case SMB_FIND_FILE_DIRECTORY_INFO:
1930 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1931 case SMB_FIND_FILE_NAMES_INFO:
1932 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1933 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1934 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1936 case SMB_FIND_FILE_UNIX:
1937 case SMB_FIND_FILE_UNIX_INFO2:
1938 if (!lp_unix_extensions()) {
1939 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1944 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1948 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1949 params+12, total_params - 12,
1950 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1951 if (!NT_STATUS_IS_OK(ntstatus)) {
1952 reply_nterror(req, ntstatus);
1956 ntstatus = resolve_dfspath_wcard(ctx, conn,
1957 req->flags2 & FLAGS2_DFS_PATHNAMES,
1960 &mask_contains_wcard);
1961 if (!NT_STATUS_IS_OK(ntstatus)) {
1962 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1963 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1964 ERRSRV, ERRbadpath);
1967 reply_nterror(req, ntstatus);
1971 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1972 if (!NT_STATUS_IS_OK(ntstatus)) {
1973 reply_nterror(req, ntstatus);
1977 ntstatus = check_name(conn, directory);
1978 if (!NT_STATUS_IS_OK(ntstatus)) {
1979 reply_nterror(req, ntstatus);
1983 p = strrchr_m(directory,'/');
1985 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1986 if((directory[0] == '.') && (directory[1] == '\0')) {
1988 mask_contains_wcard = True;
1992 directory = talloc_strdup(talloc_tos(), "./");
1994 reply_nterror(req, NT_STATUS_NO_MEMORY);
2002 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2004 if (info_level == SMB_FIND_EA_LIST) {
2007 if (total_data < 4) {
2008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2012 ea_size = IVAL(pdata,0);
2013 if (ea_size != total_data) {
2014 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2015 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2020 if (!lp_ea_support(SNUM(conn))) {
2021 reply_doserror(req, ERRDOS, ERReasnotsupported);
2025 /* Pull out the list of names. */
2026 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2033 *ppdata = (char *)SMB_REALLOC(
2034 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2035 if(*ppdata == NULL ) {
2036 reply_nterror(req, NT_STATUS_NO_MEMORY);
2040 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2042 /* Realloc the params space */
2043 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2044 if (*pparams == NULL) {
2045 reply_nterror(req, NT_STATUS_NO_MEMORY);
2050 /* Save the wildcard match and attribs we are using on this directory -
2051 needed as lanman2 assumes these are being saved between calls */
2053 ntstatus = dptr_create(conn,
2059 mask_contains_wcard,
2063 if (!NT_STATUS_IS_OK(ntstatus)) {
2064 reply_nterror(req, ntstatus);
2068 dptr_num = dptr_dnum(conn->dirptr);
2069 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2071 /* We don't need to check for VOL here as this is returned by
2072 a different TRANS2 call. */
2074 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2075 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2076 dont_descend = True;
2079 space_remaining = max_data_bytes;
2080 out_of_space = False;
2082 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2083 bool got_exact_match = False;
2085 /* this is a heuristic to avoid seeking the dirptr except when
2086 absolutely necessary. It allows for a filename of about 40 chars */
2087 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2088 out_of_space = True;
2091 finished = !get_lanman2_dir_entry(ctx,
2094 mask,dirtype,info_level,
2095 requires_resume_key,dont_descend,
2098 space_remaining, &out_of_space,
2100 &last_entry_off, ea_list);
2103 if (finished && out_of_space)
2106 if (!finished && !out_of_space)
2110 * As an optimisation if we know we aren't looking
2111 * for a wildcard name (ie. the name matches the wildcard exactly)
2112 * then we can finish on any (first) match.
2113 * This speeds up large directory searches. JRA.
2119 /* Ensure space_remaining never goes -ve. */
2120 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2121 space_remaining = 0;
2122 out_of_space = true;
2124 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2128 /* Check if we can close the dirptr */
2129 if(close_after_first || (finished && close_if_end)) {
2130 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2131 dptr_close(&dptr_num);
2135 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2136 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2137 * the protocol level is less than NT1. Tested with smbclient. JRA.
2138 * This should fix the OS/2 client bug #2335.
2141 if(numentries == 0) {
2142 dptr_close(&dptr_num);
2143 if (Protocol < PROTOCOL_NT1) {
2144 reply_doserror(req, ERRDOS, ERRnofiles);
2147 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2148 ERRDOS, ERRbadfile);
2153 /* At this point pdata points to numentries directory entries. */
2155 /* Set up the return parameter block */
2156 SSVAL(params,0,dptr_num);
2157 SSVAL(params,2,numentries);
2158 SSVAL(params,4,finished);
2159 SSVAL(params,6,0); /* Never an EA error */
2160 SSVAL(params,8,last_entry_off);
2162 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2165 if ((! *directory) && dptr_path(dptr_num)) {
2166 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2168 reply_nterror(req, NT_STATUS_NO_MEMORY);
2172 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2173 smb_fn_name(CVAL(req->inbuf,smb_com)),
2174 mask, directory, dirtype, numentries ) );
2177 * Force a name mangle here to ensure that the
2178 * mask as an 8.3 name is top of the mangled cache.
2179 * The reasons for this are subtle. Don't remove
2180 * this code unless you know what you are doing
2181 * (see PR#13758). JRA.
2184 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2185 char mangled_name[13];
2186 name_to_8_3(mask, mangled_name, True, conn->params);
2192 /****************************************************************************
2193 Reply to a TRANS2_FINDNEXT.
2194 ****************************************************************************/
2196 static void call_trans2findnext(connection_struct *conn,
2197 struct smb_request *req,
2198 char **pparams, int total_params,
2199 char **ppdata, int total_data,
2200 unsigned int max_data_bytes)
2202 /* We must be careful here that we don't return more than the
2203 allowed number of data bytes. If this means returning fewer than
2204 maxentries then so be it. We assume that the redirector has
2205 enough room for the fixed number of parameter bytes it has
2207 char *params = *pparams;
2208 char *pdata = *ppdata;
2214 uint16 findnext_flags;
2215 bool close_after_request;
2217 bool requires_resume_key;
2219 bool mask_contains_wcard = False;
2220 char *resume_name = NULL;
2221 const char *mask = NULL;
2222 const char *directory = NULL;
2226 int i, last_entry_off=0;
2227 bool finished = False;
2228 bool dont_descend = False;
2229 bool out_of_space = False;
2230 int space_remaining;
2231 struct ea_list *ea_list = NULL;
2232 NTSTATUS ntstatus = NT_STATUS_OK;
2233 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2234 TALLOC_CTX *ctx = talloc_tos();
2236 if (total_params < 13) {
2237 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2241 dptr_num = SVAL(params,0);
2242 maxentries = SVAL(params,2);
2243 info_level = SVAL(params,4);
2244 resume_key = IVAL(params,6);
2245 findnext_flags = SVAL(params,10);
2246 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2247 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2248 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2249 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2251 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2253 total_params - 12, STR_TERMINATE, &ntstatus,
2254 &mask_contains_wcard);
2255 if (!NT_STATUS_IS_OK(ntstatus)) {
2256 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2257 complain (it thinks we're asking for the directory above the shared
2258 path or an invalid name). Catch this as the resume name is only compared, never used in
2259 a file access. JRA. */
2260 srvstr_pull_talloc(ctx, params, req->flags2,
2261 &resume_name, params+12,
2265 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2266 reply_nterror(req, ntstatus);
2271 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2272 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2273 resume_key = %d resume name = %s continue=%d level = %d\n",
2274 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2275 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2278 /* W2K3 seems to treat zero as 1. */
2282 switch (info_level) {
2283 case SMB_FIND_INFO_STANDARD:
2284 case SMB_FIND_EA_SIZE:
2285 case SMB_FIND_EA_LIST:
2286 case SMB_FIND_FILE_DIRECTORY_INFO:
2287 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2288 case SMB_FIND_FILE_NAMES_INFO:
2289 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2290 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2291 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2293 case SMB_FIND_FILE_UNIX:
2294 case SMB_FIND_FILE_UNIX_INFO2:
2295 if (!lp_unix_extensions()) {
2296 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2301 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2305 if (info_level == SMB_FIND_EA_LIST) {
2308 if (total_data < 4) {
2309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2313 ea_size = IVAL(pdata,0);
2314 if (ea_size != total_data) {
2315 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2316 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2321 if (!lp_ea_support(SNUM(conn))) {
2322 reply_doserror(req, ERRDOS, ERReasnotsupported);
2326 /* Pull out the list of names. */
2327 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2334 *ppdata = (char *)SMB_REALLOC(
2335 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2336 if(*ppdata == NULL) {
2337 reply_nterror(req, NT_STATUS_NO_MEMORY);
2342 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2344 /* Realloc the params space */
2345 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2346 if(*pparams == NULL ) {
2347 reply_nterror(req, NT_STATUS_NO_MEMORY);
2353 /* Check that the dptr is valid */
2354 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2355 reply_doserror(req, ERRDOS, ERRnofiles);
2359 string_set(&conn->dirpath,dptr_path(dptr_num));
2361 /* Get the wildcard mask from the dptr */
2362 if((p = dptr_wcard(dptr_num))== NULL) {
2363 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2364 reply_doserror(req, ERRDOS, ERRnofiles);
2369 directory = conn->dirpath;
2371 /* Get the attr mask from the dptr */
2372 dirtype = dptr_attr(dptr_num);
2374 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2375 dptr_num, mask, dirtype,
2377 dptr_TellDir(conn->dirptr)));
2379 /* We don't need to check for VOL here as this is returned by
2380 a different TRANS2 call. */
2382 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2383 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2384 dont_descend = True;
2387 space_remaining = max_data_bytes;
2388 out_of_space = False;
2391 * Seek to the correct position. We no longer use the resume key but
2392 * depend on the last file name instead.
2395 if(*resume_name && !continue_bit) {
2398 long current_pos = 0;
2400 * Remember, name_to_8_3 is called by
2401 * get_lanman2_dir_entry(), so the resume name
2402 * could be mangled. Ensure we check the unmangled name.
2405 if (mangle_is_mangled(resume_name, conn->params)) {
2406 char *new_resume_name = NULL;
2407 mangle_lookup_name_from_8_3(ctx,
2411 if (new_resume_name) {
2412 resume_name = new_resume_name;
2417 * Fix for NT redirector problem triggered by resume key indexes
2418 * changing between directory scans. We now return a resume key of 0
2419 * and instead look for the filename to continue from (also given
2420 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2421 * findfirst/findnext (as is usual) then the directory pointer
2422 * should already be at the correct place.
2425 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2426 } /* end if resume_name && !continue_bit */
2428 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2429 bool got_exact_match = False;
2431 /* this is a heuristic to avoid seeking the dirptr except when
2432 absolutely necessary. It allows for a filename of about 40 chars */
2433 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2434 out_of_space = True;
2437 finished = !get_lanman2_dir_entry(ctx,
2440 mask,dirtype,info_level,
2441 requires_resume_key,dont_descend,
2444 space_remaining, &out_of_space,
2446 &last_entry_off, ea_list);
2449 if (finished && out_of_space)
2452 if (!finished && !out_of_space)
2456 * As an optimisation if we know we aren't looking
2457 * for a wildcard name (ie. the name matches the wildcard exactly)
2458 * then we can finish on any (first) match.
2459 * This speeds up large directory searches. JRA.
2465 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2468 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2469 smb_fn_name(CVAL(req->inbuf,smb_com)),
2470 mask, directory, dirtype, numentries ) );
2472 /* Check if we can close the dirptr */
2473 if(close_after_request || (finished && close_if_end)) {
2474 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2475 dptr_close(&dptr_num); /* This frees up the saved mask */
2478 /* Set up the return parameter block */
2479 SSVAL(params,0,numentries);
2480 SSVAL(params,2,finished);
2481 SSVAL(params,4,0); /* Never an EA error */
2482 SSVAL(params,6,last_entry_off);
2484 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2490 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2492 E_md4hash(lp_servicename(SNUM(conn)),objid);
2496 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2498 SMB_ASSERT(extended_info != NULL);
2500 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2501 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2502 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2503 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2504 #ifdef SAMBA_VERSION_REVISION
2505 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2507 extended_info->samba_subversion = 0;
2508 #ifdef SAMBA_VERSION_RC_RELEASE
2509 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2511 #ifdef SAMBA_VERSION_PRE_RELEASE
2512 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2515 #ifdef SAMBA_VERSION_VENDOR_PATCH
2516 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2518 extended_info->samba_gitcommitdate = 0;
2519 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2520 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2523 memset(extended_info->samba_version_string, 0,
2524 sizeof(extended_info->samba_version_string));
2526 snprintf (extended_info->samba_version_string,
2527 sizeof(extended_info->samba_version_string),
2528 "%s", samba_version_string());
2531 /****************************************************************************
2532 Reply to a TRANS2_QFSINFO (query filesystem info).
2533 ****************************************************************************/
2535 static void call_trans2qfsinfo(connection_struct *conn,
2536 struct smb_request *req,
2537 char **pparams, int total_params,
2538 char **ppdata, int total_data,
2539 unsigned int max_data_bytes)
2541 char *pdata, *end_data;
2542 char *params = *pparams;
2546 const char *vname = volume_label(SNUM(conn));
2547 int snum = SNUM(conn);
2548 char *fstype = lp_fstype(SNUM(conn));
2549 uint32 additional_flags = 0;
2551 if (total_params < 2) {
2552 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2556 info_level = SVAL(params,0);
2559 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2560 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2561 "info level (0x%x) on IPC$.\n",
2562 (unsigned int)info_level));
2563 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2568 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2569 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2570 DEBUG(0,("call_trans2qfsinfo: encryption required "
2571 "and info level 0x%x sent.\n",
2572 (unsigned int)info_level));
2573 exit_server_cleanly("encryption required "
2579 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2581 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2582 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2583 reply_doserror(req, ERRSRV, ERRinvdevice);
2587 *ppdata = (char *)SMB_REALLOC(
2588 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2589 if (*ppdata == NULL ) {
2590 reply_nterror(req, NT_STATUS_NO_MEMORY);
2595 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2596 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2598 switch (info_level) {
2599 case SMB_INFO_ALLOCATION:
2601 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2603 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2604 reply_unixerror(req, ERRHRD, ERRgeneral);
2608 block_size = lp_block_size(snum);
2609 if (bsize < block_size) {
2610 SMB_BIG_UINT factor = block_size/bsize;
2615 if (bsize > block_size) {
2616 SMB_BIG_UINT factor = bsize/block_size;
2621 bytes_per_sector = 512;
2622 sectors_per_unit = bsize/bytes_per_sector;
2624 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2625 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2626 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2628 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2629 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2630 SIVAL(pdata,l1_cUnit,dsize);
2631 SIVAL(pdata,l1_cUnitAvail,dfree);
2632 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2636 case SMB_INFO_VOLUME:
2637 /* Return volume name */
2639 * Add volume serial number - hash of a combination of
2640 * the called hostname and the service name.
2642 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2644 * Win2k3 and previous mess this up by sending a name length
2645 * one byte short. I believe only older clients (OS/2 Win9x) use
2646 * this call so try fixing this by adding a terminating null to
2647 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2651 pdata+l2_vol_szVolLabel, vname,
2652 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2653 STR_NOALIGN|STR_TERMINATE);
2654 SCVAL(pdata,l2_vol_cch,len);
2655 data_len = l2_vol_szVolLabel + len;
2656 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2657 (unsigned)st.st_ctime, len, vname));
2660 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2661 case SMB_FS_ATTRIBUTE_INFORMATION:
2663 additional_flags = 0;
2664 #if defined(HAVE_SYS_QUOTAS)
2665 additional_flags |= FILE_VOLUME_QUOTAS;
2668 if(lp_nt_acl_support(SNUM(conn))) {
2669 additional_flags |= FILE_PERSISTENT_ACLS;
2672 /* Capabilities are filled in at connection time through STATVFS call */
2673 additional_flags |= conn->fs_capabilities;
2675 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2676 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2677 additional_flags); /* FS ATTRIBUTES */
2679 SIVAL(pdata,4,255); /* Max filename component length */
2680 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2681 and will think we can't do long filenames */
2682 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2683 PTR_DIFF(end_data, pdata+12),
2686 data_len = 12 + len;
2689 case SMB_QUERY_FS_LABEL_INFO:
2690 case SMB_FS_LABEL_INFORMATION:
2691 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2692 PTR_DIFF(end_data, pdata+4), 0);
2697 case SMB_QUERY_FS_VOLUME_INFO:
2698 case SMB_FS_VOLUME_INFORMATION:
2701 * Add volume serial number - hash of a combination of
2702 * the called hostname and the service name.
2704 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2705 (str_checksum(get_local_machine_name())<<16));
2707 /* Max label len is 32 characters. */
2708 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2709 PTR_DIFF(end_data, pdata+18),
2711 SIVAL(pdata,12,len);
2714 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2715 (int)strlen(vname),vname, lp_servicename(snum)));
2718 case SMB_QUERY_FS_SIZE_INFO:
2719 case SMB_FS_SIZE_INFORMATION:
2721 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2723 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2724 reply_unixerror(req, ERRHRD, ERRgeneral);
2727 block_size = lp_block_size(snum);
2728 if (bsize < block_size) {
2729 SMB_BIG_UINT factor = block_size/bsize;
2734 if (bsize > block_size) {
2735 SMB_BIG_UINT factor = bsize/block_size;
2740 bytes_per_sector = 512;
2741 sectors_per_unit = bsize/bytes_per_sector;
2742 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2743 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2744 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2745 SBIG_UINT(pdata,0,dsize);
2746 SBIG_UINT(pdata,8,dfree);
2747 SIVAL(pdata,16,sectors_per_unit);
2748 SIVAL(pdata,20,bytes_per_sector);
2752 case SMB_FS_FULL_SIZE_INFORMATION:
2754 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2756 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2757 reply_unixerror(req, ERRHRD, ERRgeneral);
2760 block_size = lp_block_size(snum);
2761 if (bsize < block_size) {
2762 SMB_BIG_UINT factor = block_size/bsize;
2767 if (bsize > block_size) {
2768 SMB_BIG_UINT factor = bsize/block_size;
2773 bytes_per_sector = 512;
2774 sectors_per_unit = bsize/bytes_per_sector;
2775 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2776 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2777 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2778 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2779 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2780 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2781 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2782 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2786 case SMB_QUERY_FS_DEVICE_INFO:
2787 case SMB_FS_DEVICE_INFORMATION:
2789 SIVAL(pdata,0,0); /* dev type */
2790 SIVAL(pdata,4,0); /* characteristics */
2793 #ifdef HAVE_SYS_QUOTAS
2794 case SMB_FS_QUOTA_INFORMATION:
2796 * what we have to send --metze:
2798 * Unknown1: 24 NULL bytes
2799 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2800 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2801 * Quota Flags: 2 byte :
2802 * Unknown3: 6 NULL bytes
2806 * details for Quota Flags:
2808 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2809 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2810 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2811 * 0x0001 Enable Quotas: enable quota for this fs
2815 /* we need to fake up a fsp here,
2816 * because its not send in this call
2819 SMB_NTQUOTA_STRUCT quotas;
2822 ZERO_STRUCT(quotas);
2828 if (current_user.ut.uid != 0) {
2829 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2830 lp_servicename(SNUM(conn)),conn->user));
2831 reply_doserror(req, ERRDOS, ERRnoaccess);
2835 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2836 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2837 reply_doserror(req, ERRSRV, ERRerror);
2843 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2845 /* Unknown1 24 NULL bytes*/
2846 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2847 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2848 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2850 /* Default Soft Quota 8 bytes */
2851 SBIG_UINT(pdata,24,quotas.softlim);
2853 /* Default Hard Quota 8 bytes */
2854 SBIG_UINT(pdata,32,quotas.hardlim);
2856 /* Quota flag 2 bytes */
2857 SSVAL(pdata,40,quotas.qflags);
2859 /* Unknown3 6 NULL bytes */
2865 #endif /* HAVE_SYS_QUOTAS */
2866 case SMB_FS_OBJECTID_INFORMATION:
2868 unsigned char objid[16];
2869 struct smb_extended_info extended_info;
2870 memcpy(pdata,create_volume_objectid(conn, objid),16);
2871 samba_extended_info_version (&extended_info);
2872 SIVAL(pdata,16,extended_info.samba_magic);
2873 SIVAL(pdata,20,extended_info.samba_version);
2874 SIVAL(pdata,24,extended_info.samba_subversion);
2875 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2876 memcpy(pdata+36,extended_info.samba_version_string,28);
2882 * Query the version and capabilities of the CIFS UNIX extensions
2886 case SMB_QUERY_CIFS_UNIX_INFO:
2888 bool large_write = lp_min_receive_file_size() &&
2889 !srv_is_signing_active();
2890 bool large_read = !srv_is_signing_active();
2891 int encrypt_caps = 0;
2893 if (!lp_unix_extensions()) {
2894 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2898 switch (conn->encrypt_level) {
2904 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2907 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2908 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2909 large_write = false;
2915 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2916 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2918 /* We have POSIX ACLs, pathname, encryption,
2919 * large read/write, and locking capability. */
2921 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2922 CIFS_UNIX_POSIX_ACLS_CAP|
2923 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2924 CIFS_UNIX_FCNTL_LOCKS_CAP|
2925 CIFS_UNIX_EXTATTR_CAP|
2926 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2928 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2930 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2934 case SMB_QUERY_POSIX_FS_INFO:
2937 vfs_statvfs_struct svfs;
2939 if (!lp_unix_extensions()) {
2940 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2944 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2948 SIVAL(pdata,0,svfs.OptimalTransferSize);
2949 SIVAL(pdata,4,svfs.BlockSize);
2950 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2951 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2952 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2953 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2954 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2955 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2956 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2958 } else if (rc == EOPNOTSUPP) {
2959 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2961 #endif /* EOPNOTSUPP */
2963 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2964 reply_doserror(req, ERRSRV, ERRerror);
2970 case SMB_QUERY_POSIX_WHOAMI:
2976 if (!lp_unix_extensions()) {
2977 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2981 if (max_data_bytes < 40) {
2982 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2986 /* We ARE guest if global_sid_Builtin_Guests is
2987 * in our list of SIDs.
2989 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2990 current_user.nt_user_token)) {
2991 flags |= SMB_WHOAMI_GUEST;
2994 /* We are NOT guest if global_sid_Authenticated_Users
2995 * is in our list of SIDs.
2997 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2998 current_user.nt_user_token)) {
2999 flags &= ~SMB_WHOAMI_GUEST;
3002 /* NOTE: 8 bytes for UID/GID, irrespective of native
3003 * platform size. This matches
3004 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3006 data_len = 4 /* flags */
3013 + 4 /* pad/reserved */
3014 + (current_user.ut.ngroups * 8)
3016 + (current_user.nt_user_token->num_sids *
3020 SIVAL(pdata, 0, flags);
3021 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3022 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
3023 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
3026 if (data_len >= max_data_bytes) {
3027 /* Potential overflow, skip the GIDs and SIDs. */
3029 SIVAL(pdata, 24, 0); /* num_groups */
3030 SIVAL(pdata, 28, 0); /* num_sids */
3031 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3032 SIVAL(pdata, 36, 0); /* reserved */
3038 SIVAL(pdata, 24, current_user.ut.ngroups);
3040 current_user.nt_user_token->num_sids);
3042 /* We walk the SID list twice, but this call is fairly
3043 * infrequent, and I don't expect that it's performance
3044 * sensitive -- jpeach
3046 for (i = 0, sid_bytes = 0;
3047 i < current_user.nt_user_token->num_sids; ++i) {
3048 sid_bytes += ndr_size_dom_sid(
3049 ¤t_user.nt_user_token->user_sids[i], 0);
3052 /* SID list byte count */
3053 SIVAL(pdata, 32, sid_bytes);
3055 /* 4 bytes pad/reserved - must be zero */
3056 SIVAL(pdata, 36, 0);
3060 for (i = 0; i < current_user.ut.ngroups; ++i) {
3061 SBIG_UINT(pdata, data_len,
3062 (SMB_BIG_UINT)current_user.ut.groups[i]);
3068 i < current_user.nt_user_token->num_sids; ++i) {
3069 int sid_len = ndr_size_dom_sid(
3070 ¤t_user.nt_user_token->user_sids[i], 0);
3072 sid_linearize(pdata + data_len, sid_len,
3073 ¤t_user.nt_user_token->user_sids[i]);
3074 data_len += sid_len;
3080 case SMB_MAC_QUERY_FS_INFO:
3082 * Thursby MAC extension... ONLY on NTFS filesystems
3083 * once we do streams then we don't need this
3085 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3087 SIVAL(pdata,84,0x100); /* Don't support mac... */
3092 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3097 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3100 DEBUG( 4, ( "%s info_level = %d\n",
3101 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3106 /****************************************************************************
3107 Reply to a TRANS2_SETFSINFO (set filesystem info).
3108 ****************************************************************************/
3110 static void call_trans2setfsinfo(connection_struct *conn,
3111 struct smb_request *req,
3112 char **pparams, int total_params,
3113 char **ppdata, int total_data,
3114 unsigned int max_data_bytes)
3116 char *pdata = *ppdata;
3117 char *params = *pparams;
3120 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3123 if (total_params < 4) {
3124 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3130 info_level = SVAL(params,2);
3133 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3134 info_level != SMB_SET_CIFS_UNIX_INFO) {
3135 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3136 "info level (0x%x) on IPC$.\n",
3137 (unsigned int)info_level));
3138 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3143 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3144 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3145 DEBUG(0,("call_trans2setfsinfo: encryption required "
3146 "and info level 0x%x sent.\n",
3147 (unsigned int)info_level));
3148 exit_server_cleanly("encryption required "
3154 switch(info_level) {
3155 case SMB_SET_CIFS_UNIX_INFO:
3157 uint16 client_unix_major;
3158 uint16 client_unix_minor;
3159 uint32 client_unix_cap_low;
3160 uint32 client_unix_cap_high;
3162 if (!lp_unix_extensions()) {
3164 NT_STATUS_INVALID_LEVEL);
3168 /* There should be 12 bytes of capabilities set. */
3169 if (total_data < 8) {
3172 NT_STATUS_INVALID_PARAMETER);
3175 client_unix_major = SVAL(pdata,0);
3176 client_unix_minor = SVAL(pdata,2);
3177 client_unix_cap_low = IVAL(pdata,4);
3178 client_unix_cap_high = IVAL(pdata,8);
3179 /* Just print these values for now. */
3180 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3181 cap_low = 0x%x, cap_high = 0x%x\n",
3182 (unsigned int)client_unix_major,
3183 (unsigned int)client_unix_minor,
3184 (unsigned int)client_unix_cap_low,
3185 (unsigned int)client_unix_cap_high ));
3187 /* Here is where we must switch to posix pathname processing... */
3188 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3189 lp_set_posix_pathnames();
3190 mangle_change_to_posix();
3193 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3194 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3195 /* Client that knows how to do posix locks,
3196 * but not posix open/mkdir operations. Set a
3197 * default type for read/write checks. */
3199 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3205 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3208 size_t param_len = 0;
3209 size_t data_len = total_data;
3211 if (!lp_unix_extensions()) {
3214 NT_STATUS_INVALID_LEVEL);
3218 if (lp_smb_encrypt(SNUM(conn)) == false) {
3221 NT_STATUS_NOT_SUPPORTED);
3225 DEBUG( 4,("call_trans2setfsinfo: "
3226 "request transport encryption.\n"));
3228 status = srv_request_encryption_setup(conn,
3229 (unsigned char **)ppdata,
3231 (unsigned char **)pparams,
3234 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3235 !NT_STATUS_IS_OK(status)) {
3236 reply_nterror(req, status);
3240 send_trans2_replies(conn, req,
3247 if (NT_STATUS_IS_OK(status)) {
3248 /* Server-side transport
3249 * encryption is now *on*. */
3250 status = srv_encryption_start(conn);
3251 if (!NT_STATUS_IS_OK(status)) {
3252 exit_server_cleanly(
3253 "Failure in setting "
3254 "up encrypted transport");
3260 case SMB_FS_QUOTA_INFORMATION:
3262 files_struct *fsp = NULL;
3263 SMB_NTQUOTA_STRUCT quotas;
3265 ZERO_STRUCT(quotas);
3268 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3269 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3270 lp_servicename(SNUM(conn)),conn->user));
3271 reply_doserror(req, ERRSRV, ERRaccess);
3275 /* note: normaly there're 48 bytes,
3276 * but we didn't use the last 6 bytes for now
3279 fsp = file_fsp(SVAL(params,0));
3280 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3281 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3283 req, NT_STATUS_INVALID_HANDLE);
3287 if (total_data < 42) {
3288 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3292 NT_STATUS_INVALID_PARAMETER);
3296 /* unknown_1 24 NULL bytes in pdata*/
3298 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3299 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3300 #ifdef LARGE_SMB_OFF_T
3301 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3302 #else /* LARGE_SMB_OFF_T */
3303 if ((IVAL(pdata,28) != 0)&&
3304 ((quotas.softlim != 0xFFFFFFFF)||
3305 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3306 /* more than 32 bits? */
3309 NT_STATUS_INVALID_PARAMETER);
3312 #endif /* LARGE_SMB_OFF_T */
3314 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3315 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3316 #ifdef LARGE_SMB_OFF_T
3317 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3318 #else /* LARGE_SMB_OFF_T */
3319 if ((IVAL(pdata,36) != 0)&&
3320 ((quotas.hardlim != 0xFFFFFFFF)||
3321 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3322 /* more than 32 bits? */
3325 NT_STATUS_INVALID_PARAMETER);
3328 #endif /* LARGE_SMB_OFF_T */
3330 /* quota_flags 2 bytes **/
3331 quotas.qflags = SVAL(pdata,40);
3333 /* unknown_2 6 NULL bytes follow*/
3335 /* now set the quotas */
3336 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3337 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3338 reply_doserror(req, ERRSRV, ERRerror);
3345 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3347 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3353 * sending this reply works fine,
3354 * but I'm not sure it's the same
3355 * like windows do...
3358 reply_outbuf(req, 10, 0);
3361 #if defined(HAVE_POSIX_ACLS)
3362 /****************************************************************************
3363 Utility function to count the number of entries in a POSIX acl.
3364 ****************************************************************************/
3366 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3368 unsigned int ace_count = 0;
3369 int entry_id = SMB_ACL_FIRST_ENTRY;
3370 SMB_ACL_ENTRY_T entry;
3372 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3374 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3375 entry_id = SMB_ACL_NEXT_ENTRY;
3382 /****************************************************************************
3383 Utility function to marshall a POSIX acl into wire format.
3384 ****************************************************************************/
3386 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3388 int entry_id = SMB_ACL_FIRST_ENTRY;
3389 SMB_ACL_ENTRY_T entry;
3391 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3392 SMB_ACL_TAG_T tagtype;
3393 SMB_ACL_PERMSET_T permset;
3394 unsigned char perms = 0;
3395 unsigned int own_grp;
3398 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3399 entry_id = SMB_ACL_NEXT_ENTRY;
3402 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3403 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3407 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3408 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3412 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3413 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3414 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3416 SCVAL(pdata,1,perms);
3419 case SMB_ACL_USER_OBJ:
3420 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3421 own_grp = (unsigned int)pst->st_uid;
3422 SIVAL(pdata,2,own_grp);
3427 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3429 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3432 own_grp = (unsigned int)*puid;
3433 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3434 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3435 SIVAL(pdata,2,own_grp);
3439 case SMB_ACL_GROUP_OBJ:
3440 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3441 own_grp = (unsigned int)pst->st_gid;
3442 SIVAL(pdata,2,own_grp);
3447 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3449 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3452 own_grp = (unsigned int)*pgid;
3453 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3454 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3455 SIVAL(pdata,2,own_grp);
3460 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3461 SIVAL(pdata,2,0xFFFFFFFF);
3462 SIVAL(pdata,6,0xFFFFFFFF);
3465 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3466 SIVAL(pdata,2,0xFFFFFFFF);
3467 SIVAL(pdata,6,0xFFFFFFFF);
3470 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3473 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3480 /****************************************************************************
3481 Store the FILE_UNIX_BASIC info.
3482 ****************************************************************************/
3484 static char *store_file_unix_basic(connection_struct *conn,
3487 const SMB_STRUCT_STAT *psbuf)
3489 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3490 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3492 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3495 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3498 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3499 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3500 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3503 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3507 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3511 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3514 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3518 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3522 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3525 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3529 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3536 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3537 * the chflags(2) (or equivalent) flags.
3539 * XXX: this really should be behind the VFS interface. To do this, we would
3540 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3541 * Each VFS module could then implement its own mapping as appropriate for the
3542 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3544 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3548 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3552 { UF_IMMUTABLE, EXT_IMMUTABLE },
3556 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3560 { UF_HIDDEN, EXT_HIDDEN },
3563 /* Do not remove. We need to guarantee that this array has at least one
3564 * entry to build on HP-UX.
3570 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3571 uint32 *smb_fflags, uint32 *smb_fmask)
3573 #ifdef HAVE_STAT_ST_FLAGS
3576 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3577 *smb_fmask |= info2_flags_map[i].smb_fflag;
3578 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3579 *smb_fflags |= info2_flags_map[i].smb_fflag;
3582 #endif /* HAVE_STAT_ST_FLAGS */
3585 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3586 const uint32 smb_fflags,
3587 const uint32 smb_fmask,
3590 #ifdef HAVE_STAT_ST_FLAGS
3591 uint32 max_fmask = 0;
3594 *stat_fflags = psbuf->st_flags;
3596 /* For each flags requested in smb_fmask, check the state of the
3597 * corresponding flag in smb_fflags and set or clear the matching
3601 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3602 max_fmask |= info2_flags_map[i].smb_fflag;
3603 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3604 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3605 *stat_fflags |= info2_flags_map[i].stat_fflag;
3607 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3612 /* If smb_fmask is asking to set any bits that are not supported by
3613 * our flag mappings, we should fail.
3615 if ((smb_fmask & max_fmask) != smb_fmask) {
3622 #endif /* HAVE_STAT_ST_FLAGS */
3626 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3627 * of file flags and birth (create) time.
3629 static char *store_file_unix_basic_info2(connection_struct *conn,
3632 const SMB_STRUCT_STAT *psbuf)
3634 uint32 file_flags = 0;
3635 uint32 flags_mask = 0;
3637 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3639 /* Create (birth) time 64 bit */
3640 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3643 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3644 SIVAL(pdata, 0, file_flags); /* flags */
3645 SIVAL(pdata, 4, flags_mask); /* mask */
3651 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3652 const struct stream_struct *streams,
3654 unsigned int max_data_bytes,
3655 unsigned int *data_size)
3658 unsigned int ofs = 0;
3660 for (i=0; i<num_streams; i++) {
3661 unsigned int next_offset;
3663 smb_ucs2_t *namebuf;
3665 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3668 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3669 return NT_STATUS_INVALID_PARAMETER;
3673 * name_buf is now null-terminated, we need to marshall as not
3679 if (ofs + 24 + namelen > max_data_bytes) {
3680 TALLOC_FREE(namebuf);
3681 return NT_STATUS_BUFFER_TOO_SMALL;
3684 SIVAL(data, ofs+4, namelen);
3685 SOFF_T(data, ofs+8, streams[i].size);
3686 SOFF_T(data, ofs+16, streams[i].alloc_size);
3687 memcpy(data+ofs+24, namebuf, namelen);
3688 TALLOC_FREE(namebuf);
3690 next_offset = ofs + 24 + namelen;
3692 if (i == num_streams-1) {
3693 SIVAL(data, ofs, 0);
3696 unsigned int align = ndr_align_size(next_offset, 8);
3698 if (next_offset + align > max_data_bytes) {
3699 return NT_STATUS_BUFFER_TOO_SMALL;
3702 memset(data+next_offset, 0, align);
3703 next_offset += align;
3705 SIVAL(data, ofs, next_offset - ofs);
3714 return NT_STATUS_OK;
3717 /****************************************************************************
3718 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3719 ****************************************************************************/
3721 static void call_trans2qpipeinfo(connection_struct *conn,
3722 struct smb_request *req,
3723 unsigned int tran_call,
3724 char **pparams, int total_params,
3725 char **ppdata, int total_data,
3726 unsigned int max_data_bytes)
3728 char *params = *pparams;
3729 char *pdata = *ppdata;
3730 unsigned int data_size = 0;
3731 unsigned int param_size = 2;
3733 smb_np_struct *p_pipe = NULL;
3736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3740 if (total_params < 4) {
3741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3745 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3746 if (p_pipe == NULL) {
3747 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3751 info_level = SVAL(params,2);
3753 *pparams = (char *)SMB_REALLOC(*pparams,2);
3754 if (*pparams == NULL) {
3755 reply_nterror(req, NT_STATUS_NO_MEMORY);
3760 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3761 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3762 if (*ppdata == NULL ) {
3763 reply_nterror(req, NT_STATUS_NO_MEMORY);
3768 switch (info_level) {
3769 case SMB_FILE_STANDARD_INFORMATION:
3771 SOFF_T(pdata,0,4096LL);
3778 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3782 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3788 /****************************************************************************
3789 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3790 file name or file id).
3791 ****************************************************************************/
3793 static void call_trans2qfilepathinfo(connection_struct *conn,
3794 struct smb_request *req,
3795 unsigned int tran_call,
3796 char **pparams, int total_params,
3797 char **ppdata, int total_data,
3798 unsigned int max_data_bytes)
3800 char *params = *pparams;
3801 char *pdata = *ppdata;
3802 char *dstart, *dend;
3806 SMB_OFF_T file_size=0;
3807 SMB_BIG_UINT allocation_size=0;
3808 unsigned int data_size = 0;
3809 unsigned int param_size = 2;
3810 SMB_STRUCT_STAT sbuf;
3811 char *dos_fname = NULL;
3817 bool delete_pending = False;
3819 time_t create_time, mtime, atime;
3820 struct timespec create_time_ts, mtime_ts, atime_ts;
3821 struct timespec write_time_ts;
3822 files_struct *fsp = NULL;
3823 struct file_id fileid;
3824 struct ea_list *ea_list = NULL;
3825 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3826 char *lock_data = NULL;
3827 bool ms_dfs_link = false;
3828 TALLOC_CTX *ctx = talloc_tos();
3831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3836 ZERO_STRUCT(write_time_ts);
3838 if (tran_call == TRANSACT2_QFILEINFO) {
3839 if (total_params < 4) {
3840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3845 call_trans2qpipeinfo(conn, req, tran_call,
3846 pparams, total_params,
3852 fsp = file_fsp(SVAL(params,0));
3853 info_level = SVAL(params,2);
3855 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3857 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3858 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3862 /* Initial check for valid fsp ptr. */
3863 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3867 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3869 reply_nterror(req, NT_STATUS_NO_MEMORY);
3873 if(fsp->fake_file_handle) {
3875 * This is actually for the QUOTA_FAKE_FILE --metze
3878 /* We know this name is ok, it's already passed the checks. */
3880 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3882 * This is actually a QFILEINFO on a directory
3883 * handle (returned from an NT SMB). NT5.0 seems
3884 * to do this call. JRA.
3887 if (INFO_LEVEL_IS_UNIX(info_level)) {
3888 /* Always do lstat for UNIX calls. */
3889 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3890 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3891 reply_unixerror(req,ERRDOS,ERRbadpath);
3894 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3895 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3896 reply_unixerror(req, ERRDOS, ERRbadpath);
3900 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3901 get_file_infos(fileid, &delete_pending, &write_time_ts);
3904 * Original code - this is an open file.
3906 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3910 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3911 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3912 reply_unixerror(req, ERRDOS, ERRbadfid);
3915 pos = fsp->fh->position_information;
3916 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3917 get_file_infos(fileid, &delete_pending, &write_time_ts);
3918 access_mask = fsp->access_mask;
3922 NTSTATUS status = NT_STATUS_OK;
3925 if (total_params < 7) {
3926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3930 info_level = SVAL(params,0);
3932 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3934 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3935 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3939 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3941 STR_TERMINATE, &status);
3942 if (!NT_STATUS_IS_OK(status)) {
3943 reply_nterror(req, status);
3947 status = resolve_dfspath(ctx,
3949 req->flags2 & FLAGS2_DFS_PATHNAMES,
3952 if (!NT_STATUS_IS_OK(status)) {
3953 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3954 reply_botherror(req,
3955 NT_STATUS_PATH_NOT_COVERED,
3956 ERRSRV, ERRbadpath);
3958 reply_nterror(req, status);
3962 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3963 if (!NT_STATUS_IS_OK(status)) {
3964 reply_nterror(req, status);
3967 status = check_name(conn, fname);
3968 if (!NT_STATUS_IS_OK(status)) {
3969 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3970 reply_nterror(req, status);
3974 if (INFO_LEVEL_IS_UNIX(info_level)) {
3975 /* Always do lstat for UNIX calls. */
3976 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3977 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3978 reply_unixerror(req, ERRDOS, ERRbadpath);
3982 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3983 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
3986 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3987 reply_unixerror(req, ERRDOS, ERRbadpath);
3992 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3993 get_file_infos(fileid, &delete_pending, &write_time_ts);
3994 if (delete_pending) {
3995 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4000 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4001 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4005 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4006 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4008 p = strrchr_m(fname,'/');
4015 mode = dos_mode_msdfs(conn,fname,&sbuf);
4017 mode = dos_mode(conn,fname,&sbuf);
4020 mode = FILE_ATTRIBUTE_NORMAL;
4022 nlink = sbuf.st_nlink;
4024 if (nlink && (mode&aDIR)) {
4028 if ((nlink > 0) && delete_pending) {
4032 fullpathname = fname;
4034 file_size = get_file_size(sbuf);
4036 /* Pull out any data sent here before we realloc. */
4037 switch (info_level) {
4038 case SMB_INFO_QUERY_EAS_FROM_LIST:
4040 /* Pull any EA list from the data portion. */
4043 if (total_data < 4) {
4045 req, NT_STATUS_INVALID_PARAMETER);
4048 ea_size = IVAL(pdata,0);
4050 if (total_data > 0 && ea_size != total_data) {
4051 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4052 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4054 req, NT_STATUS_INVALID_PARAMETER);
4058 if (!lp_ea_support(SNUM(conn))) {
4059 reply_doserror(req, ERRDOS,
4060 ERReasnotsupported);
4064 /* Pull out the list of names. */
4065 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4068 req, NT_STATUS_INVALID_PARAMETER);
4074 case SMB_QUERY_POSIX_LOCK:
4076 if (fsp == NULL || fsp->fh->fd == -1) {
4077 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4081 if (total_data != POSIX_LOCK_DATA_SIZE) {
4083 req, NT_STATUS_INVALID_PARAMETER);
4087 /* Copy the lock range data. */
4088 lock_data = (char *)TALLOC_MEMDUP(
4089 ctx, pdata, total_data);
4091 reply_nterror(req, NT_STATUS_NO_MEMORY);
4099 *pparams = (char *)SMB_REALLOC(*pparams,2);
4100 if (*pparams == NULL) {
4101 reply_nterror(req, NT_STATUS_NO_MEMORY);
4106 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4107 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4108 if (*ppdata == NULL ) {
4109 reply_nterror(req, NT_STATUS_NO_MEMORY);
4114 dend = dstart + data_size - 1;
4116 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4117 mtime_ts = get_mtimespec(&sbuf);
4118 atime_ts = get_atimespec(&sbuf);
4120 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4123 /* Do we have this path open ? */
4125 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4126 fsp1 = file_find_di_first(fileid);
4127 if (fsp1 && fsp1->initial_allocation_size) {
4128 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4132 if (!null_timespec(write_time_ts)) {
4133 mtime_ts = write_time_ts;
4136 if (lp_dos_filetime_resolution(SNUM(conn))) {
4137 dos_filetime_timespec(&create_time_ts);
4138 dos_filetime_timespec(&mtime_ts);
4139 dos_filetime_timespec(&atime_ts);
4142 create_time = convert_timespec_to_time_t(create_time_ts);
4143 mtime = convert_timespec_to_time_t(mtime_ts);
4144 atime = convert_timespec_to_time_t(atime_ts);
4146 /* NT expects the name to be in an exact form of the *full*
4147 filename. See the trans2 torture test */
4148 if (ISDOT(base_name)) {
4149 dos_fname = talloc_strdup(ctx, "\\");
4151 reply_nterror(req, NT_STATUS_NO_MEMORY);
4155 dos_fname = talloc_asprintf(ctx,
4159 reply_nterror(req, NT_STATUS_NO_MEMORY);
4162 string_replace(dos_fname, '/', '\\');
4165 switch (info_level) {
4166 case SMB_INFO_STANDARD:
4167 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4169 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4170 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4171 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4172 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4173 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4174 SSVAL(pdata,l1_attrFile,mode);
4177 case SMB_INFO_QUERY_EA_SIZE:
4179 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4180 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4182 srv_put_dos_date2(pdata,0,create_time);
4183 srv_put_dos_date2(pdata,4,atime);
4184 srv_put_dos_date2(pdata,8,mtime); /* write time */
4185 SIVAL(pdata,12,(uint32)file_size);
4186 SIVAL(pdata,16,(uint32)allocation_size);
4187 SSVAL(pdata,20,mode);
4188 SIVAL(pdata,22,ea_size);
4192 case SMB_INFO_IS_NAME_VALID:
4193 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4194 if (tran_call == TRANSACT2_QFILEINFO) {
4195 /* os/2 needs this ? really ?*/
4196 reply_doserror(req, ERRDOS, ERRbadfunc);
4203 case SMB_INFO_QUERY_EAS_FROM_LIST:
4205 size_t total_ea_len = 0;
4206 struct ea_list *ea_file_list = NULL;
4208 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4210 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4211 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4213 if (!ea_list || (total_ea_len > data_size)) {
4215 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4219 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4223 case SMB_INFO_QUERY_ALL_EAS:
4225 /* We have data_size bytes to put EA's into. */
4226 size_t total_ea_len = 0;
4228 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4230 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4231 if (!ea_list || (total_ea_len > data_size)) {
4233 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4237 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4241 case SMB_FILE_BASIC_INFORMATION:
4242 case SMB_QUERY_FILE_BASIC_INFO:
4244 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4245 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4246 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4248 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4252 put_long_date_timespec(pdata,create_time_ts);
4253 put_long_date_timespec(pdata+8,atime_ts);
4254 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4255 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4256 SIVAL(pdata,32,mode);
4258 DEBUG(5,("SMB_QFBI - "));
4259 DEBUG(5,("create: %s ", ctime(&create_time)));
4260 DEBUG(5,("access: %s ", ctime(&atime)));
4261 DEBUG(5,("write: %s ", ctime(&mtime)));
4262 DEBUG(5,("change: %s ", ctime(&mtime)));
4263 DEBUG(5,("mode: %x\n", mode));
4266 case SMB_FILE_STANDARD_INFORMATION:
4267 case SMB_QUERY_FILE_STANDARD_INFO:
4269 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4271 SOFF_T(pdata,0,allocation_size);
4272 SOFF_T(pdata,8,file_size);
4273 SIVAL(pdata,16,nlink);
4274 SCVAL(pdata,20,delete_pending?1:0);
4275 SCVAL(pdata,21,(mode&aDIR)?1:0);
4276 SSVAL(pdata,22,0); /* Padding. */
4279 case SMB_FILE_EA_INFORMATION:
4280 case SMB_QUERY_FILE_EA_INFO:
4282 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4283 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4285 SIVAL(pdata,0,ea_size);
4289 /* Get the 8.3 name - used if NT SMB was negotiated. */
4290 case SMB_QUERY_FILE_ALT_NAME_INFO:
4291 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4293 char mangled_name[13];
4294 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4295 if (!name_to_8_3(base_name,mangled_name,
4296 True,conn->params)) {
4299 NT_STATUS_NO_MEMORY);
4301 len = srvstr_push(dstart, req->flags2,
4302 pdata+4, mangled_name,
4303 PTR_DIFF(dend, pdata+4),
4305 data_size = 4 + len;
4310 case SMB_QUERY_FILE_NAME_INFO:
4312 this must be *exactly* right for ACLs on mapped drives to work
4314 len = srvstr_push(dstart, req->flags2,
4316 PTR_DIFF(dend, pdata+4),
4318 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4319 data_size = 4 + len;
4323 case SMB_FILE_ALLOCATION_INFORMATION:
4324 case SMB_QUERY_FILE_ALLOCATION_INFO:
4325 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4327 SOFF_T(pdata,0,allocation_size);
4330 case SMB_FILE_END_OF_FILE_INFORMATION:
4331 case SMB_QUERY_FILE_END_OF_FILEINFO:
4332 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4334 SOFF_T(pdata,0,file_size);
4337 case SMB_QUERY_FILE_ALL_INFO:
4338 case SMB_FILE_ALL_INFORMATION:
4340 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4341 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4342 put_long_date_timespec(pdata,create_time_ts);
4343 put_long_date_timespec(pdata+8,atime_ts);
4344 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4345 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4346 SIVAL(pdata,32,mode);
4347 SIVAL(pdata,36,0); /* padding. */
4349 SOFF_T(pdata,0,allocation_size);
4350 SOFF_T(pdata,8,file_size);
4351 SIVAL(pdata,16,nlink);
4352 SCVAL(pdata,20,delete_pending);
4353 SCVAL(pdata,21,(mode&aDIR)?1:0);
4356 SIVAL(pdata,0,ea_size);
4357 pdata += 4; /* EA info */
4358 len = srvstr_push(dstart, req->flags2,
4360 PTR_DIFF(dend, pdata+4),
4364 data_size = PTR_DIFF(pdata,(*ppdata));
4367 case SMB_FILE_INTERNAL_INFORMATION:
4368 /* This should be an index number - looks like
4371 I think this causes us to fail the IFSKIT
4372 BasicFileInformationTest. -tpot */
4374 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4375 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4376 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4380 case SMB_FILE_ACCESS_INFORMATION:
4381 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4382 SIVAL(pdata,0,access_mask);
4386 case SMB_FILE_NAME_INFORMATION:
4387 /* Pathname with leading '\'. */
4390 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4391 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4392 SIVAL(pdata,0,byte_len);
4393 data_size = 4 + byte_len;
4397 case SMB_FILE_DISPOSITION_INFORMATION:
4398 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4400 SCVAL(pdata,0,delete_pending);
4403 case SMB_FILE_POSITION_INFORMATION:
4404 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4406 SOFF_T(pdata,0,pos);
4409 case SMB_FILE_MODE_INFORMATION:
4410 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4411 SIVAL(pdata,0,mode);
4415 case SMB_FILE_ALIGNMENT_INFORMATION:
4416 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4417 SIVAL(pdata,0,0); /* No alignment needed. */
4422 * NT4 server just returns "invalid query" to this - if we try
4423 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4426 /* The first statement above is false - verified using Thursby
4427 * client against NT4 -- gcolley.
4429 case SMB_QUERY_FILE_STREAM_INFO:
4430 case SMB_FILE_STREAM_INFORMATION: {
4431 unsigned int num_streams;
4432 struct stream_struct *streams;
4435 DEBUG(10,("call_trans2qfilepathinfo: "
4436 "SMB_FILE_STREAM_INFORMATION\n"));
4438 status = SMB_VFS_STREAMINFO(
4439 conn, fsp, fname, talloc_tos(),
4440 &num_streams, &streams);
4442 if (!NT_STATUS_IS_OK(status)) {
4443 DEBUG(10, ("could not get stream info: %s\n",
4444 nt_errstr(status)));
4445 reply_nterror(req, status);
4449 status = marshall_stream_info(num_streams, streams,
4450 pdata, max_data_bytes,
4453 if (!NT_STATUS_IS_OK(status)) {
4454 DEBUG(10, ("marshall_stream_info failed: %s\n",
4455 nt_errstr(status)));
4456 reply_nterror(req, status);
4460 TALLOC_FREE(streams);
4464 case SMB_QUERY_COMPRESSION_INFO:
4465 case SMB_FILE_COMPRESSION_INFORMATION:
4466 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4467 SOFF_T(pdata,0,file_size);
4468 SIVAL(pdata,8,0); /* ??? */
4469 SIVAL(pdata,12,0); /* ??? */
4473 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4474 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4475 put_long_date_timespec(pdata,create_time_ts);
4476 put_long_date_timespec(pdata+8,atime_ts);
4477 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4478 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4479 SOFF_T(pdata,32,allocation_size);
4480 SOFF_T(pdata,40,file_size);
4481 SIVAL(pdata,48,mode);
4482 SIVAL(pdata,52,0); /* ??? */
4486 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4487 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4488 SIVAL(pdata,0,mode);
4494 * CIFS UNIX Extensions.
4497 case SMB_QUERY_FILE_UNIX_BASIC:
4499 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4500 data_size = PTR_DIFF(pdata,(*ppdata));
4504 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4506 for (i=0; i<100; i++)
4507 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4513 case SMB_QUERY_FILE_UNIX_INFO2:
4515 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4516 data_size = PTR_DIFF(pdata,(*ppdata));
4520 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4522 for (i=0; i<100; i++)
4523 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4529 case SMB_QUERY_FILE_UNIX_LINK:
4531 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4534 reply_nterror(req, NT_STATUS_NO_MEMORY);
4538 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4540 if(!S_ISLNK(sbuf.st_mode)) {
4541 reply_unixerror(req, ERRSRV,
4546 reply_unixerror(req, ERRDOS, ERRbadlink);
4549 len = SMB_VFS_READLINK(conn,fullpathname,
4552 reply_unixerror(req, ERRDOS,
4557 len = srvstr_push(dstart, req->flags2,
4559 PTR_DIFF(dend, pdata),
4562 data_size = PTR_DIFF(pdata,(*ppdata));
4567 #if defined(HAVE_POSIX_ACLS)
4568 case SMB_QUERY_POSIX_ACL:
4570 SMB_ACL_T file_acl = NULL;
4571 SMB_ACL_T def_acl = NULL;
4572 uint16 num_file_acls = 0;
4573 uint16 num_def_acls = 0;
4575 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4576 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4578 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4581 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4582 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4586 NT_STATUS_NOT_IMPLEMENTED);
4590 if (S_ISDIR(sbuf.st_mode)) {
4591 if (fsp && fsp->is_directory) {
4592 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4594 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4596 def_acl = free_empty_sys_acl(conn, def_acl);
4599 num_file_acls = count_acl_entries(conn, file_acl);
4600 num_def_acls = count_acl_entries(conn, def_acl);
4602 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4603 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4605 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4606 SMB_POSIX_ACL_HEADER_SIZE) ));
4608 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4611 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4615 NT_STATUS_BUFFER_TOO_SMALL);
4619 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4620 SSVAL(pdata,2,num_file_acls);
4621 SSVAL(pdata,4,num_def_acls);
4622 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4624 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4627 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4630 req, NT_STATUS_INTERNAL_ERROR);
4633 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4635 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4638 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4642 NT_STATUS_INTERNAL_ERROR);
4647 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4650 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4652 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4658 case SMB_QUERY_POSIX_LOCK:
4660 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4662 SMB_BIG_UINT offset;
4664 enum brl_type lock_type;
4666 if (total_data != POSIX_LOCK_DATA_SIZE) {
4668 req, NT_STATUS_INVALID_PARAMETER);
4672 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4673 case POSIX_LOCK_TYPE_READ:
4674 lock_type = READ_LOCK;
4676 case POSIX_LOCK_TYPE_WRITE:
4677 lock_type = WRITE_LOCK;
4679 case POSIX_LOCK_TYPE_UNLOCK:
4681 /* There's no point in asking for an unlock... */
4684 NT_STATUS_INVALID_PARAMETER);
4688 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4689 #if defined(HAVE_LONGLONG)
4690 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4691 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4692 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4693 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4694 #else /* HAVE_LONGLONG */
4695 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4696 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4697 #endif /* HAVE_LONGLONG */
4699 status = query_lock(fsp,
4706 if (ERROR_WAS_LOCK_DENIED(status)) {
4707 /* Here we need to report who has it locked... */
4708 data_size = POSIX_LOCK_DATA_SIZE;
4710 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4711 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4712 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4713 #if defined(HAVE_LONGLONG)
4714 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4715 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4716 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4717 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4718 #else /* HAVE_LONGLONG */
4719 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4720 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4721 #endif /* HAVE_LONGLONG */
4723 } else if (NT_STATUS_IS_OK(status)) {
4724 /* For success we just return a copy of what we sent
4725 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4726 data_size = POSIX_LOCK_DATA_SIZE;
4727 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4728 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4730 reply_nterror(req, status);
4737 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4741 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4747 /****************************************************************************
4748 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4750 ****************************************************************************/
4752 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4753 connection_struct *conn,
4754 const char *oldname_in,
4755 const char *newname_in)
4757 SMB_STRUCT_STAT sbuf1, sbuf2;
4758 char *last_component_oldname = NULL;
4759 char *last_component_newname = NULL;
4760 char *oldname = NULL;
4761 char *newname = NULL;
4762 NTSTATUS status = NT_STATUS_OK;
4767 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4768 &last_component_oldname, &sbuf1);
4769 if (!NT_STATUS_IS_OK(status)) {
4773 status = check_name(conn, oldname);
4774 if (!NT_STATUS_IS_OK(status)) {
4778 /* source must already exist. */
4779 if (!VALID_STAT(sbuf1)) {
4780 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4783 status = unix_convert(ctx, conn, newname_in, False, &newname,
4784 &last_component_newname, &sbuf2);
4785 if (!NT_STATUS_IS_OK(status)) {
4789 status = check_name(conn, newname);
4790 if (!NT_STATUS_IS_OK(status)) {
4794 /* Disallow if newname already exists. */
4795 if (VALID_STAT(sbuf2)) {
4796 return NT_STATUS_OBJECT_NAME_COLLISION;
4799 /* No links from a directory. */
4800 if (S_ISDIR(sbuf1.st_mode)) {
4801 return NT_STATUS_FILE_IS_A_DIRECTORY;
4804 /* Ensure this is within the share. */
4805 status = check_reduced_name(conn, oldname);
4806 if (!NT_STATUS_IS_OK(status)) {
4810 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4812 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4813 status = map_nt_error_from_unix(errno);
4814 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4815 nt_errstr(status), newname, oldname));
4821 /****************************************************************************
4822 Deal with setting the time from any of the setfilepathinfo functions.
4823 ****************************************************************************/
4825 NTSTATUS smb_set_file_time(connection_struct *conn,
4828 const SMB_STRUCT_STAT *psbuf,
4829 struct timespec ts[2],
4830 bool setting_write_time)
4833 FILE_NOTIFY_CHANGE_LAST_ACCESS
4834 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4836 if (!VALID_STAT(*psbuf)) {
4837 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4840 /* get some defaults (no modifications) if any info is zero or -1. */
4841 if (null_timespec(ts[0])) {
4842 ts[0] = get_atimespec(psbuf);
4843 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4846 if (null_timespec(ts[1])) {
4847 ts[1] = get_mtimespec(psbuf);
4848 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4851 if (!setting_write_time) {
4852 /* ts[1] comes from change time, not write time. */
4853 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4856 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4857 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4860 * Try and set the times of this file if
4861 * they are different from the current values.
4865 struct timespec mts = get_mtimespec(psbuf);
4866 struct timespec ats = get_atimespec(psbuf);
4867 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4868 return NT_STATUS_OK;
4872 if (setting_write_time) {
4874 * This was a setfileinfo on an open file.
4875 * NT does this a lot. We also need to
4876 * set the time here, as it can be read by
4877 * FindFirst/FindNext and with the patch for bug #2045
4878 * in smbd/fileio.c it ensures that this timestamp is
4879 * kept sticky even after a write. We save the request
4880 * away and will set it on file close and after a write. JRA.
4883 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4884 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4887 set_sticky_write_time_fsp(fsp, ts[1]);
4889 set_sticky_write_time_path(conn, fname,
4890 vfs_file_id_from_sbuf(conn, psbuf),
4895 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4897 if(file_ntimes(conn, fname, ts)!=0) {
4898 return map_nt_error_from_unix(errno);
4900 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4902 return NT_STATUS_OK;
4905 /****************************************************************************
4906 Deal with setting the dosmode from any of the setfilepathinfo functions.
4907 ****************************************************************************/
4909 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4911 SMB_STRUCT_STAT *psbuf,
4914 if (!VALID_STAT(*psbuf)) {
4915 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4919 if (S_ISDIR(psbuf->st_mode)) {
4926 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4928 /* check the mode isn't different, before changing it */
4929 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4931 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4932 fname, (unsigned int)dosmode ));
4934 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4935 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4936 fname, strerror(errno)));
4937 return map_nt_error_from_unix(errno);
4940 return NT_STATUS_OK;
4943 /****************************************************************************
4944 Deal with setting the size from any of the setfilepathinfo functions.
4945 ****************************************************************************/
4947 static NTSTATUS smb_set_file_size(connection_struct *conn,
4948 struct smb_request *req,
4951 SMB_STRUCT_STAT *psbuf,
4954 NTSTATUS status = NT_STATUS_OK;
4955 files_struct *new_fsp = NULL;
4957 if (!VALID_STAT(*psbuf)) {
4958 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4961 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4963 if (size == get_file_size(*psbuf)) {
4964 return NT_STATUS_OK;
4967 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4968 fname, (double)size ));
4970 if (fsp && fsp->fh->fd != -1) {
4971 /* Handle based call. */
4972 if (vfs_set_filelen(fsp, size) == -1) {
4973 return map_nt_error_from_unix(errno);
4975 trigger_write_time_update_immediate(fsp);
4976 return NT_STATUS_OK;
4979 status = open_file_ntcreate(conn, req, fname, psbuf,
4980 FILE_WRITE_ATTRIBUTES,
4981 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4984 FILE_ATTRIBUTE_NORMAL,
4985 FORCE_OPLOCK_BREAK_TO_NONE,
4988 if (!NT_STATUS_IS_OK(status)) {
4989 /* NB. We check for open_was_deferred in the caller. */
4993 if (vfs_set_filelen(new_fsp, size) == -1) {
4994 status = map_nt_error_from_unix(errno);
4995 close_file(new_fsp,NORMAL_CLOSE);
4999 trigger_write_time_update_immediate(new_fsp);
5000 close_file(new_fsp,NORMAL_CLOSE);
5001 return NT_STATUS_OK;
5004 /****************************************************************************
5005 Deal with SMB_INFO_SET_EA.
5006 ****************************************************************************/
5008 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5014 struct ea_list *ea_list = NULL;
5015 TALLOC_CTX *ctx = NULL;
5016 NTSTATUS status = NT_STATUS_OK;
5018 if (total_data < 10) {
5020 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5021 length. They seem to have no effect. Bug #3212. JRA */
5023 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5024 /* We're done. We only get EA info in this call. */
5025 return NT_STATUS_OK;
5028 return NT_STATUS_INVALID_PARAMETER;
5031 if (IVAL(pdata,0) > total_data) {
5032 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5033 IVAL(pdata,0), (unsigned int)total_data));
5034 return NT_STATUS_INVALID_PARAMETER;
5038 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5040 return NT_STATUS_INVALID_PARAMETER;
5042 status = set_ea(conn, fsp, fname, ea_list);
5047 /****************************************************************************
5048 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5049 ****************************************************************************/
5051 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5056 SMB_STRUCT_STAT *psbuf)
5058 NTSTATUS status = NT_STATUS_OK;
5059 bool delete_on_close;
5062 if (total_data < 1) {
5063 return NT_STATUS_INVALID_PARAMETER;
5067 return NT_STATUS_INVALID_HANDLE;
5070 delete_on_close = (CVAL(pdata,0) ? True : False);
5071 dosmode = dos_mode(conn, fname, psbuf);
5073 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5074 "delete_on_close = %u\n",
5076 (unsigned int)dosmode,
5077 (unsigned int)delete_on_close ));
5079 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5081 if (!NT_STATUS_IS_OK(status)) {
5085 /* The set is across all open files on this dev/inode pair. */
5086 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
5087 return NT_STATUS_ACCESS_DENIED;
5089 return NT_STATUS_OK;
5092 /****************************************************************************
5093 Deal with SMB_FILE_POSITION_INFORMATION.
5094 ****************************************************************************/
5096 static NTSTATUS smb_file_position_information(connection_struct *conn,
5101 SMB_BIG_UINT position_information;
5103 if (total_data < 8) {
5104 return NT_STATUS_INVALID_PARAMETER;
5108 /* Ignore on pathname based set. */
5109 return NT_STATUS_OK;
5112 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5113 #ifdef LARGE_SMB_OFF_T
5114 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5115 #else /* LARGE_SMB_OFF_T */
5116 if (IVAL(pdata,4) != 0) {
5117 /* more than 32 bits? */
5118 return NT_STATUS_INVALID_PARAMETER;
5120 #endif /* LARGE_SMB_OFF_T */
5122 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5123 fsp->fsp_name, (double)position_information ));
5124 fsp->fh->position_information = position_information;
5125 return NT_STATUS_OK;
5128 /****************************************************************************
5129 Deal with SMB_FILE_MODE_INFORMATION.
5130 ****************************************************************************/
5132 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5138 if (total_data < 4) {
5139 return NT_STATUS_INVALID_PARAMETER;
5141 mode = IVAL(pdata,0);
5142 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5143 return NT_STATUS_INVALID_PARAMETER;
5145 return NT_STATUS_OK;
5148 /****************************************************************************
5149 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5150 ****************************************************************************/
5152 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5153 struct smb_request *req,
5158 char *link_target = NULL;
5159 const char *newname = fname;
5160 NTSTATUS status = NT_STATUS_OK;
5161 TALLOC_CTX *ctx = talloc_tos();
5163 /* Set a symbolic link. */
5164 /* Don't allow this if follow links is false. */
5166 if (total_data == 0) {
5167 return NT_STATUS_INVALID_PARAMETER;
5170 if (!lp_symlinks(SNUM(conn))) {
5171 return NT_STATUS_ACCESS_DENIED;
5174 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5175 total_data, STR_TERMINATE);
5178 return NT_STATUS_INVALID_PARAMETER;
5181 /* !widelinks forces the target path to be within the share. */
5182 /* This means we can interpret the target as a pathname. */
5183 if (!lp_widelinks(SNUM(conn))) {
5184 char *rel_name = NULL;
5185 char *last_dirp = NULL;
5187 if (*link_target == '/') {
5188 /* No absolute paths allowed. */
5189 return NT_STATUS_ACCESS_DENIED;
5191 rel_name = talloc_strdup(ctx,newname);
5193 return NT_STATUS_NO_MEMORY;
5195 last_dirp = strrchr_m(rel_name, '/');
5197 last_dirp[1] = '\0';
5199 rel_name = talloc_strdup(ctx,"./");
5201 return NT_STATUS_NO_MEMORY;
5204 rel_name = talloc_asprintf_append(rel_name,
5208 return NT_STATUS_NO_MEMORY;
5211 status = check_name(conn, rel_name);
5212 if (!NT_STATUS_IS_OK(status)) {
5217 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5218 newname, link_target ));
5220 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5221 return map_nt_error_from_unix(errno);
5224 return NT_STATUS_OK;
5227 /****************************************************************************
5228 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5229 ****************************************************************************/
5231 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5232 struct smb_request *req,
5233 const char *pdata, int total_data,
5236 char *oldname = NULL;
5237 TALLOC_CTX *ctx = talloc_tos();
5238 NTSTATUS status = NT_STATUS_OK;
5240 /* Set a hard link. */
5241 if (total_data == 0) {
5242 return NT_STATUS_INVALID_PARAMETER;
5245 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5246 total_data, STR_TERMINATE, &status);
5247 if (!NT_STATUS_IS_OK(status)) {
5251 status = resolve_dfspath(ctx, conn,
5252 req->flags2 & FLAGS2_DFS_PATHNAMES,
5255 if (!NT_STATUS_IS_OK(status)) {
5259 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5262 return hardlink_internals(ctx, conn, oldname, fname);
5265 /****************************************************************************
5266 Deal with SMB_FILE_RENAME_INFORMATION.
5267 ****************************************************************************/
5269 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5270 struct smb_request *req,
5279 char *newname = NULL;
5280 char *base_name = NULL;
5281 bool dest_has_wcard = False;
5282 NTSTATUS status = NT_STATUS_OK;
5284 TALLOC_CTX *ctx = talloc_tos();
5286 if (total_data < 13) {
5287 return NT_STATUS_INVALID_PARAMETER;
5290 overwrite = (CVAL(pdata,0) ? True : False);
5291 root_fid = IVAL(pdata,4);
5292 len = IVAL(pdata,8);
5294 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5295 return NT_STATUS_INVALID_PARAMETER;
5298 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5301 if (!NT_STATUS_IS_OK(status)) {
5305 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5308 status = resolve_dfspath_wcard(ctx, conn,
5309 req->flags2 & FLAGS2_DFS_PATHNAMES,
5313 if (!NT_STATUS_IS_OK(status)) {
5317 /* Check the new name has no '/' characters. */
5318 if (strchr_m(newname, '/')) {
5319 return NT_STATUS_NOT_SUPPORTED;
5322 /* Create the base directory. */
5323 base_name = talloc_strdup(ctx, fname);
5325 return NT_STATUS_NO_MEMORY;
5327 p = strrchr_m(base_name, '/');
5331 base_name = talloc_strdup(ctx, "./");
5333 return NT_STATUS_NO_MEMORY;
5336 /* Append the new name. */
5337 base_name = talloc_asprintf_append(base_name,
5341 return NT_STATUS_NO_MEMORY;
5345 SMB_STRUCT_STAT sbuf;
5346 char *newname_last_component = NULL;
5350 status = unix_convert(ctx, conn, newname, False,
5352 &newname_last_component,
5355 /* If an error we expect this to be
5356 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5358 if (!NT_STATUS_IS_OK(status)
5359 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5364 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5365 fsp->fnum, fsp->fsp_name, base_name ));
5366 status = rename_internals_fsp(conn, fsp, base_name,
5367 newname_last_component, 0,
5370 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5371 fname, base_name ));
5372 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5373 overwrite, False, dest_has_wcard,
5374 FILE_WRITE_ATTRIBUTES);
5380 /****************************************************************************
5381 Deal with SMB_SET_POSIX_ACL.
5382 ****************************************************************************/
5384 #if defined(HAVE_POSIX_ACLS)
5385 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5390 SMB_STRUCT_STAT *psbuf)
5392 uint16 posix_acl_version;
5393 uint16 num_file_acls;
5394 uint16 num_def_acls;
5395 bool valid_file_acls = True;
5396 bool valid_def_acls = True;
5398 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5399 return NT_STATUS_INVALID_PARAMETER;
5401 posix_acl_version = SVAL(pdata,0);
5402 num_file_acls = SVAL(pdata,2);
5403 num_def_acls = SVAL(pdata,4);
5405 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5406 valid_file_acls = False;
5410 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5411 valid_def_acls = False;
5415 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5416 return NT_STATUS_INVALID_PARAMETER;
5419 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5420 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5421 return NT_STATUS_INVALID_PARAMETER;
5424 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5425 fname ? fname : fsp->fsp_name,
5426 (unsigned int)num_file_acls,
5427 (unsigned int)num_def_acls));
5429 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5430 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5431 return map_nt_error_from_unix(errno);
5434 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5435 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5436 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5437 return map_nt_error_from_unix(errno);
5439 return NT_STATUS_OK;
5443 /****************************************************************************
5444 Deal with SMB_SET_POSIX_LOCK.
5445 ****************************************************************************/
5447 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5448 const struct smb_request *req,
5454 SMB_BIG_UINT offset;
5456 bool blocking_lock = False;
5457 enum brl_type lock_type;
5459 NTSTATUS status = NT_STATUS_OK;
5461 if (fsp == NULL || fsp->fh->fd == -1) {
5462 return NT_STATUS_INVALID_HANDLE;
5465 if (total_data != POSIX_LOCK_DATA_SIZE) {
5466 return NT_STATUS_INVALID_PARAMETER;
5469 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5470 case POSIX_LOCK_TYPE_READ:
5471 lock_type = READ_LOCK;
5473 case POSIX_LOCK_TYPE_WRITE:
5474 /* Return the right POSIX-mappable error code for files opened read-only. */
5475 if (!fsp->can_write) {
5476 return NT_STATUS_INVALID_HANDLE;
5478 lock_type = WRITE_LOCK;
5480 case POSIX_LOCK_TYPE_UNLOCK:
5481 lock_type = UNLOCK_LOCK;
5484 return NT_STATUS_INVALID_PARAMETER;
5487 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5488 blocking_lock = False;
5489 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5490 blocking_lock = True;
5492 return NT_STATUS_INVALID_PARAMETER;
5495 if (!lp_blocking_locks(SNUM(conn))) {
5496 blocking_lock = False;
5499 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5500 #if defined(HAVE_LONGLONG)
5501 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5502 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5503 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5504 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5505 #else /* HAVE_LONGLONG */
5506 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5507 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5508 #endif /* HAVE_LONGLONG */
5510 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5511 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5513 (unsigned int)lock_type,
5514 (unsigned int)lock_pid,
5518 if (lock_type == UNLOCK_LOCK) {
5519 status = do_unlock(smbd_messaging_context(),
5526 uint32 block_smbpid;
5528 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5539 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5541 * A blocking lock was requested. Package up
5542 * this smb into a queued request and push it
5543 * onto the blocking lock queue.
5545 if(push_blocking_lock_request(br_lck,
5548 -1, /* infinite timeout. */
5556 TALLOC_FREE(br_lck);
5560 TALLOC_FREE(br_lck);
5566 /****************************************************************************
5567 Deal with SMB_INFO_STANDARD.
5568 ****************************************************************************/
5570 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5575 const SMB_STRUCT_STAT *psbuf)
5577 struct timespec ts[2];
5579 if (total_data < 12) {
5580 return NT_STATUS_INVALID_PARAMETER;
5584 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5586 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5588 DEBUG(10,("smb_set_info_standard: file %s\n",
5589 fname ? fname : fsp->fsp_name ));
5591 return smb_set_file_time(conn,
5599 /****************************************************************************
5600 Deal with SMB_SET_FILE_BASIC_INFO.
5601 ****************************************************************************/
5603 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5608 SMB_STRUCT_STAT *psbuf)
5610 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5611 struct timespec write_time;
5612 struct timespec changed_time;
5614 struct timespec ts[2];
5615 NTSTATUS status = NT_STATUS_OK;
5616 bool setting_write_time = true;
5618 if (total_data < 36) {
5619 return NT_STATUS_INVALID_PARAMETER;
5622 /* Set the attributes */
5623 dosmode = IVAL(pdata,32);
5624 status = smb_set_file_dosmode(conn,
5628 if (!NT_STATUS_IS_OK(status)) {
5632 /* Ignore create time at offset pdata. */
5635 ts[0] = interpret_long_date(pdata+8);
5637 write_time = interpret_long_date(pdata+16);
5638 changed_time = interpret_long_date(pdata+24);
5641 ts[1] = timespec_min(&write_time, &changed_time);
5643 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5647 /* Prefer a defined time to an undefined one. */
5648 if (null_timespec(ts[1])) {
5649 if (null_timespec(write_time)) {
5650 ts[1] = changed_time;
5651 setting_write_time = false;
5657 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5658 fname ? fname : fsp->fsp_name ));
5660 return smb_set_file_time(conn,
5665 setting_write_time);
5668 /****************************************************************************
5669 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5670 ****************************************************************************/
5672 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5673 struct smb_request *req,
5678 SMB_STRUCT_STAT *psbuf)
5680 SMB_BIG_UINT allocation_size = 0;
5681 NTSTATUS status = NT_STATUS_OK;
5682 files_struct *new_fsp = NULL;
5684 if (!VALID_STAT(*psbuf)) {
5685 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5688 if (total_data < 8) {
5689 return NT_STATUS_INVALID_PARAMETER;
5692 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5693 #ifdef LARGE_SMB_OFF_T
5694 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5695 #else /* LARGE_SMB_OFF_T */
5696 if (IVAL(pdata,4) != 0) {
5697 /* more than 32 bits? */
5698 return NT_STATUS_INVALID_PARAMETER;
5700 #endif /* LARGE_SMB_OFF_T */
5702 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5703 fname, (double)allocation_size ));
5705 if (allocation_size) {
5706 allocation_size = smb_roundup(conn, allocation_size);
5709 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5710 fname, (double)allocation_size ));
5712 if (fsp && fsp->fh->fd != -1) {
5713 /* Open file handle. */
5714 /* Only change if needed. */
5715 if (allocation_size != get_file_size(*psbuf)) {
5716 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5717 return map_nt_error_from_unix(errno);
5720 /* But always update the time. */
5722 * This is equivalent to a write. Ensure it's seen immediately
5723 * if there are no pending writes.
5725 trigger_write_time_update_immediate(fsp);
5726 return NT_STATUS_OK;
5729 /* Pathname or stat or directory file. */
5731 status = open_file_ntcreate(conn, req, fname, psbuf,
5733 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5736 FILE_ATTRIBUTE_NORMAL,
5737 FORCE_OPLOCK_BREAK_TO_NONE,
5740 if (!NT_STATUS_IS_OK(status)) {
5741 /* NB. We check for open_was_deferred in the caller. */
5745 /* Only change if needed. */
5746 if (allocation_size != get_file_size(*psbuf)) {
5747 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5748 status = map_nt_error_from_unix(errno);
5749 close_file(new_fsp,NORMAL_CLOSE);
5754 /* Changing the allocation size should set the last mod time. */
5756 * This is equivalent to a write. Ensure it's seen immediately
5757 * if there are no pending writes.
5759 trigger_write_time_update_immediate(new_fsp);
5761 close_file(new_fsp,NORMAL_CLOSE);
5762 return NT_STATUS_OK;
5765 /****************************************************************************
5766 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5767 ****************************************************************************/
5769 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5770 struct smb_request *req,
5775 SMB_STRUCT_STAT *psbuf)
5779 if (total_data < 8) {
5780 return NT_STATUS_INVALID_PARAMETER;
5783 size = IVAL(pdata,0);
5784 #ifdef LARGE_SMB_OFF_T
5785 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5786 #else /* LARGE_SMB_OFF_T */
5787 if (IVAL(pdata,4) != 0) {
5788 /* more than 32 bits? */
5789 return NT_STATUS_INVALID_PARAMETER;
5791 #endif /* LARGE_SMB_OFF_T */
5792 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5793 "file %s to %.0f\n", fname, (double)size ));
5795 return smb_set_file_size(conn, req,
5802 /****************************************************************************
5803 Allow a UNIX info mknod.
5804 ****************************************************************************/
5806 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5810 SMB_STRUCT_STAT *psbuf)
5812 uint32 file_type = IVAL(pdata,56);
5813 #if defined(HAVE_MAKEDEV)
5814 uint32 dev_major = IVAL(pdata,60);
5815 uint32 dev_minor = IVAL(pdata,68);
5817 SMB_DEV_T dev = (SMB_DEV_T)0;
5818 uint32 raw_unixmode = IVAL(pdata,84);
5822 if (total_data < 100) {
5823 return NT_STATUS_INVALID_PARAMETER;
5826 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5827 if (!NT_STATUS_IS_OK(status)) {
5831 #if defined(HAVE_MAKEDEV)
5832 dev = makedev(dev_major, dev_minor);
5835 switch (file_type) {
5836 #if defined(S_IFIFO)
5837 case UNIX_TYPE_FIFO:
5838 unixmode |= S_IFIFO;
5841 #if defined(S_IFSOCK)
5842 case UNIX_TYPE_SOCKET:
5843 unixmode |= S_IFSOCK;
5846 #if defined(S_IFCHR)
5847 case UNIX_TYPE_CHARDEV:
5848 unixmode |= S_IFCHR;
5851 #if defined(S_IFBLK)
5852 case UNIX_TYPE_BLKDEV:
5853 unixmode |= S_IFBLK;
5857 return NT_STATUS_INVALID_PARAMETER;
5860 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5861 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5863 /* Ok - do the mknod. */
5864 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5865 return map_nt_error_from_unix(errno);
5868 /* If any of the other "set" calls fail we
5869 * don't want to end up with a half-constructed mknod.
5872 if (lp_inherit_perms(SNUM(conn))) {
5874 conn, parent_dirname(fname),
5878 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5879 status = map_nt_error_from_unix(errno);
5880 SMB_VFS_UNLINK(conn,fname);
5883 return NT_STATUS_OK;
5886 /****************************************************************************
5887 Deal with SMB_SET_FILE_UNIX_BASIC.
5888 ****************************************************************************/
5890 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5891 struct smb_request *req,
5896 SMB_STRUCT_STAT *psbuf)
5898 struct timespec ts[2];
5899 uint32 raw_unixmode;
5902 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5903 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5904 NTSTATUS status = NT_STATUS_OK;
5905 bool delete_on_fail = False;
5906 enum perm_type ptype;
5908 if (total_data < 100) {
5909 return NT_STATUS_INVALID_PARAMETER;
5912 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5913 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5914 size=IVAL(pdata,0); /* first 8 Bytes are size */
5915 #ifdef LARGE_SMB_OFF_T
5916 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5917 #else /* LARGE_SMB_OFF_T */
5918 if (IVAL(pdata,4) != 0) {
5919 /* more than 32 bits? */
5920 return NT_STATUS_INVALID_PARAMETER;
5922 #endif /* LARGE_SMB_OFF_T */
5925 ts[0] = interpret_long_date(pdata+24); /* access_time */
5926 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5927 set_owner = (uid_t)IVAL(pdata,40);
5928 set_grp = (gid_t)IVAL(pdata,48);
5929 raw_unixmode = IVAL(pdata,84);
5931 if (VALID_STAT(*psbuf)) {
5932 if (S_ISDIR(psbuf->st_mode)) {
5933 ptype = PERM_EXISTING_DIR;
5935 ptype = PERM_EXISTING_FILE;
5938 ptype = PERM_NEW_FILE;
5941 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5942 if (!NT_STATUS_IS_OK(status)) {
5946 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5947 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5948 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5950 if (!VALID_STAT(*psbuf)) {
5952 * The only valid use of this is to create character and block
5953 * devices, and named pipes. This is deprecated (IMHO) and
5954 * a new info level should be used for mknod. JRA.
5957 status = smb_unix_mknod(conn,
5962 if (!NT_STATUS_IS_OK(status)) {
5966 /* Ensure we don't try and change anything else. */
5967 raw_unixmode = SMB_MODE_NO_CHANGE;
5968 size = get_file_size(*psbuf);
5969 ts[0] = get_atimespec(psbuf);
5970 ts[1] = get_mtimespec(psbuf);
5972 * We continue here as we might want to change the
5975 delete_on_fail = True;
5979 /* Horrible backwards compatibility hack as an old server bug
5980 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5984 size = get_file_size(*psbuf);
5989 * Deal with the UNIX specific mode set.
5992 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5993 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5994 (unsigned int)unixmode, fname ));
5995 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5996 return map_nt_error_from_unix(errno);
6001 * Deal with the UNIX specific uid set.
6004 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6007 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6008 (unsigned int)set_owner, fname ));
6010 if (S_ISLNK(psbuf->st_mode)) {
6011 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6013 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6017 status = map_nt_error_from_unix(errno);
6018 if (delete_on_fail) {
6019 SMB_VFS_UNLINK(conn,fname);
6026 * Deal with the UNIX specific gid set.
6029 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6030 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6031 (unsigned int)set_owner, fname ));
6032 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6033 status = map_nt_error_from_unix(errno);
6034 if (delete_on_fail) {
6035 SMB_VFS_UNLINK(conn,fname);
6041 /* Deal with any size changes. */
6043 status = smb_set_file_size(conn, req,
6048 if (!NT_STATUS_IS_OK(status)) {
6052 /* Deal with any time changes. */
6054 return smb_set_file_time(conn,
6062 /****************************************************************************
6063 Deal with SMB_SET_FILE_UNIX_INFO2.
6064 ****************************************************************************/
6066 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6067 struct smb_request *req,
6072 SMB_STRUCT_STAT *psbuf)
6078 if (total_data < 116) {
6079 return NT_STATUS_INVALID_PARAMETER;
6082 /* Start by setting all the fields that are common between UNIX_BASIC
6085 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6087 if (!NT_STATUS_IS_OK(status)) {
6091 smb_fflags = IVAL(pdata, 108);
6092 smb_fmask = IVAL(pdata, 112);
6094 /* NB: We should only attempt to alter the file flags if the client
6095 * sends a non-zero mask.
6097 if (smb_fmask != 0) {
6098 int stat_fflags = 0;
6100 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6102 /* Client asked to alter a flag we don't understand. */
6103 return NT_STATUS_INVALID_PARAMETER;
6106 if (fsp && fsp->fh->fd != -1) {
6107 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6108 return NT_STATUS_NOT_SUPPORTED;
6110 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6111 return map_nt_error_from_unix(errno);
6116 /* XXX: need to add support for changing the create_time here. You
6117 * can do this for paths on Darwin with setattrlist(2). The right way
6118 * to hook this up is probably by extending the VFS utimes interface.
6121 return NT_STATUS_OK;
6124 /****************************************************************************
6125 Create a directory with POSIX semantics.
6126 ****************************************************************************/
6128 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6129 struct smb_request *req,
6133 SMB_STRUCT_STAT *psbuf,
6134 int *pdata_return_size)
6136 NTSTATUS status = NT_STATUS_OK;
6137 uint32 raw_unixmode = 0;
6138 uint32 mod_unixmode = 0;
6139 mode_t unixmode = (mode_t)0;
6140 files_struct *fsp = NULL;
6141 uint16 info_level_return = 0;
6143 char *pdata = *ppdata;
6145 if (total_data < 18) {
6146 return NT_STATUS_INVALID_PARAMETER;
6149 raw_unixmode = IVAL(pdata,8);
6150 /* Next 4 bytes are not yet defined. */
6152 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6153 if (!NT_STATUS_IS_OK(status)) {
6157 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6159 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6160 fname, (unsigned int)unixmode ));
6162 status = open_directory(conn, req,
6165 FILE_READ_ATTRIBUTES, /* Just a stat open */
6166 FILE_SHARE_NONE, /* Ignored for stat opens */
6173 if (NT_STATUS_IS_OK(status)) {
6174 close_file(fsp, NORMAL_CLOSE);
6177 info_level_return = SVAL(pdata,16);
6179 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6180 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6181 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6182 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6184 *pdata_return_size = 12;
6187 /* Realloc the data size */
6188 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6189 if (*ppdata == NULL) {
6190 *pdata_return_size = 0;
6191 return NT_STATUS_NO_MEMORY;
6195 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6196 SSVAL(pdata,2,0); /* No fnum. */
6197 SIVAL(pdata,4,info); /* Was directory created. */
6199 switch (info_level_return) {
6200 case SMB_QUERY_FILE_UNIX_BASIC:
6201 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6202 SSVAL(pdata,10,0); /* Padding. */
6203 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6205 case SMB_QUERY_FILE_UNIX_INFO2:
6206 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6207 SSVAL(pdata,10,0); /* Padding. */
6208 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6211 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6212 SSVAL(pdata,10,0); /* Padding. */
6219 /****************************************************************************
6220 Open/Create a file with POSIX semantics.
6221 ****************************************************************************/
6223 static NTSTATUS smb_posix_open(connection_struct *conn,
6224 struct smb_request *req,
6228 SMB_STRUCT_STAT *psbuf,
6229 int *pdata_return_size)
6231 bool extended_oplock_granted = False;
6232 char *pdata = *ppdata;
6234 uint32 wire_open_mode = 0;
6235 uint32 raw_unixmode = 0;
6236 uint32 mod_unixmode = 0;
6237 uint32 create_disp = 0;
6238 uint32 access_mask = 0;
6239 uint32 create_options = 0;
6240 NTSTATUS status = NT_STATUS_OK;
6241 mode_t unixmode = (mode_t)0;
6242 files_struct *fsp = NULL;
6243 int oplock_request = 0;
6245 uint16 info_level_return = 0;
6247 if (total_data < 18) {
6248 return NT_STATUS_INVALID_PARAMETER;
6251 flags = IVAL(pdata,0);
6252 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6253 if (oplock_request) {
6254 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6257 wire_open_mode = IVAL(pdata,4);
6259 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6260 return smb_posix_mkdir(conn, req,
6268 switch (wire_open_mode & SMB_ACCMODE) {
6270 access_mask = FILE_READ_DATA;
6273 access_mask = FILE_WRITE_DATA;
6276 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6279 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6280 (unsigned int)wire_open_mode ));
6281 return NT_STATUS_INVALID_PARAMETER;
6284 wire_open_mode &= ~SMB_ACCMODE;
6286 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6287 create_disp = FILE_CREATE;
6288 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6289 create_disp = FILE_OVERWRITE_IF;
6290 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6291 create_disp = FILE_OPEN_IF;
6293 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6294 (unsigned int)wire_open_mode ));
6295 return NT_STATUS_INVALID_PARAMETER;
6298 raw_unixmode = IVAL(pdata,8);
6299 /* Next 4 bytes are not yet defined. */
6301 status = unix_perms_from_wire(conn,
6304 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6307 if (!NT_STATUS_IS_OK(status)) {
6311 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6313 if (wire_open_mode & SMB_O_SYNC) {
6314 create_options |= FILE_WRITE_THROUGH;
6316 if (wire_open_mode & SMB_O_APPEND) {
6317 access_mask |= FILE_APPEND_DATA;
6319 if (wire_open_mode & SMB_O_DIRECT) {
6320 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6323 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6325 (unsigned int)wire_open_mode,
6326 (unsigned int)unixmode ));
6328 status = open_file_ntcreate(conn, req,
6332 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6334 0, /* no create options yet. */
6340 if (!NT_STATUS_IS_OK(status)) {
6344 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6345 extended_oplock_granted = True;
6348 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6349 extended_oplock_granted = True;
6352 info_level_return = SVAL(pdata,16);
6354 /* Allocate the correct return size. */
6356 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6357 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6358 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6359 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6361 *pdata_return_size = 12;
6364 /* Realloc the data size */
6365 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6366 if (*ppdata == NULL) {
6367 close_file(fsp,ERROR_CLOSE);
6368 *pdata_return_size = 0;
6369 return NT_STATUS_NO_MEMORY;
6373 if (extended_oplock_granted) {
6374 if (flags & REQUEST_BATCH_OPLOCK) {
6375 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6377 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6379 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6380 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6382 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6385 SSVAL(pdata,2,fsp->fnum);
6386 SIVAL(pdata,4,info); /* Was file created etc. */
6388 switch (info_level_return) {
6389 case SMB_QUERY_FILE_UNIX_BASIC:
6390 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6391 SSVAL(pdata,10,0); /* padding. */
6392 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6394 case SMB_QUERY_FILE_UNIX_INFO2:
6395 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6396 SSVAL(pdata,10,0); /* padding. */
6397 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6400 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6401 SSVAL(pdata,10,0); /* padding. */
6404 return NT_STATUS_OK;
6407 /****************************************************************************
6408 Delete a file with POSIX semantics.
6409 ****************************************************************************/
6411 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6412 struct smb_request *req,
6416 SMB_STRUCT_STAT *psbuf)
6418 NTSTATUS status = NT_STATUS_OK;
6419 files_struct *fsp = NULL;
6424 struct share_mode_lock *lck = NULL;
6426 if (total_data < 2) {
6427 return NT_STATUS_INVALID_PARAMETER;
6430 flags = SVAL(pdata,0);
6432 if (!VALID_STAT(*psbuf)) {
6433 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6436 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6437 !VALID_STAT_OF_DIR(*psbuf)) {
6438 return NT_STATUS_NOT_A_DIRECTORY;
6441 DEBUG(10,("smb_posix_unlink: %s %s\n",
6442 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6445 if (VALID_STAT_OF_DIR(*psbuf)) {
6446 status = open_directory(conn, req,
6450 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6453 FILE_FLAG_POSIX_SEMANTICS|0777,
6458 status = open_file_ntcreate(conn, req,
6462 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6465 FILE_FLAG_POSIX_SEMANTICS|0777,
6466 0, /* No oplock, but break existing ones. */
6471 if (!NT_STATUS_IS_OK(status)) {
6476 * Don't lie to client. If we can't really delete due to
6477 * non-POSIX opens return SHARING_VIOLATION.
6480 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6483 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6484 "lock for file %s\n", fsp->fsp_name));
6485 close_file(fsp, NORMAL_CLOSE);
6486 return NT_STATUS_INVALID_PARAMETER;
6490 * See if others still have the file open. If this is the case, then
6491 * don't delete. If all opens are POSIX delete we can set the delete
6492 * on close disposition.
6494 for (i=0; i<lck->num_share_modes; i++) {
6495 struct share_mode_entry *e = &lck->share_modes[i];
6496 if (is_valid_share_mode_entry(e)) {
6497 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6500 /* Fail with sharing violation. */
6501 close_file(fsp, NORMAL_CLOSE);
6503 return NT_STATUS_SHARING_VIOLATION;
6508 * Set the delete on close.
6510 status = smb_set_file_disposition_info(conn,
6517 if (!NT_STATUS_IS_OK(status)) {
6518 close_file(fsp, NORMAL_CLOSE);
6523 return close_file(fsp, NORMAL_CLOSE);
6526 /****************************************************************************
6527 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6528 ****************************************************************************/
6530 static void call_trans2setfilepathinfo(connection_struct *conn,
6531 struct smb_request *req,
6532 unsigned int tran_call,
6533 char **pparams, int total_params,
6534 char **ppdata, int total_data,
6535 unsigned int max_data_bytes)
6537 char *params = *pparams;
6538 char *pdata = *ppdata;
6540 SMB_STRUCT_STAT sbuf;
6542 files_struct *fsp = NULL;
6543 NTSTATUS status = NT_STATUS_OK;
6544 int data_return_size = 0;
6545 TALLOC_CTX *ctx = talloc_tos();
6548 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6554 if (tran_call == TRANSACT2_SETFILEINFO) {
6555 if (total_params < 4) {
6556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6560 fsp = file_fsp(SVAL(params,0));
6561 /* Basic check for non-null fsp. */
6562 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6565 info_level = SVAL(params,2);
6567 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6569 reply_nterror(req, NT_STATUS_NO_MEMORY);
6573 if(fsp->is_directory || fsp->fh->fd == -1) {
6575 * This is actually a SETFILEINFO on a directory
6576 * handle (returned from an NT SMB). NT5.0 seems
6577 * to do this call. JRA.
6579 if (INFO_LEVEL_IS_UNIX(info_level)) {
6580 /* Always do lstat for UNIX calls. */
6581 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6582 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6583 reply_unixerror(req,ERRDOS,ERRbadpath);
6587 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6588 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6589 reply_unixerror(req,ERRDOS,ERRbadpath);
6593 } else if (fsp->print_file) {
6595 * Doing a DELETE_ON_CLOSE should cancel a print job.
6597 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6598 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6600 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6603 send_trans2_replies(conn, req, params, 2,
6608 reply_unixerror(req, ERRDOS, ERRbadpath);
6613 * Original code - this is an open file.
6615 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6619 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6620 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6621 reply_unixerror(req, ERRDOS, ERRbadfid);
6627 if (total_params < 7) {
6628 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6632 info_level = SVAL(params,0);
6633 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6634 total_params - 6, STR_TERMINATE,
6636 if (!NT_STATUS_IS_OK(status)) {
6637 reply_nterror(req, status);
6641 status = resolve_dfspath(ctx, conn,
6642 req->flags2 & FLAGS2_DFS_PATHNAMES,
6645 if (!NT_STATUS_IS_OK(status)) {
6646 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6647 reply_botherror(req,
6648 NT_STATUS_PATH_NOT_COVERED,
6649 ERRSRV, ERRbadpath);
6652 reply_nterror(req, status);
6656 status = unix_convert(ctx, conn, fname, False,
6657 &fname, NULL, &sbuf);
6658 if (!NT_STATUS_IS_OK(status)) {
6659 reply_nterror(req, status);
6663 status = check_name(conn, fname);
6664 if (!NT_STATUS_IS_OK(status)) {
6665 reply_nterror(req, status);
6669 if (INFO_LEVEL_IS_UNIX(info_level)) {
6671 * For CIFS UNIX extensions the target name may not exist.
6674 /* Always do lstat for UNIX calls. */
6675 SMB_VFS_LSTAT(conn,fname,&sbuf);
6677 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6678 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6679 reply_unixerror(req, ERRDOS, ERRbadpath);
6684 if (!CAN_WRITE(conn)) {
6685 reply_doserror(req, ERRSRV, ERRaccess);
6689 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6690 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6694 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6695 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6697 /* Realloc the parameter size */
6698 *pparams = (char *)SMB_REALLOC(*pparams,2);
6699 if (*pparams == NULL) {
6700 reply_nterror(req, NT_STATUS_NO_MEMORY);
6707 switch (info_level) {
6709 case SMB_INFO_STANDARD:
6711 status = smb_set_info_standard(conn,
6720 case SMB_INFO_SET_EA:
6722 status = smb_info_set_ea(conn,
6730 case SMB_SET_FILE_BASIC_INFO:
6731 case SMB_FILE_BASIC_INFORMATION:
6733 status = smb_set_file_basic_info(conn,
6742 case SMB_FILE_ALLOCATION_INFORMATION:
6743 case SMB_SET_FILE_ALLOCATION_INFO:
6745 status = smb_set_file_allocation_info(conn, req,
6754 case SMB_FILE_END_OF_FILE_INFORMATION:
6755 case SMB_SET_FILE_END_OF_FILE_INFO:
6757 status = smb_set_file_end_of_file_info(conn, req,
6766 case SMB_FILE_DISPOSITION_INFORMATION:
6767 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6770 /* JRA - We used to just ignore this on a path ?
6771 * Shouldn't this be invalid level on a pathname
6774 if (tran_call != TRANSACT2_SETFILEINFO) {
6775 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6778 status = smb_set_file_disposition_info(conn,
6787 case SMB_FILE_POSITION_INFORMATION:
6789 status = smb_file_position_information(conn,
6796 /* From tridge Samba4 :
6797 * MODE_INFORMATION in setfileinfo (I have no
6798 * idea what "mode information" on a file is - it takes a value of 0,
6799 * 2, 4 or 6. What could it be?).
6802 case SMB_FILE_MODE_INFORMATION:
6804 status = smb_file_mode_information(conn,
6811 * CIFS UNIX extensions.
6814 case SMB_SET_FILE_UNIX_BASIC:
6816 status = smb_set_file_unix_basic(conn, req,
6825 case SMB_SET_FILE_UNIX_INFO2:
6827 status = smb_set_file_unix_info2(conn, req,
6836 case SMB_SET_FILE_UNIX_LINK:
6838 if (tran_call != TRANSACT2_SETPATHINFO) {
6839 /* We must have a pathname for this. */
6840 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6843 status = smb_set_file_unix_link(conn, req, pdata,
6848 case SMB_SET_FILE_UNIX_HLINK:
6850 if (tran_call != TRANSACT2_SETPATHINFO) {
6851 /* We must have a pathname for this. */
6852 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6855 status = smb_set_file_unix_hlink(conn, req,
6861 case SMB_FILE_RENAME_INFORMATION:
6863 status = smb_file_rename_information(conn, req,
6869 #if defined(HAVE_POSIX_ACLS)
6870 case SMB_SET_POSIX_ACL:
6872 status = smb_set_posix_acl(conn,
6882 case SMB_SET_POSIX_LOCK:
6884 if (tran_call != TRANSACT2_SETFILEINFO) {
6885 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6888 status = smb_set_posix_lock(conn, req,
6889 pdata, total_data, fsp);
6893 case SMB_POSIX_PATH_OPEN:
6895 if (tran_call != TRANSACT2_SETPATHINFO) {
6896 /* We must have a pathname for this. */
6897 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6901 status = smb_posix_open(conn, req,
6910 case SMB_POSIX_PATH_UNLINK:
6912 if (tran_call != TRANSACT2_SETPATHINFO) {
6913 /* We must have a pathname for this. */
6914 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6918 status = smb_posix_unlink(conn, req,
6927 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6932 if (!NT_STATUS_IS_OK(status)) {
6933 if (open_was_deferred(req->mid)) {
6934 /* We have re-scheduled this call. */
6937 if (blocking_lock_was_deferred(req->mid)) {
6938 /* We have re-scheduled this call. */
6941 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6942 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6943 ERRSRV, ERRbadpath);
6946 if (info_level == SMB_POSIX_PATH_OPEN) {
6947 reply_openerror(req, status);
6951 reply_nterror(req, status);
6956 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6962 /****************************************************************************
6963 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6964 ****************************************************************************/
6966 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6967 char **pparams, int total_params,
6968 char **ppdata, int total_data,
6969 unsigned int max_data_bytes)
6971 char *params = *pparams;
6972 char *pdata = *ppdata;
6973 char *directory = NULL;
6974 SMB_STRUCT_STAT sbuf;
6975 NTSTATUS status = NT_STATUS_OK;
6976 struct ea_list *ea_list = NULL;
6977 TALLOC_CTX *ctx = talloc_tos();
6979 if (!CAN_WRITE(conn)) {
6980 reply_doserror(req, ERRSRV, ERRaccess);
6984 if (total_params < 5) {
6985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6989 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6990 total_params - 4, STR_TERMINATE,
6992 if (!NT_STATUS_IS_OK(status)) {
6993 reply_nterror(req, status);
6997 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6999 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7000 if (!NT_STATUS_IS_OK(status)) {
7001 reply_nterror(req, status);
7005 status = check_name(conn, directory);
7006 if (!NT_STATUS_IS_OK(status)) {
7007 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7008 reply_nterror(req, status);
7012 /* Any data in this call is an EA list. */
7013 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7014 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7019 * OS/2 workplace shell seems to send SET_EA requests of "null"
7020 * length (4 bytes containing IVAL 4).
7021 * They seem to have no effect. Bug #3212. JRA.
7024 if (total_data != 4) {
7025 if (total_data < 10) {
7026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7030 if (IVAL(pdata,0) > total_data) {
7031 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7032 IVAL(pdata,0), (unsigned int)total_data));
7033 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7037 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7043 } else if (IVAL(pdata,0) != 4) {
7044 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7048 status = create_directory(conn, req, directory);
7050 if (!NT_STATUS_IS_OK(status)) {
7051 reply_nterror(req, status);
7055 /* Try and set any given EA. */
7057 status = set_ea(conn, NULL, directory, ea_list);
7058 if (!NT_STATUS_IS_OK(status)) {
7059 reply_nterror(req, status);
7064 /* Realloc the parameter and data sizes */
7065 *pparams = (char *)SMB_REALLOC(*pparams,2);
7066 if(*pparams == NULL) {
7067 reply_nterror(req, NT_STATUS_NO_MEMORY);
7074 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7079 /****************************************************************************
7080 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7081 We don't actually do this - we just send a null response.
7082 ****************************************************************************/
7084 static void call_trans2findnotifyfirst(connection_struct *conn,
7085 struct smb_request *req,
7086 char **pparams, int total_params,
7087 char **ppdata, int total_data,
7088 unsigned int max_data_bytes)
7090 static uint16 fnf_handle = 257;
7091 char *params = *pparams;
7094 if (total_params < 6) {
7095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7099 info_level = SVAL(params,4);
7100 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7102 switch (info_level) {
7107 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7111 /* Realloc the parameter and data sizes */
7112 *pparams = (char *)SMB_REALLOC(*pparams,6);
7113 if (*pparams == NULL) {
7114 reply_nterror(req, NT_STATUS_NO_MEMORY);
7119 SSVAL(params,0,fnf_handle);
7120 SSVAL(params,2,0); /* No changes */
7121 SSVAL(params,4,0); /* No EA errors */
7128 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7133 /****************************************************************************
7134 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7135 changes). Currently this does nothing.
7136 ****************************************************************************/
7138 static void call_trans2findnotifynext(connection_struct *conn,
7139 struct smb_request *req,
7140 char **pparams, int total_params,
7141 char **ppdata, int total_data,
7142 unsigned int max_data_bytes)
7144 char *params = *pparams;
7146 DEBUG(3,("call_trans2findnotifynext\n"));
7148 /* Realloc the parameter and data sizes */
7149 *pparams = (char *)SMB_REALLOC(*pparams,4);
7150 if (*pparams == NULL) {
7151 reply_nterror(req, NT_STATUS_NO_MEMORY);
7156 SSVAL(params,0,0); /* No changes */
7157 SSVAL(params,2,0); /* No EA errors */
7159 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7164 /****************************************************************************
7165 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7166 ****************************************************************************/
7168 static void call_trans2getdfsreferral(connection_struct *conn,
7169 struct smb_request *req,
7170 char **pparams, int total_params,
7171 char **ppdata, int total_data,
7172 unsigned int max_data_bytes)
7174 char *params = *pparams;
7175 char *pathname = NULL;
7177 int max_referral_level;
7178 NTSTATUS status = NT_STATUS_OK;
7179 TALLOC_CTX *ctx = talloc_tos();
7181 DEBUG(10,("call_trans2getdfsreferral\n"));
7183 if (total_params < 3) {
7184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7188 max_referral_level = SVAL(params,0);
7190 if(!lp_host_msdfs()) {
7191 reply_doserror(req, ERRDOS, ERRbadfunc);
7195 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7196 total_params - 2, STR_TERMINATE);
7198 reply_nterror(req, NT_STATUS_NOT_FOUND);
7201 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7202 ppdata,&status)) < 0) {
7203 reply_nterror(req, status);
7207 SSVAL(req->inbuf, smb_flg2,
7208 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7209 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7214 #define LMCAT_SPL 0x53
7215 #define LMFUNC_GETJOBID 0x60
7217 /****************************************************************************
7218 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7219 ****************************************************************************/
7221 static void call_trans2ioctl(connection_struct *conn,
7222 struct smb_request *req,
7223 char **pparams, int total_params,
7224 char **ppdata, int total_data,
7225 unsigned int max_data_bytes)
7227 char *pdata = *ppdata;
7228 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7230 /* check for an invalid fid before proceeding */
7233 reply_doserror(req, ERRDOS, ERRbadfid);
7237 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7238 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7239 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7240 if (*ppdata == NULL) {
7241 reply_nterror(req, NT_STATUS_NO_MEMORY);
7246 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7247 CAN ACCEPT THIS IN UNICODE. JRA. */
7249 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7250 srvstr_push(pdata, req->flags2, pdata + 2,
7251 global_myname(), 15,
7252 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7253 srvstr_push(pdata, req->flags2, pdata+18,
7254 lp_servicename(SNUM(conn)), 13,
7255 STR_ASCII|STR_TERMINATE); /* Service name */
7256 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7261 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7262 reply_doserror(req, ERRSRV, ERRerror);
7265 /****************************************************************************
7266 Reply to a SMBfindclose (stop trans2 directory search).
7267 ****************************************************************************/
7269 void reply_findclose(struct smb_request *req)
7273 START_PROFILE(SMBfindclose);
7276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7277 END_PROFILE(SMBfindclose);
7281 dptr_num = SVALS(req->inbuf,smb_vwv0);
7283 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7285 dptr_close(&dptr_num);
7287 reply_outbuf(req, 0, 0);
7289 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7291 END_PROFILE(SMBfindclose);
7295 /****************************************************************************
7296 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7297 ****************************************************************************/
7299 void reply_findnclose(struct smb_request *req)
7303 START_PROFILE(SMBfindnclose);
7306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7307 END_PROFILE(SMBfindnclose);
7311 dptr_num = SVAL(req->inbuf,smb_vwv0);
7313 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7315 /* We never give out valid handles for a
7316 findnotifyfirst - so any dptr_num is ok here.
7319 reply_outbuf(req, 0, 0);
7321 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7323 END_PROFILE(SMBfindnclose);
7327 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7328 struct trans_state *state)
7330 if (Protocol >= PROTOCOL_NT1) {
7331 req->flags2 |= 0x40; /* IS_LONG_NAME */
7332 SSVAL(req->inbuf,smb_flg2,req->flags2);
7335 if (conn->encrypt_level == Required && !req->encrypted) {
7336 if (state->call != TRANSACT2_QFSINFO &&
7337 state->call != TRANSACT2_SETFSINFO) {
7338 DEBUG(0,("handle_trans2: encryption required "
7340 (unsigned int)state->call));
7341 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7346 /* Now we must call the relevant TRANS2 function */
7347 switch(state->call) {
7348 case TRANSACT2_OPEN:
7350 START_PROFILE(Trans2_open);
7351 call_trans2open(conn, req,
7352 &state->param, state->total_param,
7353 &state->data, state->total_data,
7354 state->max_data_return);
7355 END_PROFILE(Trans2_open);
7359 case TRANSACT2_FINDFIRST:
7361 START_PROFILE(Trans2_findfirst);
7362 call_trans2findfirst(conn, req,
7363 &state->param, state->total_param,
7364 &state->data, state->total_data,
7365 state->max_data_return);
7366 END_PROFILE(Trans2_findfirst);
7370 case TRANSACT2_FINDNEXT:
7372 START_PROFILE(Trans2_findnext);
7373 call_trans2findnext(conn, req,
7374 &state->param, state->total_param,
7375 &state->data, state->total_data,
7376 state->max_data_return);
7377 END_PROFILE(Trans2_findnext);
7381 case TRANSACT2_QFSINFO:
7383 START_PROFILE(Trans2_qfsinfo);
7384 call_trans2qfsinfo(conn, req,
7385 &state->param, state->total_param,
7386 &state->data, state->total_data,
7387 state->max_data_return);
7388 END_PROFILE(Trans2_qfsinfo);
7392 case TRANSACT2_SETFSINFO:
7394 START_PROFILE(Trans2_setfsinfo);
7395 call_trans2setfsinfo(conn, req,
7396 &state->param, state->total_param,
7397 &state->data, state->total_data,
7398 state->max_data_return);
7399 END_PROFILE(Trans2_setfsinfo);
7403 case TRANSACT2_QPATHINFO:
7404 case TRANSACT2_QFILEINFO:
7406 START_PROFILE(Trans2_qpathinfo);
7407 call_trans2qfilepathinfo(conn, req, state->call,
7408 &state->param, state->total_param,
7409 &state->data, state->total_data,
7410 state->max_data_return);
7411 END_PROFILE(Trans2_qpathinfo);
7415 case TRANSACT2_SETPATHINFO:
7416 case TRANSACT2_SETFILEINFO:
7418 START_PROFILE(Trans2_setpathinfo);
7419 call_trans2setfilepathinfo(conn, req, state->call,
7420 &state->param, state->total_param,
7421 &state->data, state->total_data,
7422 state->max_data_return);
7423 END_PROFILE(Trans2_setpathinfo);
7427 case TRANSACT2_FINDNOTIFYFIRST:
7429 START_PROFILE(Trans2_findnotifyfirst);
7430 call_trans2findnotifyfirst(conn, req,
7431 &state->param, state->total_param,
7432 &state->data, state->total_data,
7433 state->max_data_return);
7434 END_PROFILE(Trans2_findnotifyfirst);
7438 case TRANSACT2_FINDNOTIFYNEXT:
7440 START_PROFILE(Trans2_findnotifynext);
7441 call_trans2findnotifynext(conn, req,
7442 &state->param, state->total_param,
7443 &state->data, state->total_data,
7444 state->max_data_return);
7445 END_PROFILE(Trans2_findnotifynext);
7449 case TRANSACT2_MKDIR:
7451 START_PROFILE(Trans2_mkdir);
7452 call_trans2mkdir(conn, req,
7453 &state->param, state->total_param,
7454 &state->data, state->total_data,
7455 state->max_data_return);
7456 END_PROFILE(Trans2_mkdir);
7460 case TRANSACT2_GET_DFS_REFERRAL:
7462 START_PROFILE(Trans2_get_dfs_referral);
7463 call_trans2getdfsreferral(conn, req,
7464 &state->param, state->total_param,
7465 &state->data, state->total_data,
7466 state->max_data_return);
7467 END_PROFILE(Trans2_get_dfs_referral);
7471 case TRANSACT2_IOCTL:
7473 START_PROFILE(Trans2_ioctl);
7474 call_trans2ioctl(conn, req,
7475 &state->param, state->total_param,
7476 &state->data, state->total_data,
7477 state->max_data_return);
7478 END_PROFILE(Trans2_ioctl);
7483 /* Error in request */
7484 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7485 reply_doserror(req, ERRSRV,ERRerror);
7489 /****************************************************************************
7490 Reply to a SMBtrans2.
7491 ****************************************************************************/
7493 void reply_trans2(struct smb_request *req)
7495 connection_struct *conn = req->conn;
7500 unsigned int tran_call;
7502 unsigned int av_size;
7503 struct trans_state *state;
7506 START_PROFILE(SMBtrans2);
7508 if (req->wct < 14) {
7509 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7510 END_PROFILE(SMBtrans2);
7514 dsoff = SVAL(req->inbuf, smb_dsoff);
7515 dscnt = SVAL(req->inbuf, smb_dscnt);
7516 psoff = SVAL(req->inbuf, smb_psoff);
7517 pscnt = SVAL(req->inbuf, smb_pscnt);
7518 tran_call = SVAL(req->inbuf, smb_setup0);
7519 size = smb_len(req->inbuf) + 4;
7520 av_size = smb_len(req->inbuf);
7522 result = allow_new_trans(conn->pending_trans, req->mid);
7523 if (!NT_STATUS_IS_OK(result)) {
7524 DEBUG(2, ("Got invalid trans2 request: %s\n",
7525 nt_errstr(result)));
7526 reply_nterror(req, result);
7527 END_PROFILE(SMBtrans2);
7532 switch (tran_call) {
7533 /* List the allowed trans2 calls on IPC$ */
7534 case TRANSACT2_OPEN:
7535 case TRANSACT2_GET_DFS_REFERRAL:
7536 case TRANSACT2_QFILEINFO:
7537 case TRANSACT2_QFSINFO:
7538 case TRANSACT2_SETFSINFO:
7541 reply_doserror(req, ERRSRV, ERRaccess);
7542 END_PROFILE(SMBtrans2);
7547 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7548 DEBUG(0, ("talloc failed\n"));
7549 reply_nterror(req, NT_STATUS_NO_MEMORY);
7550 END_PROFILE(SMBtrans2);
7554 state->cmd = SMBtrans2;
7556 state->mid = req->mid;
7557 state->vuid = req->vuid;
7558 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7559 state->setup = NULL;
7560 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7561 state->param = NULL;
7562 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7564 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7565 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7566 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7567 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7568 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7570 state->call = tran_call;
7572 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7573 is so as a sanity check */
7574 if (state->setup_count != 1) {
7576 * Need to have rc=0 for ioctl to get job id for OS/2.
7577 * Network printing will fail if function is not successful.
7578 * Similar function in reply.c will be used if protocol
7579 * is LANMAN1.0 instead of LM1.2X002.
7580 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7581 * outbuf doesn't have to be set(only job id is used).
7583 if ( (state->setup_count == 4)
7584 && (tran_call == TRANSACT2_IOCTL)
7585 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7586 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7587 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7589 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7590 DEBUG(2,("Transaction is %d\n",tran_call));
7592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7593 END_PROFILE(SMBtrans2);
7598 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7601 if (state->total_data) {
7602 /* Can't use talloc here, the core routines do realloc on the
7603 * params and data. */
7604 state->data = (char *)SMB_MALLOC(state->total_data);
7605 if (state->data == NULL) {
7606 DEBUG(0,("reply_trans2: data malloc fail for %u "
7607 "bytes !\n", (unsigned int)state->total_data));
7609 reply_nterror(req, NT_STATUS_NO_MEMORY);
7610 END_PROFILE(SMBtrans2);
7614 if (dscnt > state->total_data ||
7615 dsoff+dscnt < dsoff) {
7619 if (dsoff > av_size ||
7621 dsoff+dscnt > av_size) {
7625 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7628 if (state->total_param) {
7629 /* Can't use talloc here, the core routines do realloc on the
7630 * params and data. */
7631 state->param = (char *)SMB_MALLOC(state->total_param);
7632 if (state->param == NULL) {
7633 DEBUG(0,("reply_trans: param malloc fail for %u "
7634 "bytes !\n", (unsigned int)state->total_param));
7635 SAFE_FREE(state->data);
7637 reply_nterror(req, NT_STATUS_NO_MEMORY);
7638 END_PROFILE(SMBtrans2);
7642 if (pscnt > state->total_param ||
7643 psoff+pscnt < psoff) {
7647 if (psoff > av_size ||
7649 psoff+pscnt > av_size) {
7653 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7656 state->received_data = dscnt;
7657 state->received_param = pscnt;
7659 if ((state->received_param == state->total_param) &&
7660 (state->received_data == state->total_data)) {
7662 handle_trans2(conn, req, state);
7664 SAFE_FREE(state->data);
7665 SAFE_FREE(state->param);
7667 END_PROFILE(SMBtrans2);
7671 DLIST_ADD(conn->pending_trans, state);
7673 /* We need to send an interim response then receive the rest
7674 of the parameter/data bytes */
7675 reply_outbuf(req, 0, 0);
7676 show_msg((char *)req->outbuf);
7677 END_PROFILE(SMBtrans2);
7682 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7683 SAFE_FREE(state->data);
7684 SAFE_FREE(state->param);
7686 END_PROFILE(SMBtrans2);
7687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7691 /****************************************************************************
7692 Reply to a SMBtranss2
7693 ****************************************************************************/
7695 void reply_transs2(struct smb_request *req)
7697 connection_struct *conn = req->conn;
7698 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7699 struct trans_state *state;
7701 unsigned int av_size;
7703 START_PROFILE(SMBtranss2);
7705 show_msg((char *)req->inbuf);
7708 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7709 END_PROFILE(SMBtranss2);
7713 size = smb_len(req->inbuf)+4;
7714 av_size = smb_len(req->inbuf);
7716 for (state = conn->pending_trans; state != NULL;
7717 state = state->next) {
7718 if (state->mid == req->mid) {
7723 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7725 END_PROFILE(SMBtranss2);
7729 /* Revise state->total_param and state->total_data in case they have
7730 changed downwards */
7732 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7733 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7734 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7735 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7737 pcnt = SVAL(req->inbuf, smb_spscnt);
7738 poff = SVAL(req->inbuf, smb_spsoff);
7739 pdisp = SVAL(req->inbuf, smb_spsdisp);
7741 dcnt = SVAL(req->inbuf, smb_sdscnt);
7742 doff = SVAL(req->inbuf, smb_sdsoff);
7743 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7745 state->received_param += pcnt;
7746 state->received_data += dcnt;
7748 if ((state->received_data > state->total_data) ||
7749 (state->received_param > state->total_param))
7753 if (pdisp > state->total_param ||
7754 pcnt > state->total_param ||
7755 pdisp+pcnt > state->total_param ||
7756 pdisp+pcnt < pdisp) {
7760 if (poff > av_size ||
7762 poff+pcnt > av_size ||
7767 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7772 if (ddisp > state->total_data ||
7773 dcnt > state->total_data ||
7774 ddisp+dcnt > state->total_data ||
7775 ddisp+dcnt < ddisp) {
7779 if (ddisp > av_size ||
7781 ddisp+dcnt > av_size ||
7782 ddisp+dcnt < ddisp) {
7786 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7790 if ((state->received_param < state->total_param) ||
7791 (state->received_data < state->total_data)) {
7792 END_PROFILE(SMBtranss2);
7797 * construct_reply_common will copy smb_com from inbuf to
7798 * outbuf. SMBtranss2 is wrong here.
7800 SCVAL(req->inbuf,smb_com,SMBtrans2);
7802 handle_trans2(conn, req, state);
7804 DLIST_REMOVE(conn->pending_trans, state);
7805 SAFE_FREE(state->data);
7806 SAFE_FREE(state->param);
7809 END_PROFILE(SMBtranss2);
7814 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7815 DLIST_REMOVE(conn->pending_trans, state);
7816 SAFE_FREE(state->data);
7817 SAFE_FREE(state->param);
7819 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7820 END_PROFILE(SMBtranss2);