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 "
2830 "service [%s] user [%s]\n",
2831 lp_servicename(SNUM(conn)),
2832 conn->server_info->unix_name));
2833 reply_doserror(req, ERRDOS, ERRnoaccess);
2837 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2838 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2839 reply_doserror(req, ERRSRV, ERRerror);
2845 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2847 /* Unknown1 24 NULL bytes*/
2848 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2849 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2850 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2852 /* Default Soft Quota 8 bytes */
2853 SBIG_UINT(pdata,24,quotas.softlim);
2855 /* Default Hard Quota 8 bytes */
2856 SBIG_UINT(pdata,32,quotas.hardlim);
2858 /* Quota flag 2 bytes */
2859 SSVAL(pdata,40,quotas.qflags);
2861 /* Unknown3 6 NULL bytes */
2867 #endif /* HAVE_SYS_QUOTAS */
2868 case SMB_FS_OBJECTID_INFORMATION:
2870 unsigned char objid[16];
2871 struct smb_extended_info extended_info;
2872 memcpy(pdata,create_volume_objectid(conn, objid),16);
2873 samba_extended_info_version (&extended_info);
2874 SIVAL(pdata,16,extended_info.samba_magic);
2875 SIVAL(pdata,20,extended_info.samba_version);
2876 SIVAL(pdata,24,extended_info.samba_subversion);
2877 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2878 memcpy(pdata+36,extended_info.samba_version_string,28);
2884 * Query the version and capabilities of the CIFS UNIX extensions
2888 case SMB_QUERY_CIFS_UNIX_INFO:
2890 bool large_write = lp_min_receive_file_size() &&
2891 !srv_is_signing_active();
2892 bool large_read = !srv_is_signing_active();
2893 int encrypt_caps = 0;
2895 if (!lp_unix_extensions()) {
2896 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2900 switch (conn->encrypt_level) {
2906 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2909 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2910 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2911 large_write = false;
2917 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2918 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2920 /* We have POSIX ACLs, pathname, encryption,
2921 * large read/write, and locking capability. */
2923 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2924 CIFS_UNIX_POSIX_ACLS_CAP|
2925 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2926 CIFS_UNIX_FCNTL_LOCKS_CAP|
2927 CIFS_UNIX_EXTATTR_CAP|
2928 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2930 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2932 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2936 case SMB_QUERY_POSIX_FS_INFO:
2939 vfs_statvfs_struct svfs;
2941 if (!lp_unix_extensions()) {
2942 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2946 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2950 SIVAL(pdata,0,svfs.OptimalTransferSize);
2951 SIVAL(pdata,4,svfs.BlockSize);
2952 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2953 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2954 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2955 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2956 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2957 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2958 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2960 } else if (rc == EOPNOTSUPP) {
2961 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2963 #endif /* EOPNOTSUPP */
2965 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2966 reply_doserror(req, ERRSRV, ERRerror);
2972 case SMB_QUERY_POSIX_WHOAMI:
2978 if (!lp_unix_extensions()) {
2979 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2983 if (max_data_bytes < 40) {
2984 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2988 /* We ARE guest if global_sid_Builtin_Guests is
2989 * in our list of SIDs.
2991 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2992 current_user.nt_user_token)) {
2993 flags |= SMB_WHOAMI_GUEST;
2996 /* We are NOT guest if global_sid_Authenticated_Users
2997 * is in our list of SIDs.
2999 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3000 current_user.nt_user_token)) {
3001 flags &= ~SMB_WHOAMI_GUEST;
3004 /* NOTE: 8 bytes for UID/GID, irrespective of native
3005 * platform size. This matches
3006 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3008 data_len = 4 /* flags */
3015 + 4 /* pad/reserved */
3016 + (current_user.ut.ngroups * 8)
3018 + (current_user.nt_user_token->num_sids *
3022 SIVAL(pdata, 0, flags);
3023 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3024 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
3025 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
3028 if (data_len >= max_data_bytes) {
3029 /* Potential overflow, skip the GIDs and SIDs. */
3031 SIVAL(pdata, 24, 0); /* num_groups */
3032 SIVAL(pdata, 28, 0); /* num_sids */
3033 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3034 SIVAL(pdata, 36, 0); /* reserved */
3040 SIVAL(pdata, 24, current_user.ut.ngroups);
3042 current_user.nt_user_token->num_sids);
3044 /* We walk the SID list twice, but this call is fairly
3045 * infrequent, and I don't expect that it's performance
3046 * sensitive -- jpeach
3048 for (i = 0, sid_bytes = 0;
3049 i < current_user.nt_user_token->num_sids; ++i) {
3050 sid_bytes += ndr_size_dom_sid(
3051 ¤t_user.nt_user_token->user_sids[i], 0);
3054 /* SID list byte count */
3055 SIVAL(pdata, 32, sid_bytes);
3057 /* 4 bytes pad/reserved - must be zero */
3058 SIVAL(pdata, 36, 0);
3062 for (i = 0; i < current_user.ut.ngroups; ++i) {
3063 SBIG_UINT(pdata, data_len,
3064 (SMB_BIG_UINT)current_user.ut.groups[i]);
3070 i < current_user.nt_user_token->num_sids; ++i) {
3071 int sid_len = ndr_size_dom_sid(
3072 ¤t_user.nt_user_token->user_sids[i], 0);
3074 sid_linearize(pdata + data_len, sid_len,
3075 ¤t_user.nt_user_token->user_sids[i]);
3076 data_len += sid_len;
3082 case SMB_MAC_QUERY_FS_INFO:
3084 * Thursby MAC extension... ONLY on NTFS filesystems
3085 * once we do streams then we don't need this
3087 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3089 SIVAL(pdata,84,0x100); /* Don't support mac... */
3094 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3099 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3102 DEBUG( 4, ( "%s info_level = %d\n",
3103 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3108 /****************************************************************************
3109 Reply to a TRANS2_SETFSINFO (set filesystem info).
3110 ****************************************************************************/
3112 static void call_trans2setfsinfo(connection_struct *conn,
3113 struct smb_request *req,
3114 char **pparams, int total_params,
3115 char **ppdata, int total_data,
3116 unsigned int max_data_bytes)
3118 char *pdata = *ppdata;
3119 char *params = *pparams;
3122 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3125 if (total_params < 4) {
3126 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3132 info_level = SVAL(params,2);
3135 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3136 info_level != SMB_SET_CIFS_UNIX_INFO) {
3137 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3138 "info level (0x%x) on IPC$.\n",
3139 (unsigned int)info_level));
3140 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3145 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3146 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3147 DEBUG(0,("call_trans2setfsinfo: encryption required "
3148 "and info level 0x%x sent.\n",
3149 (unsigned int)info_level));
3150 exit_server_cleanly("encryption required "
3156 switch(info_level) {
3157 case SMB_SET_CIFS_UNIX_INFO:
3159 uint16 client_unix_major;
3160 uint16 client_unix_minor;
3161 uint32 client_unix_cap_low;
3162 uint32 client_unix_cap_high;
3164 if (!lp_unix_extensions()) {
3166 NT_STATUS_INVALID_LEVEL);
3170 /* There should be 12 bytes of capabilities set. */
3171 if (total_data < 8) {
3174 NT_STATUS_INVALID_PARAMETER);
3177 client_unix_major = SVAL(pdata,0);
3178 client_unix_minor = SVAL(pdata,2);
3179 client_unix_cap_low = IVAL(pdata,4);
3180 client_unix_cap_high = IVAL(pdata,8);
3181 /* Just print these values for now. */
3182 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3183 cap_low = 0x%x, cap_high = 0x%x\n",
3184 (unsigned int)client_unix_major,
3185 (unsigned int)client_unix_minor,
3186 (unsigned int)client_unix_cap_low,
3187 (unsigned int)client_unix_cap_high ));
3189 /* Here is where we must switch to posix pathname processing... */
3190 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3191 lp_set_posix_pathnames();
3192 mangle_change_to_posix();
3195 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3196 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3197 /* Client that knows how to do posix locks,
3198 * but not posix open/mkdir operations. Set a
3199 * default type for read/write checks. */
3201 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3207 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3210 size_t param_len = 0;
3211 size_t data_len = total_data;
3213 if (!lp_unix_extensions()) {
3216 NT_STATUS_INVALID_LEVEL);
3220 if (lp_smb_encrypt(SNUM(conn)) == false) {
3223 NT_STATUS_NOT_SUPPORTED);
3227 DEBUG( 4,("call_trans2setfsinfo: "
3228 "request transport encryption.\n"));
3230 status = srv_request_encryption_setup(conn,
3231 (unsigned char **)ppdata,
3233 (unsigned char **)pparams,
3236 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3237 !NT_STATUS_IS_OK(status)) {
3238 reply_nterror(req, status);
3242 send_trans2_replies(conn, req,
3249 if (NT_STATUS_IS_OK(status)) {
3250 /* Server-side transport
3251 * encryption is now *on*. */
3252 status = srv_encryption_start(conn);
3253 if (!NT_STATUS_IS_OK(status)) {
3254 exit_server_cleanly(
3255 "Failure in setting "
3256 "up encrypted transport");
3262 case SMB_FS_QUOTA_INFORMATION:
3264 files_struct *fsp = NULL;
3265 SMB_NTQUOTA_STRUCT quotas;
3267 ZERO_STRUCT(quotas);
3270 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3271 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3272 lp_servicename(SNUM(conn)),
3273 conn->server_info->unix_name));
3274 reply_doserror(req, ERRSRV, ERRaccess);
3278 /* note: normaly there're 48 bytes,
3279 * but we didn't use the last 6 bytes for now
3282 fsp = file_fsp(SVAL(params,0));
3283 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3284 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3286 req, NT_STATUS_INVALID_HANDLE);
3290 if (total_data < 42) {
3291 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3295 NT_STATUS_INVALID_PARAMETER);
3299 /* unknown_1 24 NULL bytes in pdata*/
3301 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3302 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3303 #ifdef LARGE_SMB_OFF_T
3304 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3305 #else /* LARGE_SMB_OFF_T */
3306 if ((IVAL(pdata,28) != 0)&&
3307 ((quotas.softlim != 0xFFFFFFFF)||
3308 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3309 /* more than 32 bits? */
3312 NT_STATUS_INVALID_PARAMETER);
3315 #endif /* LARGE_SMB_OFF_T */
3317 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3318 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3319 #ifdef LARGE_SMB_OFF_T
3320 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3321 #else /* LARGE_SMB_OFF_T */
3322 if ((IVAL(pdata,36) != 0)&&
3323 ((quotas.hardlim != 0xFFFFFFFF)||
3324 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3325 /* more than 32 bits? */
3328 NT_STATUS_INVALID_PARAMETER);
3331 #endif /* LARGE_SMB_OFF_T */
3333 /* quota_flags 2 bytes **/
3334 quotas.qflags = SVAL(pdata,40);
3336 /* unknown_2 6 NULL bytes follow*/
3338 /* now set the quotas */
3339 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3340 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3341 reply_doserror(req, ERRSRV, ERRerror);
3348 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3350 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3356 * sending this reply works fine,
3357 * but I'm not sure it's the same
3358 * like windows do...
3361 reply_outbuf(req, 10, 0);
3364 #if defined(HAVE_POSIX_ACLS)
3365 /****************************************************************************
3366 Utility function to count the number of entries in a POSIX acl.
3367 ****************************************************************************/
3369 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3371 unsigned int ace_count = 0;
3372 int entry_id = SMB_ACL_FIRST_ENTRY;
3373 SMB_ACL_ENTRY_T entry;
3375 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3377 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3378 entry_id = SMB_ACL_NEXT_ENTRY;
3385 /****************************************************************************
3386 Utility function to marshall a POSIX acl into wire format.
3387 ****************************************************************************/
3389 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3391 int entry_id = SMB_ACL_FIRST_ENTRY;
3392 SMB_ACL_ENTRY_T entry;
3394 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3395 SMB_ACL_TAG_T tagtype;
3396 SMB_ACL_PERMSET_T permset;
3397 unsigned char perms = 0;
3398 unsigned int own_grp;
3401 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3402 entry_id = SMB_ACL_NEXT_ENTRY;
3405 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3406 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3410 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3411 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3415 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3416 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3417 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3419 SCVAL(pdata,1,perms);
3422 case SMB_ACL_USER_OBJ:
3423 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3424 own_grp = (unsigned int)pst->st_uid;
3425 SIVAL(pdata,2,own_grp);
3430 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3432 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3435 own_grp = (unsigned int)*puid;
3436 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3437 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3438 SIVAL(pdata,2,own_grp);
3442 case SMB_ACL_GROUP_OBJ:
3443 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3444 own_grp = (unsigned int)pst->st_gid;
3445 SIVAL(pdata,2,own_grp);
3450 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3452 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3455 own_grp = (unsigned int)*pgid;
3456 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3457 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3458 SIVAL(pdata,2,own_grp);
3463 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3464 SIVAL(pdata,2,0xFFFFFFFF);
3465 SIVAL(pdata,6,0xFFFFFFFF);
3468 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3469 SIVAL(pdata,2,0xFFFFFFFF);
3470 SIVAL(pdata,6,0xFFFFFFFF);
3473 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3476 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3483 /****************************************************************************
3484 Store the FILE_UNIX_BASIC info.
3485 ****************************************************************************/
3487 static char *store_file_unix_basic(connection_struct *conn,
3490 const SMB_STRUCT_STAT *psbuf)
3492 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3493 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3495 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3498 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3501 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3502 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3503 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3506 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3510 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3514 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3517 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3521 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3525 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3528 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3532 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3539 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3540 * the chflags(2) (or equivalent) flags.
3542 * XXX: this really should be behind the VFS interface. To do this, we would
3543 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3544 * Each VFS module could then implement its own mapping as appropriate for the
3545 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3547 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3551 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3555 { UF_IMMUTABLE, EXT_IMMUTABLE },
3559 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3563 { UF_HIDDEN, EXT_HIDDEN },
3566 /* Do not remove. We need to guarantee that this array has at least one
3567 * entry to build on HP-UX.
3573 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3574 uint32 *smb_fflags, uint32 *smb_fmask)
3576 #ifdef HAVE_STAT_ST_FLAGS
3579 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3580 *smb_fmask |= info2_flags_map[i].smb_fflag;
3581 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3582 *smb_fflags |= info2_flags_map[i].smb_fflag;
3585 #endif /* HAVE_STAT_ST_FLAGS */
3588 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3589 const uint32 smb_fflags,
3590 const uint32 smb_fmask,
3593 #ifdef HAVE_STAT_ST_FLAGS
3594 uint32 max_fmask = 0;
3597 *stat_fflags = psbuf->st_flags;
3599 /* For each flags requested in smb_fmask, check the state of the
3600 * corresponding flag in smb_fflags and set or clear the matching
3604 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3605 max_fmask |= info2_flags_map[i].smb_fflag;
3606 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3607 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3608 *stat_fflags |= info2_flags_map[i].stat_fflag;
3610 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3615 /* If smb_fmask is asking to set any bits that are not supported by
3616 * our flag mappings, we should fail.
3618 if ((smb_fmask & max_fmask) != smb_fmask) {
3625 #endif /* HAVE_STAT_ST_FLAGS */
3629 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3630 * of file flags and birth (create) time.
3632 static char *store_file_unix_basic_info2(connection_struct *conn,
3635 const SMB_STRUCT_STAT *psbuf)
3637 uint32 file_flags = 0;
3638 uint32 flags_mask = 0;
3640 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3642 /* Create (birth) time 64 bit */
3643 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3646 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3647 SIVAL(pdata, 0, file_flags); /* flags */
3648 SIVAL(pdata, 4, flags_mask); /* mask */
3654 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3655 const struct stream_struct *streams,
3657 unsigned int max_data_bytes,
3658 unsigned int *data_size)
3661 unsigned int ofs = 0;
3663 for (i=0; i<num_streams; i++) {
3664 unsigned int next_offset;
3666 smb_ucs2_t *namebuf;
3668 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3671 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3672 return NT_STATUS_INVALID_PARAMETER;
3676 * name_buf is now null-terminated, we need to marshall as not
3682 if (ofs + 24 + namelen > max_data_bytes) {
3683 TALLOC_FREE(namebuf);
3684 return NT_STATUS_BUFFER_TOO_SMALL;
3687 SIVAL(data, ofs+4, namelen);
3688 SOFF_T(data, ofs+8, streams[i].size);
3689 SOFF_T(data, ofs+16, streams[i].alloc_size);
3690 memcpy(data+ofs+24, namebuf, namelen);
3691 TALLOC_FREE(namebuf);
3693 next_offset = ofs + 24 + namelen;
3695 if (i == num_streams-1) {
3696 SIVAL(data, ofs, 0);
3699 unsigned int align = ndr_align_size(next_offset, 8);
3701 if (next_offset + align > max_data_bytes) {
3702 return NT_STATUS_BUFFER_TOO_SMALL;
3705 memset(data+next_offset, 0, align);
3706 next_offset += align;
3708 SIVAL(data, ofs, next_offset - ofs);
3717 return NT_STATUS_OK;
3720 /****************************************************************************
3721 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3722 ****************************************************************************/
3724 static void call_trans2qpipeinfo(connection_struct *conn,
3725 struct smb_request *req,
3726 unsigned int tran_call,
3727 char **pparams, int total_params,
3728 char **ppdata, int total_data,
3729 unsigned int max_data_bytes)
3731 char *params = *pparams;
3732 char *pdata = *ppdata;
3733 unsigned int data_size = 0;
3734 unsigned int param_size = 2;
3736 smb_np_struct *p_pipe = NULL;
3739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3743 if (total_params < 4) {
3744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3748 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3749 if (p_pipe == NULL) {
3750 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3754 info_level = SVAL(params,2);
3756 *pparams = (char *)SMB_REALLOC(*pparams,2);
3757 if (*pparams == NULL) {
3758 reply_nterror(req, NT_STATUS_NO_MEMORY);
3763 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3764 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3765 if (*ppdata == NULL ) {
3766 reply_nterror(req, NT_STATUS_NO_MEMORY);
3771 switch (info_level) {
3772 case SMB_FILE_STANDARD_INFORMATION:
3774 SOFF_T(pdata,0,4096LL);
3781 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3785 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3791 /****************************************************************************
3792 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3793 file name or file id).
3794 ****************************************************************************/
3796 static void call_trans2qfilepathinfo(connection_struct *conn,
3797 struct smb_request *req,
3798 unsigned int tran_call,
3799 char **pparams, int total_params,
3800 char **ppdata, int total_data,
3801 unsigned int max_data_bytes)
3803 char *params = *pparams;
3804 char *pdata = *ppdata;
3805 char *dstart, *dend;
3809 SMB_OFF_T file_size=0;
3810 SMB_BIG_UINT allocation_size=0;
3811 unsigned int data_size = 0;
3812 unsigned int param_size = 2;
3813 SMB_STRUCT_STAT sbuf;
3814 char *dos_fname = NULL;
3820 bool delete_pending = False;
3822 time_t create_time, mtime, atime;
3823 struct timespec create_time_ts, mtime_ts, atime_ts;
3824 struct timespec write_time_ts;
3825 files_struct *fsp = NULL;
3826 struct file_id fileid;
3827 struct ea_list *ea_list = NULL;
3828 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3829 char *lock_data = NULL;
3830 bool ms_dfs_link = false;
3831 TALLOC_CTX *ctx = talloc_tos();
3834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3839 ZERO_STRUCT(write_time_ts);
3841 if (tran_call == TRANSACT2_QFILEINFO) {
3842 if (total_params < 4) {
3843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3848 call_trans2qpipeinfo(conn, req, tran_call,
3849 pparams, total_params,
3855 fsp = file_fsp(SVAL(params,0));
3856 info_level = SVAL(params,2);
3858 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3860 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3861 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3865 /* Initial check for valid fsp ptr. */
3866 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3870 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3872 reply_nterror(req, NT_STATUS_NO_MEMORY);
3876 if(fsp->fake_file_handle) {
3878 * This is actually for the QUOTA_FAKE_FILE --metze
3881 /* We know this name is ok, it's already passed the checks. */
3883 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3885 * This is actually a QFILEINFO on a directory
3886 * handle (returned from an NT SMB). NT5.0 seems
3887 * to do this call. JRA.
3890 if (INFO_LEVEL_IS_UNIX(info_level)) {
3891 /* Always do lstat for UNIX calls. */
3892 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3893 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3894 reply_unixerror(req,ERRDOS,ERRbadpath);
3897 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3898 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3899 reply_unixerror(req, ERRDOS, ERRbadpath);
3903 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3904 get_file_infos(fileid, &delete_pending, &write_time_ts);
3907 * Original code - this is an open file.
3909 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3913 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3914 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3915 reply_unixerror(req, ERRDOS, ERRbadfid);
3918 pos = fsp->fh->position_information;
3919 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3920 get_file_infos(fileid, &delete_pending, &write_time_ts);
3921 access_mask = fsp->access_mask;
3925 NTSTATUS status = NT_STATUS_OK;
3928 if (total_params < 7) {
3929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3933 info_level = SVAL(params,0);
3935 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3937 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3938 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3942 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3944 STR_TERMINATE, &status);
3945 if (!NT_STATUS_IS_OK(status)) {
3946 reply_nterror(req, status);
3950 status = resolve_dfspath(ctx,
3952 req->flags2 & FLAGS2_DFS_PATHNAMES,
3955 if (!NT_STATUS_IS_OK(status)) {
3956 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3957 reply_botherror(req,
3958 NT_STATUS_PATH_NOT_COVERED,
3959 ERRSRV, ERRbadpath);
3961 reply_nterror(req, status);
3965 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 reply_nterror(req, status);
3970 status = check_name(conn, fname);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3973 reply_nterror(req, status);
3977 if (INFO_LEVEL_IS_UNIX(info_level)) {
3978 /* Always do lstat for UNIX calls. */
3979 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3980 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3981 reply_unixerror(req, ERRDOS, ERRbadpath);
3985 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3986 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
3989 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3990 reply_unixerror(req, ERRDOS, ERRbadpath);
3995 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3996 get_file_infos(fileid, &delete_pending, &write_time_ts);
3997 if (delete_pending) {
3998 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4003 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4004 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4008 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4009 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4011 p = strrchr_m(fname,'/');
4018 mode = dos_mode_msdfs(conn,fname,&sbuf);
4020 mode = dos_mode(conn,fname,&sbuf);
4023 mode = FILE_ATTRIBUTE_NORMAL;
4025 nlink = sbuf.st_nlink;
4027 if (nlink && (mode&aDIR)) {
4031 if ((nlink > 0) && delete_pending) {
4035 fullpathname = fname;
4037 file_size = get_file_size(sbuf);
4039 /* Pull out any data sent here before we realloc. */
4040 switch (info_level) {
4041 case SMB_INFO_QUERY_EAS_FROM_LIST:
4043 /* Pull any EA list from the data portion. */
4046 if (total_data < 4) {
4048 req, NT_STATUS_INVALID_PARAMETER);
4051 ea_size = IVAL(pdata,0);
4053 if (total_data > 0 && ea_size != total_data) {
4054 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4055 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4057 req, NT_STATUS_INVALID_PARAMETER);
4061 if (!lp_ea_support(SNUM(conn))) {
4062 reply_doserror(req, ERRDOS,
4063 ERReasnotsupported);
4067 /* Pull out the list of names. */
4068 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4071 req, NT_STATUS_INVALID_PARAMETER);
4077 case SMB_QUERY_POSIX_LOCK:
4079 if (fsp == NULL || fsp->fh->fd == -1) {
4080 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4084 if (total_data != POSIX_LOCK_DATA_SIZE) {
4086 req, NT_STATUS_INVALID_PARAMETER);
4090 /* Copy the lock range data. */
4091 lock_data = (char *)TALLOC_MEMDUP(
4092 ctx, pdata, total_data);
4094 reply_nterror(req, NT_STATUS_NO_MEMORY);
4102 *pparams = (char *)SMB_REALLOC(*pparams,2);
4103 if (*pparams == NULL) {
4104 reply_nterror(req, NT_STATUS_NO_MEMORY);
4109 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4110 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4111 if (*ppdata == NULL ) {
4112 reply_nterror(req, NT_STATUS_NO_MEMORY);
4117 dend = dstart + data_size - 1;
4119 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4120 mtime_ts = get_mtimespec(&sbuf);
4121 atime_ts = get_atimespec(&sbuf);
4123 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4126 /* Do we have this path open ? */
4128 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4129 fsp1 = file_find_di_first(fileid);
4130 if (fsp1 && fsp1->initial_allocation_size) {
4131 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4135 if (!null_timespec(write_time_ts)) {
4136 mtime_ts = write_time_ts;
4139 if (lp_dos_filetime_resolution(SNUM(conn))) {
4140 dos_filetime_timespec(&create_time_ts);
4141 dos_filetime_timespec(&mtime_ts);
4142 dos_filetime_timespec(&atime_ts);
4145 create_time = convert_timespec_to_time_t(create_time_ts);
4146 mtime = convert_timespec_to_time_t(mtime_ts);
4147 atime = convert_timespec_to_time_t(atime_ts);
4149 /* NT expects the name to be in an exact form of the *full*
4150 filename. See the trans2 torture test */
4151 if (ISDOT(base_name)) {
4152 dos_fname = talloc_strdup(ctx, "\\");
4154 reply_nterror(req, NT_STATUS_NO_MEMORY);
4158 dos_fname = talloc_asprintf(ctx,
4162 reply_nterror(req, NT_STATUS_NO_MEMORY);
4165 string_replace(dos_fname, '/', '\\');
4168 switch (info_level) {
4169 case SMB_INFO_STANDARD:
4170 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4172 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4173 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4174 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4175 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4176 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4177 SSVAL(pdata,l1_attrFile,mode);
4180 case SMB_INFO_QUERY_EA_SIZE:
4182 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4183 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4185 srv_put_dos_date2(pdata,0,create_time);
4186 srv_put_dos_date2(pdata,4,atime);
4187 srv_put_dos_date2(pdata,8,mtime); /* write time */
4188 SIVAL(pdata,12,(uint32)file_size);
4189 SIVAL(pdata,16,(uint32)allocation_size);
4190 SSVAL(pdata,20,mode);
4191 SIVAL(pdata,22,ea_size);
4195 case SMB_INFO_IS_NAME_VALID:
4196 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4197 if (tran_call == TRANSACT2_QFILEINFO) {
4198 /* os/2 needs this ? really ?*/
4199 reply_doserror(req, ERRDOS, ERRbadfunc);
4206 case SMB_INFO_QUERY_EAS_FROM_LIST:
4208 size_t total_ea_len = 0;
4209 struct ea_list *ea_file_list = NULL;
4211 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4213 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4214 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4216 if (!ea_list || (total_ea_len > data_size)) {
4218 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4222 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4226 case SMB_INFO_QUERY_ALL_EAS:
4228 /* We have data_size bytes to put EA's into. */
4229 size_t total_ea_len = 0;
4231 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4233 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4234 if (!ea_list || (total_ea_len > data_size)) {
4236 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4240 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4244 case SMB_FILE_BASIC_INFORMATION:
4245 case SMB_QUERY_FILE_BASIC_INFO:
4247 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4248 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4249 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4251 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4255 put_long_date_timespec(pdata,create_time_ts);
4256 put_long_date_timespec(pdata+8,atime_ts);
4257 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4258 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4259 SIVAL(pdata,32,mode);
4261 DEBUG(5,("SMB_QFBI - "));
4262 DEBUG(5,("create: %s ", ctime(&create_time)));
4263 DEBUG(5,("access: %s ", ctime(&atime)));
4264 DEBUG(5,("write: %s ", ctime(&mtime)));
4265 DEBUG(5,("change: %s ", ctime(&mtime)));
4266 DEBUG(5,("mode: %x\n", mode));
4269 case SMB_FILE_STANDARD_INFORMATION:
4270 case SMB_QUERY_FILE_STANDARD_INFO:
4272 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4274 SOFF_T(pdata,0,allocation_size);
4275 SOFF_T(pdata,8,file_size);
4276 SIVAL(pdata,16,nlink);
4277 SCVAL(pdata,20,delete_pending?1:0);
4278 SCVAL(pdata,21,(mode&aDIR)?1:0);
4279 SSVAL(pdata,22,0); /* Padding. */
4282 case SMB_FILE_EA_INFORMATION:
4283 case SMB_QUERY_FILE_EA_INFO:
4285 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4286 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4288 SIVAL(pdata,0,ea_size);
4292 /* Get the 8.3 name - used if NT SMB was negotiated. */
4293 case SMB_QUERY_FILE_ALT_NAME_INFO:
4294 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4296 char mangled_name[13];
4297 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4298 if (!name_to_8_3(base_name,mangled_name,
4299 True,conn->params)) {
4302 NT_STATUS_NO_MEMORY);
4304 len = srvstr_push(dstart, req->flags2,
4305 pdata+4, mangled_name,
4306 PTR_DIFF(dend, pdata+4),
4308 data_size = 4 + len;
4313 case SMB_QUERY_FILE_NAME_INFO:
4315 this must be *exactly* right for ACLs on mapped drives to work
4317 len = srvstr_push(dstart, req->flags2,
4319 PTR_DIFF(dend, pdata+4),
4321 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4322 data_size = 4 + len;
4326 case SMB_FILE_ALLOCATION_INFORMATION:
4327 case SMB_QUERY_FILE_ALLOCATION_INFO:
4328 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4330 SOFF_T(pdata,0,allocation_size);
4333 case SMB_FILE_END_OF_FILE_INFORMATION:
4334 case SMB_QUERY_FILE_END_OF_FILEINFO:
4335 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4337 SOFF_T(pdata,0,file_size);
4340 case SMB_QUERY_FILE_ALL_INFO:
4341 case SMB_FILE_ALL_INFORMATION:
4343 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4344 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4345 put_long_date_timespec(pdata,create_time_ts);
4346 put_long_date_timespec(pdata+8,atime_ts);
4347 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4348 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4349 SIVAL(pdata,32,mode);
4350 SIVAL(pdata,36,0); /* padding. */
4352 SOFF_T(pdata,0,allocation_size);
4353 SOFF_T(pdata,8,file_size);
4354 SIVAL(pdata,16,nlink);
4355 SCVAL(pdata,20,delete_pending);
4356 SCVAL(pdata,21,(mode&aDIR)?1:0);
4359 SIVAL(pdata,0,ea_size);
4360 pdata += 4; /* EA info */
4361 len = srvstr_push(dstart, req->flags2,
4363 PTR_DIFF(dend, pdata+4),
4367 data_size = PTR_DIFF(pdata,(*ppdata));
4370 case SMB_FILE_INTERNAL_INFORMATION:
4371 /* This should be an index number - looks like
4374 I think this causes us to fail the IFSKIT
4375 BasicFileInformationTest. -tpot */
4377 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4378 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4379 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4383 case SMB_FILE_ACCESS_INFORMATION:
4384 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4385 SIVAL(pdata,0,access_mask);
4389 case SMB_FILE_NAME_INFORMATION:
4390 /* Pathname with leading '\'. */
4393 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4394 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4395 SIVAL(pdata,0,byte_len);
4396 data_size = 4 + byte_len;
4400 case SMB_FILE_DISPOSITION_INFORMATION:
4401 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4403 SCVAL(pdata,0,delete_pending);
4406 case SMB_FILE_POSITION_INFORMATION:
4407 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4409 SOFF_T(pdata,0,pos);
4412 case SMB_FILE_MODE_INFORMATION:
4413 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4414 SIVAL(pdata,0,mode);
4418 case SMB_FILE_ALIGNMENT_INFORMATION:
4419 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4420 SIVAL(pdata,0,0); /* No alignment needed. */
4425 * NT4 server just returns "invalid query" to this - if we try
4426 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4429 /* The first statement above is false - verified using Thursby
4430 * client against NT4 -- gcolley.
4432 case SMB_QUERY_FILE_STREAM_INFO:
4433 case SMB_FILE_STREAM_INFORMATION: {
4434 unsigned int num_streams;
4435 struct stream_struct *streams;
4438 DEBUG(10,("call_trans2qfilepathinfo: "
4439 "SMB_FILE_STREAM_INFORMATION\n"));
4441 status = SMB_VFS_STREAMINFO(
4442 conn, fsp, fname, talloc_tos(),
4443 &num_streams, &streams);
4445 if (!NT_STATUS_IS_OK(status)) {
4446 DEBUG(10, ("could not get stream info: %s\n",
4447 nt_errstr(status)));
4448 reply_nterror(req, status);
4452 status = marshall_stream_info(num_streams, streams,
4453 pdata, max_data_bytes,
4456 if (!NT_STATUS_IS_OK(status)) {
4457 DEBUG(10, ("marshall_stream_info failed: %s\n",
4458 nt_errstr(status)));
4459 reply_nterror(req, status);
4463 TALLOC_FREE(streams);
4467 case SMB_QUERY_COMPRESSION_INFO:
4468 case SMB_FILE_COMPRESSION_INFORMATION:
4469 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4470 SOFF_T(pdata,0,file_size);
4471 SIVAL(pdata,8,0); /* ??? */
4472 SIVAL(pdata,12,0); /* ??? */
4476 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4477 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4478 put_long_date_timespec(pdata,create_time_ts);
4479 put_long_date_timespec(pdata+8,atime_ts);
4480 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4481 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4482 SOFF_T(pdata,32,allocation_size);
4483 SOFF_T(pdata,40,file_size);
4484 SIVAL(pdata,48,mode);
4485 SIVAL(pdata,52,0); /* ??? */
4489 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4490 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4491 SIVAL(pdata,0,mode);
4497 * CIFS UNIX Extensions.
4500 case SMB_QUERY_FILE_UNIX_BASIC:
4502 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4503 data_size = PTR_DIFF(pdata,(*ppdata));
4507 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4509 for (i=0; i<100; i++)
4510 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4516 case SMB_QUERY_FILE_UNIX_INFO2:
4518 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4519 data_size = PTR_DIFF(pdata,(*ppdata));
4523 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4525 for (i=0; i<100; i++)
4526 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4532 case SMB_QUERY_FILE_UNIX_LINK:
4534 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4537 reply_nterror(req, NT_STATUS_NO_MEMORY);
4541 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4543 if(!S_ISLNK(sbuf.st_mode)) {
4544 reply_unixerror(req, ERRSRV,
4549 reply_unixerror(req, ERRDOS, ERRbadlink);
4552 len = SMB_VFS_READLINK(conn,fullpathname,
4555 reply_unixerror(req, ERRDOS,
4560 len = srvstr_push(dstart, req->flags2,
4562 PTR_DIFF(dend, pdata),
4565 data_size = PTR_DIFF(pdata,(*ppdata));
4570 #if defined(HAVE_POSIX_ACLS)
4571 case SMB_QUERY_POSIX_ACL:
4573 SMB_ACL_T file_acl = NULL;
4574 SMB_ACL_T def_acl = NULL;
4575 uint16 num_file_acls = 0;
4576 uint16 num_def_acls = 0;
4578 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4579 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4581 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4584 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4585 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4589 NT_STATUS_NOT_IMPLEMENTED);
4593 if (S_ISDIR(sbuf.st_mode)) {
4594 if (fsp && fsp->is_directory) {
4595 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4597 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4599 def_acl = free_empty_sys_acl(conn, def_acl);
4602 num_file_acls = count_acl_entries(conn, file_acl);
4603 num_def_acls = count_acl_entries(conn, def_acl);
4605 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4606 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4608 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4609 SMB_POSIX_ACL_HEADER_SIZE) ));
4611 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4614 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4618 NT_STATUS_BUFFER_TOO_SMALL);
4622 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4623 SSVAL(pdata,2,num_file_acls);
4624 SSVAL(pdata,4,num_def_acls);
4625 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4627 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4630 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4633 req, NT_STATUS_INTERNAL_ERROR);
4636 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4638 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4641 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4645 NT_STATUS_INTERNAL_ERROR);
4650 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4653 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4655 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4661 case SMB_QUERY_POSIX_LOCK:
4663 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4665 SMB_BIG_UINT offset;
4667 enum brl_type lock_type;
4669 if (total_data != POSIX_LOCK_DATA_SIZE) {
4671 req, NT_STATUS_INVALID_PARAMETER);
4675 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4676 case POSIX_LOCK_TYPE_READ:
4677 lock_type = READ_LOCK;
4679 case POSIX_LOCK_TYPE_WRITE:
4680 lock_type = WRITE_LOCK;
4682 case POSIX_LOCK_TYPE_UNLOCK:
4684 /* There's no point in asking for an unlock... */
4687 NT_STATUS_INVALID_PARAMETER);
4691 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4692 #if defined(HAVE_LONGLONG)
4693 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4694 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4695 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4696 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4697 #else /* HAVE_LONGLONG */
4698 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4699 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4700 #endif /* HAVE_LONGLONG */
4702 status = query_lock(fsp,
4709 if (ERROR_WAS_LOCK_DENIED(status)) {
4710 /* Here we need to report who has it locked... */
4711 data_size = POSIX_LOCK_DATA_SIZE;
4713 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4714 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4715 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4716 #if defined(HAVE_LONGLONG)
4717 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4718 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4719 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4720 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4721 #else /* HAVE_LONGLONG */
4722 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4723 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4724 #endif /* HAVE_LONGLONG */
4726 } else if (NT_STATUS_IS_OK(status)) {
4727 /* For success we just return a copy of what we sent
4728 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4729 data_size = POSIX_LOCK_DATA_SIZE;
4730 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4731 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4733 reply_nterror(req, status);
4740 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4744 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4750 /****************************************************************************
4751 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4753 ****************************************************************************/
4755 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4756 connection_struct *conn,
4757 const char *oldname_in,
4758 const char *newname_in)
4760 SMB_STRUCT_STAT sbuf1, sbuf2;
4761 char *last_component_oldname = NULL;
4762 char *last_component_newname = NULL;
4763 char *oldname = NULL;
4764 char *newname = NULL;
4765 NTSTATUS status = NT_STATUS_OK;
4770 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4771 &last_component_oldname, &sbuf1);
4772 if (!NT_STATUS_IS_OK(status)) {
4776 status = check_name(conn, oldname);
4777 if (!NT_STATUS_IS_OK(status)) {
4781 /* source must already exist. */
4782 if (!VALID_STAT(sbuf1)) {
4783 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4786 status = unix_convert(ctx, conn, newname_in, False, &newname,
4787 &last_component_newname, &sbuf2);
4788 if (!NT_STATUS_IS_OK(status)) {
4792 status = check_name(conn, newname);
4793 if (!NT_STATUS_IS_OK(status)) {
4797 /* Disallow if newname already exists. */
4798 if (VALID_STAT(sbuf2)) {
4799 return NT_STATUS_OBJECT_NAME_COLLISION;
4802 /* No links from a directory. */
4803 if (S_ISDIR(sbuf1.st_mode)) {
4804 return NT_STATUS_FILE_IS_A_DIRECTORY;
4807 /* Ensure this is within the share. */
4808 status = check_reduced_name(conn, oldname);
4809 if (!NT_STATUS_IS_OK(status)) {
4813 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4815 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4816 status = map_nt_error_from_unix(errno);
4817 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4818 nt_errstr(status), newname, oldname));
4824 /****************************************************************************
4825 Deal with setting the time from any of the setfilepathinfo functions.
4826 ****************************************************************************/
4828 NTSTATUS smb_set_file_time(connection_struct *conn,
4831 const SMB_STRUCT_STAT *psbuf,
4832 struct timespec ts[2],
4833 bool setting_write_time)
4836 FILE_NOTIFY_CHANGE_LAST_ACCESS
4837 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4839 if (!VALID_STAT(*psbuf)) {
4840 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4843 /* get some defaults (no modifications) if any info is zero or -1. */
4844 if (null_timespec(ts[0])) {
4845 ts[0] = get_atimespec(psbuf);
4846 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4849 if (null_timespec(ts[1])) {
4850 ts[1] = get_mtimespec(psbuf);
4851 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4854 if (!setting_write_time) {
4855 /* ts[1] comes from change time, not write time. */
4856 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4859 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4860 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4863 * Try and set the times of this file if
4864 * they are different from the current values.
4868 struct timespec mts = get_mtimespec(psbuf);
4869 struct timespec ats = get_atimespec(psbuf);
4870 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4871 return NT_STATUS_OK;
4875 if (setting_write_time) {
4877 * This was a setfileinfo on an open file.
4878 * NT does this a lot. We also need to
4879 * set the time here, as it can be read by
4880 * FindFirst/FindNext and with the patch for bug #2045
4881 * in smbd/fileio.c it ensures that this timestamp is
4882 * kept sticky even after a write. We save the request
4883 * away and will set it on file close and after a write. JRA.
4886 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4887 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4890 set_write_time_fsp(fsp, ts[1], true);
4892 set_write_time_path(conn, fname,
4893 vfs_file_id_from_sbuf(conn, psbuf),
4898 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4900 if(file_ntimes(conn, fname, ts)!=0) {
4901 return map_nt_error_from_unix(errno);
4903 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4905 return NT_STATUS_OK;
4908 /****************************************************************************
4909 Deal with setting the dosmode from any of the setfilepathinfo functions.
4910 ****************************************************************************/
4912 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4914 SMB_STRUCT_STAT *psbuf,
4917 if (!VALID_STAT(*psbuf)) {
4918 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4922 if (S_ISDIR(psbuf->st_mode)) {
4929 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4931 /* check the mode isn't different, before changing it */
4932 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4934 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4935 fname, (unsigned int)dosmode ));
4937 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4938 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4939 fname, strerror(errno)));
4940 return map_nt_error_from_unix(errno);
4943 return NT_STATUS_OK;
4946 /****************************************************************************
4947 Deal with setting the size from any of the setfilepathinfo functions.
4948 ****************************************************************************/
4950 static NTSTATUS smb_set_file_size(connection_struct *conn,
4951 struct smb_request *req,
4954 SMB_STRUCT_STAT *psbuf,
4957 NTSTATUS status = NT_STATUS_OK;
4958 files_struct *new_fsp = NULL;
4960 if (!VALID_STAT(*psbuf)) {
4961 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4964 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4966 if (size == get_file_size(*psbuf)) {
4967 return NT_STATUS_OK;
4970 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4971 fname, (double)size ));
4973 if (fsp && fsp->fh->fd != -1) {
4974 /* Handle based call. */
4975 if (vfs_set_filelen(fsp, size) == -1) {
4976 return map_nt_error_from_unix(errno);
4978 return NT_STATUS_OK;
4981 status = open_file_ntcreate(conn, req, fname, psbuf,
4982 FILE_WRITE_ATTRIBUTES,
4983 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4986 FILE_ATTRIBUTE_NORMAL,
4987 FORCE_OPLOCK_BREAK_TO_NONE,
4990 if (!NT_STATUS_IS_OK(status)) {
4991 /* NB. We check for open_was_deferred in the caller. */
4995 if (vfs_set_filelen(new_fsp, size) == -1) {
4996 status = map_nt_error_from_unix(errno);
4997 close_file(new_fsp,NORMAL_CLOSE);
5001 close_file(new_fsp,NORMAL_CLOSE);
5002 return NT_STATUS_OK;
5005 /****************************************************************************
5006 Deal with SMB_INFO_SET_EA.
5007 ****************************************************************************/
5009 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5015 struct ea_list *ea_list = NULL;
5016 TALLOC_CTX *ctx = NULL;
5017 NTSTATUS status = NT_STATUS_OK;
5019 if (total_data < 10) {
5021 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5022 length. They seem to have no effect. Bug #3212. JRA */
5024 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5025 /* We're done. We only get EA info in this call. */
5026 return NT_STATUS_OK;
5029 return NT_STATUS_INVALID_PARAMETER;
5032 if (IVAL(pdata,0) > total_data) {
5033 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5034 IVAL(pdata,0), (unsigned int)total_data));
5035 return NT_STATUS_INVALID_PARAMETER;
5039 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5041 return NT_STATUS_INVALID_PARAMETER;
5043 status = set_ea(conn, fsp, fname, ea_list);
5048 /****************************************************************************
5049 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5050 ****************************************************************************/
5052 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5057 SMB_STRUCT_STAT *psbuf)
5059 NTSTATUS status = NT_STATUS_OK;
5060 bool delete_on_close;
5063 if (total_data < 1) {
5064 return NT_STATUS_INVALID_PARAMETER;
5068 return NT_STATUS_INVALID_HANDLE;
5071 delete_on_close = (CVAL(pdata,0) ? True : False);
5072 dosmode = dos_mode(conn, fname, psbuf);
5074 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5075 "delete_on_close = %u\n",
5077 (unsigned int)dosmode,
5078 (unsigned int)delete_on_close ));
5080 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5082 if (!NT_STATUS_IS_OK(status)) {
5086 /* The set is across all open files on this dev/inode pair. */
5087 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
5088 return NT_STATUS_ACCESS_DENIED;
5090 return NT_STATUS_OK;
5093 /****************************************************************************
5094 Deal with SMB_FILE_POSITION_INFORMATION.
5095 ****************************************************************************/
5097 static NTSTATUS smb_file_position_information(connection_struct *conn,
5102 SMB_BIG_UINT position_information;
5104 if (total_data < 8) {
5105 return NT_STATUS_INVALID_PARAMETER;
5109 /* Ignore on pathname based set. */
5110 return NT_STATUS_OK;
5113 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5114 #ifdef LARGE_SMB_OFF_T
5115 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5116 #else /* LARGE_SMB_OFF_T */
5117 if (IVAL(pdata,4) != 0) {
5118 /* more than 32 bits? */
5119 return NT_STATUS_INVALID_PARAMETER;
5121 #endif /* LARGE_SMB_OFF_T */
5123 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5124 fsp->fsp_name, (double)position_information ));
5125 fsp->fh->position_information = position_information;
5126 return NT_STATUS_OK;
5129 /****************************************************************************
5130 Deal with SMB_FILE_MODE_INFORMATION.
5131 ****************************************************************************/
5133 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5139 if (total_data < 4) {
5140 return NT_STATUS_INVALID_PARAMETER;
5142 mode = IVAL(pdata,0);
5143 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5144 return NT_STATUS_INVALID_PARAMETER;
5146 return NT_STATUS_OK;
5149 /****************************************************************************
5150 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5151 ****************************************************************************/
5153 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5154 struct smb_request *req,
5159 char *link_target = NULL;
5160 const char *newname = fname;
5161 NTSTATUS status = NT_STATUS_OK;
5162 TALLOC_CTX *ctx = talloc_tos();
5164 /* Set a symbolic link. */
5165 /* Don't allow this if follow links is false. */
5167 if (total_data == 0) {
5168 return NT_STATUS_INVALID_PARAMETER;
5171 if (!lp_symlinks(SNUM(conn))) {
5172 return NT_STATUS_ACCESS_DENIED;
5175 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5176 total_data, STR_TERMINATE);
5179 return NT_STATUS_INVALID_PARAMETER;
5182 /* !widelinks forces the target path to be within the share. */
5183 /* This means we can interpret the target as a pathname. */
5184 if (!lp_widelinks(SNUM(conn))) {
5185 char *rel_name = NULL;
5186 char *last_dirp = NULL;
5188 if (*link_target == '/') {
5189 /* No absolute paths allowed. */
5190 return NT_STATUS_ACCESS_DENIED;
5192 rel_name = talloc_strdup(ctx,newname);
5194 return NT_STATUS_NO_MEMORY;
5196 last_dirp = strrchr_m(rel_name, '/');
5198 last_dirp[1] = '\0';
5200 rel_name = talloc_strdup(ctx,"./");
5202 return NT_STATUS_NO_MEMORY;
5205 rel_name = talloc_asprintf_append(rel_name,
5209 return NT_STATUS_NO_MEMORY;
5212 status = check_name(conn, rel_name);
5213 if (!NT_STATUS_IS_OK(status)) {
5218 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5219 newname, link_target ));
5221 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5222 return map_nt_error_from_unix(errno);
5225 return NT_STATUS_OK;
5228 /****************************************************************************
5229 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5230 ****************************************************************************/
5232 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5233 struct smb_request *req,
5234 const char *pdata, int total_data,
5237 char *oldname = NULL;
5238 TALLOC_CTX *ctx = talloc_tos();
5239 NTSTATUS status = NT_STATUS_OK;
5241 /* Set a hard link. */
5242 if (total_data == 0) {
5243 return NT_STATUS_INVALID_PARAMETER;
5246 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5247 total_data, STR_TERMINATE, &status);
5248 if (!NT_STATUS_IS_OK(status)) {
5252 status = resolve_dfspath(ctx, conn,
5253 req->flags2 & FLAGS2_DFS_PATHNAMES,
5256 if (!NT_STATUS_IS_OK(status)) {
5260 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5263 return hardlink_internals(ctx, conn, oldname, fname);
5266 /****************************************************************************
5267 Deal with SMB_FILE_RENAME_INFORMATION.
5268 ****************************************************************************/
5270 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5271 struct smb_request *req,
5280 char *newname = NULL;
5281 char *base_name = NULL;
5282 bool dest_has_wcard = False;
5283 NTSTATUS status = NT_STATUS_OK;
5285 TALLOC_CTX *ctx = talloc_tos();
5287 if (total_data < 13) {
5288 return NT_STATUS_INVALID_PARAMETER;
5291 overwrite = (CVAL(pdata,0) ? True : False);
5292 root_fid = IVAL(pdata,4);
5293 len = IVAL(pdata,8);
5295 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5296 return NT_STATUS_INVALID_PARAMETER;
5299 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5302 if (!NT_STATUS_IS_OK(status)) {
5306 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5309 status = resolve_dfspath_wcard(ctx, conn,
5310 req->flags2 & FLAGS2_DFS_PATHNAMES,
5314 if (!NT_STATUS_IS_OK(status)) {
5318 /* Check the new name has no '/' characters. */
5319 if (strchr_m(newname, '/')) {
5320 return NT_STATUS_NOT_SUPPORTED;
5323 /* Create the base directory. */
5324 base_name = talloc_strdup(ctx, fname);
5326 return NT_STATUS_NO_MEMORY;
5328 p = strrchr_m(base_name, '/');
5332 base_name = talloc_strdup(ctx, "./");
5334 return NT_STATUS_NO_MEMORY;
5337 /* Append the new name. */
5338 base_name = talloc_asprintf_append(base_name,
5342 return NT_STATUS_NO_MEMORY;
5346 SMB_STRUCT_STAT sbuf;
5347 char *newname_last_component = NULL;
5351 status = unix_convert(ctx, conn, newname, False,
5353 &newname_last_component,
5356 /* If an error we expect this to be
5357 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5359 if (!NT_STATUS_IS_OK(status)
5360 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5365 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5366 fsp->fnum, fsp->fsp_name, base_name ));
5367 status = rename_internals_fsp(conn, fsp, base_name,
5368 newname_last_component, 0,
5371 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5372 fname, base_name ));
5373 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5374 overwrite, False, dest_has_wcard,
5375 FILE_WRITE_ATTRIBUTES);
5381 /****************************************************************************
5382 Deal with SMB_SET_POSIX_ACL.
5383 ****************************************************************************/
5385 #if defined(HAVE_POSIX_ACLS)
5386 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5391 SMB_STRUCT_STAT *psbuf)
5393 uint16 posix_acl_version;
5394 uint16 num_file_acls;
5395 uint16 num_def_acls;
5396 bool valid_file_acls = True;
5397 bool valid_def_acls = True;
5399 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5400 return NT_STATUS_INVALID_PARAMETER;
5402 posix_acl_version = SVAL(pdata,0);
5403 num_file_acls = SVAL(pdata,2);
5404 num_def_acls = SVAL(pdata,4);
5406 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5407 valid_file_acls = False;
5411 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5412 valid_def_acls = False;
5416 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5417 return NT_STATUS_INVALID_PARAMETER;
5420 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5421 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5422 return NT_STATUS_INVALID_PARAMETER;
5425 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5426 fname ? fname : fsp->fsp_name,
5427 (unsigned int)num_file_acls,
5428 (unsigned int)num_def_acls));
5430 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5431 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5432 return map_nt_error_from_unix(errno);
5435 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5436 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5437 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5438 return map_nt_error_from_unix(errno);
5440 return NT_STATUS_OK;
5444 /****************************************************************************
5445 Deal with SMB_SET_POSIX_LOCK.
5446 ****************************************************************************/
5448 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5449 const struct smb_request *req,
5455 SMB_BIG_UINT offset;
5457 bool blocking_lock = False;
5458 enum brl_type lock_type;
5460 NTSTATUS status = NT_STATUS_OK;
5462 if (fsp == NULL || fsp->fh->fd == -1) {
5463 return NT_STATUS_INVALID_HANDLE;
5466 if (total_data != POSIX_LOCK_DATA_SIZE) {
5467 return NT_STATUS_INVALID_PARAMETER;
5470 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5471 case POSIX_LOCK_TYPE_READ:
5472 lock_type = READ_LOCK;
5474 case POSIX_LOCK_TYPE_WRITE:
5475 /* Return the right POSIX-mappable error code for files opened read-only. */
5476 if (!fsp->can_write) {
5477 return NT_STATUS_INVALID_HANDLE;
5479 lock_type = WRITE_LOCK;
5481 case POSIX_LOCK_TYPE_UNLOCK:
5482 lock_type = UNLOCK_LOCK;
5485 return NT_STATUS_INVALID_PARAMETER;
5488 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5489 blocking_lock = False;
5490 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5491 blocking_lock = True;
5493 return NT_STATUS_INVALID_PARAMETER;
5496 if (!lp_blocking_locks(SNUM(conn))) {
5497 blocking_lock = False;
5500 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5501 #if defined(HAVE_LONGLONG)
5502 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5503 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5504 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5505 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5506 #else /* HAVE_LONGLONG */
5507 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5508 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5509 #endif /* HAVE_LONGLONG */
5511 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5512 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5514 (unsigned int)lock_type,
5515 (unsigned int)lock_pid,
5519 if (lock_type == UNLOCK_LOCK) {
5520 status = do_unlock(smbd_messaging_context(),
5527 uint32 block_smbpid;
5529 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5540 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5542 * A blocking lock was requested. Package up
5543 * this smb into a queued request and push it
5544 * onto the blocking lock queue.
5546 if(push_blocking_lock_request(br_lck,
5549 -1, /* infinite timeout. */
5557 TALLOC_FREE(br_lck);
5561 TALLOC_FREE(br_lck);
5567 /****************************************************************************
5568 Deal with SMB_INFO_STANDARD.
5569 ****************************************************************************/
5571 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5576 const SMB_STRUCT_STAT *psbuf)
5578 struct timespec ts[2];
5580 if (total_data < 12) {
5581 return NT_STATUS_INVALID_PARAMETER;
5585 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5587 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5589 DEBUG(10,("smb_set_info_standard: file %s\n",
5590 fname ? fname : fsp->fsp_name ));
5592 return smb_set_file_time(conn,
5600 /****************************************************************************
5601 Deal with SMB_SET_FILE_BASIC_INFO.
5602 ****************************************************************************/
5604 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5609 SMB_STRUCT_STAT *psbuf)
5611 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5612 struct timespec write_time;
5613 struct timespec changed_time;
5615 struct timespec ts[2];
5616 NTSTATUS status = NT_STATUS_OK;
5617 bool setting_write_time = true;
5619 if (total_data < 36) {
5620 return NT_STATUS_INVALID_PARAMETER;
5623 /* Set the attributes */
5624 dosmode = IVAL(pdata,32);
5625 status = smb_set_file_dosmode(conn,
5629 if (!NT_STATUS_IS_OK(status)) {
5633 /* Ignore create time at offset pdata. */
5636 ts[0] = interpret_long_date(pdata+8);
5638 write_time = interpret_long_date(pdata+16);
5639 changed_time = interpret_long_date(pdata+24);
5642 ts[1] = timespec_min(&write_time, &changed_time);
5644 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5648 /* Prefer a defined time to an undefined one. */
5649 if (null_timespec(ts[1])) {
5650 if (null_timespec(write_time)) {
5651 ts[1] = changed_time;
5652 setting_write_time = false;
5658 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5659 fname ? fname : fsp->fsp_name ));
5661 return smb_set_file_time(conn,
5666 setting_write_time);
5669 /****************************************************************************
5670 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5671 ****************************************************************************/
5673 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5674 struct smb_request *req,
5679 SMB_STRUCT_STAT *psbuf)
5681 SMB_BIG_UINT allocation_size = 0;
5682 NTSTATUS status = NT_STATUS_OK;
5683 files_struct *new_fsp = NULL;
5685 if (!VALID_STAT(*psbuf)) {
5686 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5689 if (total_data < 8) {
5690 return NT_STATUS_INVALID_PARAMETER;
5693 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5694 #ifdef LARGE_SMB_OFF_T
5695 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5696 #else /* LARGE_SMB_OFF_T */
5697 if (IVAL(pdata,4) != 0) {
5698 /* more than 32 bits? */
5699 return NT_STATUS_INVALID_PARAMETER;
5701 #endif /* LARGE_SMB_OFF_T */
5703 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5704 fname, (double)allocation_size ));
5706 if (allocation_size) {
5707 allocation_size = smb_roundup(conn, allocation_size);
5710 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5711 fname, (double)allocation_size ));
5713 if (fsp && fsp->fh->fd != -1) {
5714 /* Open file handle. */
5715 /* Only change if needed. */
5716 if (allocation_size != get_file_size(*psbuf)) {
5717 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5718 return map_nt_error_from_unix(errno);
5721 /* But always update the time. */
5723 * This is equivalent to a write. Ensure it's seen immediately
5724 * if there are no pending writes.
5726 trigger_write_time_update(fsp);
5727 return NT_STATUS_OK;
5730 /* Pathname or stat or directory file. */
5732 status = open_file_ntcreate(conn, req, fname, psbuf,
5734 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5737 FILE_ATTRIBUTE_NORMAL,
5738 FORCE_OPLOCK_BREAK_TO_NONE,
5741 if (!NT_STATUS_IS_OK(status)) {
5742 /* NB. We check for open_was_deferred in the caller. */
5746 /* Only change if needed. */
5747 if (allocation_size != get_file_size(*psbuf)) {
5748 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5749 status = map_nt_error_from_unix(errno);
5750 close_file(new_fsp,NORMAL_CLOSE);
5755 /* Changing the allocation size should set the last mod time. */
5757 * This is equivalent to a write. Ensure it's seen immediately
5758 * if there are no pending writes.
5760 trigger_write_time_update(new_fsp);
5762 close_file(new_fsp,NORMAL_CLOSE);
5763 return NT_STATUS_OK;
5766 /****************************************************************************
5767 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5768 ****************************************************************************/
5770 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5771 struct smb_request *req,
5776 SMB_STRUCT_STAT *psbuf)
5780 if (total_data < 8) {
5781 return NT_STATUS_INVALID_PARAMETER;
5784 size = IVAL(pdata,0);
5785 #ifdef LARGE_SMB_OFF_T
5786 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5787 #else /* LARGE_SMB_OFF_T */
5788 if (IVAL(pdata,4) != 0) {
5789 /* more than 32 bits? */
5790 return NT_STATUS_INVALID_PARAMETER;
5792 #endif /* LARGE_SMB_OFF_T */
5793 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5794 "file %s to %.0f\n", fname, (double)size ));
5796 return smb_set_file_size(conn, req,
5803 /****************************************************************************
5804 Allow a UNIX info mknod.
5805 ****************************************************************************/
5807 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5811 SMB_STRUCT_STAT *psbuf)
5813 uint32 file_type = IVAL(pdata,56);
5814 #if defined(HAVE_MAKEDEV)
5815 uint32 dev_major = IVAL(pdata,60);
5816 uint32 dev_minor = IVAL(pdata,68);
5818 SMB_DEV_T dev = (SMB_DEV_T)0;
5819 uint32 raw_unixmode = IVAL(pdata,84);
5823 if (total_data < 100) {
5824 return NT_STATUS_INVALID_PARAMETER;
5827 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5828 if (!NT_STATUS_IS_OK(status)) {
5832 #if defined(HAVE_MAKEDEV)
5833 dev = makedev(dev_major, dev_minor);
5836 switch (file_type) {
5837 #if defined(S_IFIFO)
5838 case UNIX_TYPE_FIFO:
5839 unixmode |= S_IFIFO;
5842 #if defined(S_IFSOCK)
5843 case UNIX_TYPE_SOCKET:
5844 unixmode |= S_IFSOCK;
5847 #if defined(S_IFCHR)
5848 case UNIX_TYPE_CHARDEV:
5849 unixmode |= S_IFCHR;
5852 #if defined(S_IFBLK)
5853 case UNIX_TYPE_BLKDEV:
5854 unixmode |= S_IFBLK;
5858 return NT_STATUS_INVALID_PARAMETER;
5861 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5862 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5864 /* Ok - do the mknod. */
5865 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5866 return map_nt_error_from_unix(errno);
5869 /* If any of the other "set" calls fail we
5870 * don't want to end up with a half-constructed mknod.
5873 if (lp_inherit_perms(SNUM(conn))) {
5874 inherit_access_posix_acl(
5875 conn, parent_dirname(fname),
5879 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5880 status = map_nt_error_from_unix(errno);
5881 SMB_VFS_UNLINK(conn,fname);
5884 return NT_STATUS_OK;
5887 /****************************************************************************
5888 Deal with SMB_SET_FILE_UNIX_BASIC.
5889 ****************************************************************************/
5891 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5892 struct smb_request *req,
5897 SMB_STRUCT_STAT *psbuf)
5899 struct timespec ts[2];
5900 uint32 raw_unixmode;
5903 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5904 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5905 NTSTATUS status = NT_STATUS_OK;
5906 bool delete_on_fail = False;
5907 enum perm_type ptype;
5909 if (total_data < 100) {
5910 return NT_STATUS_INVALID_PARAMETER;
5913 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5914 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5915 size=IVAL(pdata,0); /* first 8 Bytes are size */
5916 #ifdef LARGE_SMB_OFF_T
5917 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5918 #else /* LARGE_SMB_OFF_T */
5919 if (IVAL(pdata,4) != 0) {
5920 /* more than 32 bits? */
5921 return NT_STATUS_INVALID_PARAMETER;
5923 #endif /* LARGE_SMB_OFF_T */
5926 ts[0] = interpret_long_date(pdata+24); /* access_time */
5927 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5928 set_owner = (uid_t)IVAL(pdata,40);
5929 set_grp = (gid_t)IVAL(pdata,48);
5930 raw_unixmode = IVAL(pdata,84);
5932 if (VALID_STAT(*psbuf)) {
5933 if (S_ISDIR(psbuf->st_mode)) {
5934 ptype = PERM_EXISTING_DIR;
5936 ptype = PERM_EXISTING_FILE;
5939 ptype = PERM_NEW_FILE;
5942 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5943 if (!NT_STATUS_IS_OK(status)) {
5947 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5948 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5949 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5951 if (!VALID_STAT(*psbuf)) {
5953 * The only valid use of this is to create character and block
5954 * devices, and named pipes. This is deprecated (IMHO) and
5955 * a new info level should be used for mknod. JRA.
5958 status = smb_unix_mknod(conn,
5963 if (!NT_STATUS_IS_OK(status)) {
5967 /* Ensure we don't try and change anything else. */
5968 raw_unixmode = SMB_MODE_NO_CHANGE;
5969 size = get_file_size(*psbuf);
5970 ts[0] = get_atimespec(psbuf);
5971 ts[1] = get_mtimespec(psbuf);
5973 * We continue here as we might want to change the
5976 delete_on_fail = True;
5980 /* Horrible backwards compatibility hack as an old server bug
5981 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5985 size = get_file_size(*psbuf);
5990 * Deal with the UNIX specific mode set.
5993 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5994 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5995 (unsigned int)unixmode, fname ));
5996 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5997 return map_nt_error_from_unix(errno);
6002 * Deal with the UNIX specific uid set.
6005 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6008 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6009 (unsigned int)set_owner, fname ));
6011 if (S_ISLNK(psbuf->st_mode)) {
6012 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6014 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6018 status = map_nt_error_from_unix(errno);
6019 if (delete_on_fail) {
6020 SMB_VFS_UNLINK(conn,fname);
6027 * Deal with the UNIX specific gid set.
6030 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6031 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6032 (unsigned int)set_owner, fname ));
6033 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6034 status = map_nt_error_from_unix(errno);
6035 if (delete_on_fail) {
6036 SMB_VFS_UNLINK(conn,fname);
6042 /* Deal with any size changes. */
6044 status = smb_set_file_size(conn, req,
6049 if (!NT_STATUS_IS_OK(status)) {
6053 /* Deal with any time changes. */
6055 return smb_set_file_time(conn,
6063 /****************************************************************************
6064 Deal with SMB_SET_FILE_UNIX_INFO2.
6065 ****************************************************************************/
6067 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6068 struct smb_request *req,
6073 SMB_STRUCT_STAT *psbuf)
6079 if (total_data < 116) {
6080 return NT_STATUS_INVALID_PARAMETER;
6083 /* Start by setting all the fields that are common between UNIX_BASIC
6086 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6088 if (!NT_STATUS_IS_OK(status)) {
6092 smb_fflags = IVAL(pdata, 108);
6093 smb_fmask = IVAL(pdata, 112);
6095 /* NB: We should only attempt to alter the file flags if the client
6096 * sends a non-zero mask.
6098 if (smb_fmask != 0) {
6099 int stat_fflags = 0;
6101 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6103 /* Client asked to alter a flag we don't understand. */
6104 return NT_STATUS_INVALID_PARAMETER;
6107 if (fsp && fsp->fh->fd != -1) {
6108 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6109 return NT_STATUS_NOT_SUPPORTED;
6111 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6112 return map_nt_error_from_unix(errno);
6117 /* XXX: need to add support for changing the create_time here. You
6118 * can do this for paths on Darwin with setattrlist(2). The right way
6119 * to hook this up is probably by extending the VFS utimes interface.
6122 return NT_STATUS_OK;
6125 /****************************************************************************
6126 Create a directory with POSIX semantics.
6127 ****************************************************************************/
6129 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6130 struct smb_request *req,
6134 SMB_STRUCT_STAT *psbuf,
6135 int *pdata_return_size)
6137 NTSTATUS status = NT_STATUS_OK;
6138 uint32 raw_unixmode = 0;
6139 uint32 mod_unixmode = 0;
6140 mode_t unixmode = (mode_t)0;
6141 files_struct *fsp = NULL;
6142 uint16 info_level_return = 0;
6144 char *pdata = *ppdata;
6146 if (total_data < 18) {
6147 return NT_STATUS_INVALID_PARAMETER;
6150 raw_unixmode = IVAL(pdata,8);
6151 /* Next 4 bytes are not yet defined. */
6153 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6154 if (!NT_STATUS_IS_OK(status)) {
6158 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6160 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6161 fname, (unsigned int)unixmode ));
6163 status = open_directory(conn, req,
6166 FILE_READ_ATTRIBUTES, /* Just a stat open */
6167 FILE_SHARE_NONE, /* Ignored for stat opens */
6174 if (NT_STATUS_IS_OK(status)) {
6175 close_file(fsp, NORMAL_CLOSE);
6178 info_level_return = SVAL(pdata,16);
6180 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6181 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6182 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6183 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6185 *pdata_return_size = 12;
6188 /* Realloc the data size */
6189 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6190 if (*ppdata == NULL) {
6191 *pdata_return_size = 0;
6192 return NT_STATUS_NO_MEMORY;
6196 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6197 SSVAL(pdata,2,0); /* No fnum. */
6198 SIVAL(pdata,4,info); /* Was directory created. */
6200 switch (info_level_return) {
6201 case SMB_QUERY_FILE_UNIX_BASIC:
6202 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6203 SSVAL(pdata,10,0); /* Padding. */
6204 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6206 case SMB_QUERY_FILE_UNIX_INFO2:
6207 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6208 SSVAL(pdata,10,0); /* Padding. */
6209 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6212 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6213 SSVAL(pdata,10,0); /* Padding. */
6220 /****************************************************************************
6221 Open/Create a file with POSIX semantics.
6222 ****************************************************************************/
6224 static NTSTATUS smb_posix_open(connection_struct *conn,
6225 struct smb_request *req,
6229 SMB_STRUCT_STAT *psbuf,
6230 int *pdata_return_size)
6232 bool extended_oplock_granted = False;
6233 char *pdata = *ppdata;
6235 uint32 wire_open_mode = 0;
6236 uint32 raw_unixmode = 0;
6237 uint32 mod_unixmode = 0;
6238 uint32 create_disp = 0;
6239 uint32 access_mask = 0;
6240 uint32 create_options = 0;
6241 NTSTATUS status = NT_STATUS_OK;
6242 mode_t unixmode = (mode_t)0;
6243 files_struct *fsp = NULL;
6244 int oplock_request = 0;
6246 uint16 info_level_return = 0;
6248 if (total_data < 18) {
6249 return NT_STATUS_INVALID_PARAMETER;
6252 flags = IVAL(pdata,0);
6253 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6254 if (oplock_request) {
6255 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6258 wire_open_mode = IVAL(pdata,4);
6260 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6261 return smb_posix_mkdir(conn, req,
6269 switch (wire_open_mode & SMB_ACCMODE) {
6271 access_mask = FILE_READ_DATA;
6274 access_mask = FILE_WRITE_DATA;
6277 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6280 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6281 (unsigned int)wire_open_mode ));
6282 return NT_STATUS_INVALID_PARAMETER;
6285 wire_open_mode &= ~SMB_ACCMODE;
6287 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6288 create_disp = FILE_CREATE;
6289 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6290 create_disp = FILE_OVERWRITE_IF;
6291 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6292 create_disp = FILE_OPEN_IF;
6294 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6295 (unsigned int)wire_open_mode ));
6296 return NT_STATUS_INVALID_PARAMETER;
6299 raw_unixmode = IVAL(pdata,8);
6300 /* Next 4 bytes are not yet defined. */
6302 status = unix_perms_from_wire(conn,
6305 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6308 if (!NT_STATUS_IS_OK(status)) {
6312 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6314 if (wire_open_mode & SMB_O_SYNC) {
6315 create_options |= FILE_WRITE_THROUGH;
6317 if (wire_open_mode & SMB_O_APPEND) {
6318 access_mask |= FILE_APPEND_DATA;
6320 if (wire_open_mode & SMB_O_DIRECT) {
6321 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6324 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6326 (unsigned int)wire_open_mode,
6327 (unsigned int)unixmode ));
6329 status = open_file_ntcreate(conn, req,
6333 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6335 0, /* no create options yet. */
6341 if (!NT_STATUS_IS_OK(status)) {
6345 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6346 extended_oplock_granted = True;
6349 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6350 extended_oplock_granted = True;
6353 info_level_return = SVAL(pdata,16);
6355 /* Allocate the correct return size. */
6357 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6358 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6359 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6360 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6362 *pdata_return_size = 12;
6365 /* Realloc the data size */
6366 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6367 if (*ppdata == NULL) {
6368 close_file(fsp,ERROR_CLOSE);
6369 *pdata_return_size = 0;
6370 return NT_STATUS_NO_MEMORY;
6374 if (extended_oplock_granted) {
6375 if (flags & REQUEST_BATCH_OPLOCK) {
6376 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6378 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6380 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6381 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6383 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6386 SSVAL(pdata,2,fsp->fnum);
6387 SIVAL(pdata,4,info); /* Was file created etc. */
6389 switch (info_level_return) {
6390 case SMB_QUERY_FILE_UNIX_BASIC:
6391 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6392 SSVAL(pdata,10,0); /* padding. */
6393 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6395 case SMB_QUERY_FILE_UNIX_INFO2:
6396 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6397 SSVAL(pdata,10,0); /* padding. */
6398 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6401 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6402 SSVAL(pdata,10,0); /* padding. */
6405 return NT_STATUS_OK;
6408 /****************************************************************************
6409 Delete a file with POSIX semantics.
6410 ****************************************************************************/
6412 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6413 struct smb_request *req,
6417 SMB_STRUCT_STAT *psbuf)
6419 NTSTATUS status = NT_STATUS_OK;
6420 files_struct *fsp = NULL;
6425 struct share_mode_lock *lck = NULL;
6427 if (total_data < 2) {
6428 return NT_STATUS_INVALID_PARAMETER;
6431 flags = SVAL(pdata,0);
6433 if (!VALID_STAT(*psbuf)) {
6434 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6437 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6438 !VALID_STAT_OF_DIR(*psbuf)) {
6439 return NT_STATUS_NOT_A_DIRECTORY;
6442 DEBUG(10,("smb_posix_unlink: %s %s\n",
6443 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6446 if (VALID_STAT_OF_DIR(*psbuf)) {
6447 status = open_directory(conn, req,
6451 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6454 FILE_FLAG_POSIX_SEMANTICS|0777,
6459 status = open_file_ntcreate(conn, req,
6463 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6466 FILE_FLAG_POSIX_SEMANTICS|0777,
6467 0, /* No oplock, but break existing ones. */
6472 if (!NT_STATUS_IS_OK(status)) {
6477 * Don't lie to client. If we can't really delete due to
6478 * non-POSIX opens return SHARING_VIOLATION.
6481 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6484 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6485 "lock for file %s\n", fsp->fsp_name));
6486 close_file(fsp, NORMAL_CLOSE);
6487 return NT_STATUS_INVALID_PARAMETER;
6491 * See if others still have the file open. If this is the case, then
6492 * don't delete. If all opens are POSIX delete we can set the delete
6493 * on close disposition.
6495 for (i=0; i<lck->num_share_modes; i++) {
6496 struct share_mode_entry *e = &lck->share_modes[i];
6497 if (is_valid_share_mode_entry(e)) {
6498 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6501 /* Fail with sharing violation. */
6502 close_file(fsp, NORMAL_CLOSE);
6504 return NT_STATUS_SHARING_VIOLATION;
6509 * Set the delete on close.
6511 status = smb_set_file_disposition_info(conn,
6518 if (!NT_STATUS_IS_OK(status)) {
6519 close_file(fsp, NORMAL_CLOSE);
6524 return close_file(fsp, NORMAL_CLOSE);
6527 /****************************************************************************
6528 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6529 ****************************************************************************/
6531 static void call_trans2setfilepathinfo(connection_struct *conn,
6532 struct smb_request *req,
6533 unsigned int tran_call,
6534 char **pparams, int total_params,
6535 char **ppdata, int total_data,
6536 unsigned int max_data_bytes)
6538 char *params = *pparams;
6539 char *pdata = *ppdata;
6541 SMB_STRUCT_STAT sbuf;
6543 files_struct *fsp = NULL;
6544 NTSTATUS status = NT_STATUS_OK;
6545 int data_return_size = 0;
6546 TALLOC_CTX *ctx = talloc_tos();
6549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6555 if (tran_call == TRANSACT2_SETFILEINFO) {
6556 if (total_params < 4) {
6557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6561 fsp = file_fsp(SVAL(params,0));
6562 /* Basic check for non-null fsp. */
6563 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6566 info_level = SVAL(params,2);
6568 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6570 reply_nterror(req, NT_STATUS_NO_MEMORY);
6574 if(fsp->is_directory || fsp->fh->fd == -1) {
6576 * This is actually a SETFILEINFO on a directory
6577 * handle (returned from an NT SMB). NT5.0 seems
6578 * to do this call. JRA.
6580 if (INFO_LEVEL_IS_UNIX(info_level)) {
6581 /* Always do lstat for UNIX calls. */
6582 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6583 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6584 reply_unixerror(req,ERRDOS,ERRbadpath);
6588 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6589 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6590 reply_unixerror(req,ERRDOS,ERRbadpath);
6594 } else if (fsp->print_file) {
6596 * Doing a DELETE_ON_CLOSE should cancel a print job.
6598 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6599 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6601 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6604 send_trans2_replies(conn, req, params, 2,
6609 reply_unixerror(req, ERRDOS, ERRbadpath);
6614 * Original code - this is an open file.
6616 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6620 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6621 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6622 reply_unixerror(req, ERRDOS, ERRbadfid);
6628 if (total_params < 7) {
6629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6633 info_level = SVAL(params,0);
6634 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6635 total_params - 6, STR_TERMINATE,
6637 if (!NT_STATUS_IS_OK(status)) {
6638 reply_nterror(req, status);
6642 status = resolve_dfspath(ctx, conn,
6643 req->flags2 & FLAGS2_DFS_PATHNAMES,
6646 if (!NT_STATUS_IS_OK(status)) {
6647 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6648 reply_botherror(req,
6649 NT_STATUS_PATH_NOT_COVERED,
6650 ERRSRV, ERRbadpath);
6653 reply_nterror(req, status);
6657 status = unix_convert(ctx, conn, fname, False,
6658 &fname, NULL, &sbuf);
6659 if (!NT_STATUS_IS_OK(status)) {
6660 reply_nterror(req, status);
6664 status = check_name(conn, fname);
6665 if (!NT_STATUS_IS_OK(status)) {
6666 reply_nterror(req, status);
6670 if (INFO_LEVEL_IS_UNIX(info_level)) {
6672 * For CIFS UNIX extensions the target name may not exist.
6675 /* Always do lstat for UNIX calls. */
6676 SMB_VFS_LSTAT(conn,fname,&sbuf);
6678 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6679 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6680 reply_unixerror(req, ERRDOS, ERRbadpath);
6685 if (!CAN_WRITE(conn)) {
6686 reply_doserror(req, ERRSRV, ERRaccess);
6690 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6691 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6695 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6696 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6698 /* Realloc the parameter size */
6699 *pparams = (char *)SMB_REALLOC(*pparams,2);
6700 if (*pparams == NULL) {
6701 reply_nterror(req, NT_STATUS_NO_MEMORY);
6708 switch (info_level) {
6710 case SMB_INFO_STANDARD:
6712 status = smb_set_info_standard(conn,
6721 case SMB_INFO_SET_EA:
6723 status = smb_info_set_ea(conn,
6731 case SMB_SET_FILE_BASIC_INFO:
6732 case SMB_FILE_BASIC_INFORMATION:
6734 status = smb_set_file_basic_info(conn,
6743 case SMB_FILE_ALLOCATION_INFORMATION:
6744 case SMB_SET_FILE_ALLOCATION_INFO:
6746 status = smb_set_file_allocation_info(conn, req,
6755 case SMB_FILE_END_OF_FILE_INFORMATION:
6756 case SMB_SET_FILE_END_OF_FILE_INFO:
6758 status = smb_set_file_end_of_file_info(conn, req,
6767 case SMB_FILE_DISPOSITION_INFORMATION:
6768 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6771 /* JRA - We used to just ignore this on a path ?
6772 * Shouldn't this be invalid level on a pathname
6775 if (tran_call != TRANSACT2_SETFILEINFO) {
6776 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6779 status = smb_set_file_disposition_info(conn,
6788 case SMB_FILE_POSITION_INFORMATION:
6790 status = smb_file_position_information(conn,
6797 /* From tridge Samba4 :
6798 * MODE_INFORMATION in setfileinfo (I have no
6799 * idea what "mode information" on a file is - it takes a value of 0,
6800 * 2, 4 or 6. What could it be?).
6803 case SMB_FILE_MODE_INFORMATION:
6805 status = smb_file_mode_information(conn,
6812 * CIFS UNIX extensions.
6815 case SMB_SET_FILE_UNIX_BASIC:
6817 status = smb_set_file_unix_basic(conn, req,
6826 case SMB_SET_FILE_UNIX_INFO2:
6828 status = smb_set_file_unix_info2(conn, req,
6837 case SMB_SET_FILE_UNIX_LINK:
6839 if (tran_call != TRANSACT2_SETPATHINFO) {
6840 /* We must have a pathname for this. */
6841 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6844 status = smb_set_file_unix_link(conn, req, pdata,
6849 case SMB_SET_FILE_UNIX_HLINK:
6851 if (tran_call != TRANSACT2_SETPATHINFO) {
6852 /* We must have a pathname for this. */
6853 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6856 status = smb_set_file_unix_hlink(conn, req,
6862 case SMB_FILE_RENAME_INFORMATION:
6864 status = smb_file_rename_information(conn, req,
6870 #if defined(HAVE_POSIX_ACLS)
6871 case SMB_SET_POSIX_ACL:
6873 status = smb_set_posix_acl(conn,
6883 case SMB_SET_POSIX_LOCK:
6885 if (tran_call != TRANSACT2_SETFILEINFO) {
6886 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6889 status = smb_set_posix_lock(conn, req,
6890 pdata, total_data, fsp);
6894 case SMB_POSIX_PATH_OPEN:
6896 if (tran_call != TRANSACT2_SETPATHINFO) {
6897 /* We must have a pathname for this. */
6898 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6902 status = smb_posix_open(conn, req,
6911 case SMB_POSIX_PATH_UNLINK:
6913 if (tran_call != TRANSACT2_SETPATHINFO) {
6914 /* We must have a pathname for this. */
6915 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6919 status = smb_posix_unlink(conn, req,
6928 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6933 if (!NT_STATUS_IS_OK(status)) {
6934 if (open_was_deferred(req->mid)) {
6935 /* We have re-scheduled this call. */
6938 if (blocking_lock_was_deferred(req->mid)) {
6939 /* We have re-scheduled this call. */
6942 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6943 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6944 ERRSRV, ERRbadpath);
6947 if (info_level == SMB_POSIX_PATH_OPEN) {
6948 reply_openerror(req, status);
6952 reply_nterror(req, status);
6957 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6963 /****************************************************************************
6964 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6965 ****************************************************************************/
6967 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6968 char **pparams, int total_params,
6969 char **ppdata, int total_data,
6970 unsigned int max_data_bytes)
6972 char *params = *pparams;
6973 char *pdata = *ppdata;
6974 char *directory = NULL;
6975 SMB_STRUCT_STAT sbuf;
6976 NTSTATUS status = NT_STATUS_OK;
6977 struct ea_list *ea_list = NULL;
6978 TALLOC_CTX *ctx = talloc_tos();
6980 if (!CAN_WRITE(conn)) {
6981 reply_doserror(req, ERRSRV, ERRaccess);
6985 if (total_params < 5) {
6986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6990 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6991 total_params - 4, STR_TERMINATE,
6993 if (!NT_STATUS_IS_OK(status)) {
6994 reply_nterror(req, status);
6998 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7000 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7001 if (!NT_STATUS_IS_OK(status)) {
7002 reply_nterror(req, status);
7006 status = check_name(conn, directory);
7007 if (!NT_STATUS_IS_OK(status)) {
7008 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7009 reply_nterror(req, status);
7013 /* Any data in this call is an EA list. */
7014 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7015 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7020 * OS/2 workplace shell seems to send SET_EA requests of "null"
7021 * length (4 bytes containing IVAL 4).
7022 * They seem to have no effect. Bug #3212. JRA.
7025 if (total_data != 4) {
7026 if (total_data < 10) {
7027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7031 if (IVAL(pdata,0) > total_data) {
7032 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7033 IVAL(pdata,0), (unsigned int)total_data));
7034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7038 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7044 } else if (IVAL(pdata,0) != 4) {
7045 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7049 status = create_directory(conn, req, directory);
7051 if (!NT_STATUS_IS_OK(status)) {
7052 reply_nterror(req, status);
7056 /* Try and set any given EA. */
7058 status = set_ea(conn, NULL, directory, ea_list);
7059 if (!NT_STATUS_IS_OK(status)) {
7060 reply_nterror(req, status);
7065 /* Realloc the parameter and data sizes */
7066 *pparams = (char *)SMB_REALLOC(*pparams,2);
7067 if(*pparams == NULL) {
7068 reply_nterror(req, NT_STATUS_NO_MEMORY);
7075 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7080 /****************************************************************************
7081 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7082 We don't actually do this - we just send a null response.
7083 ****************************************************************************/
7085 static void call_trans2findnotifyfirst(connection_struct *conn,
7086 struct smb_request *req,
7087 char **pparams, int total_params,
7088 char **ppdata, int total_data,
7089 unsigned int max_data_bytes)
7091 static uint16 fnf_handle = 257;
7092 char *params = *pparams;
7095 if (total_params < 6) {
7096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7100 info_level = SVAL(params,4);
7101 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7103 switch (info_level) {
7108 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7112 /* Realloc the parameter and data sizes */
7113 *pparams = (char *)SMB_REALLOC(*pparams,6);
7114 if (*pparams == NULL) {
7115 reply_nterror(req, NT_STATUS_NO_MEMORY);
7120 SSVAL(params,0,fnf_handle);
7121 SSVAL(params,2,0); /* No changes */
7122 SSVAL(params,4,0); /* No EA errors */
7129 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7134 /****************************************************************************
7135 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7136 changes). Currently this does nothing.
7137 ****************************************************************************/
7139 static void call_trans2findnotifynext(connection_struct *conn,
7140 struct smb_request *req,
7141 char **pparams, int total_params,
7142 char **ppdata, int total_data,
7143 unsigned int max_data_bytes)
7145 char *params = *pparams;
7147 DEBUG(3,("call_trans2findnotifynext\n"));
7149 /* Realloc the parameter and data sizes */
7150 *pparams = (char *)SMB_REALLOC(*pparams,4);
7151 if (*pparams == NULL) {
7152 reply_nterror(req, NT_STATUS_NO_MEMORY);
7157 SSVAL(params,0,0); /* No changes */
7158 SSVAL(params,2,0); /* No EA errors */
7160 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7165 /****************************************************************************
7166 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7167 ****************************************************************************/
7169 static void call_trans2getdfsreferral(connection_struct *conn,
7170 struct smb_request *req,
7171 char **pparams, int total_params,
7172 char **ppdata, int total_data,
7173 unsigned int max_data_bytes)
7175 char *params = *pparams;
7176 char *pathname = NULL;
7178 int max_referral_level;
7179 NTSTATUS status = NT_STATUS_OK;
7180 TALLOC_CTX *ctx = talloc_tos();
7182 DEBUG(10,("call_trans2getdfsreferral\n"));
7184 if (total_params < 3) {
7185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7189 max_referral_level = SVAL(params,0);
7191 if(!lp_host_msdfs()) {
7192 reply_doserror(req, ERRDOS, ERRbadfunc);
7196 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7197 total_params - 2, STR_TERMINATE);
7199 reply_nterror(req, NT_STATUS_NOT_FOUND);
7202 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7203 ppdata,&status)) < 0) {
7204 reply_nterror(req, status);
7208 SSVAL(req->inbuf, smb_flg2,
7209 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7210 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7215 #define LMCAT_SPL 0x53
7216 #define LMFUNC_GETJOBID 0x60
7218 /****************************************************************************
7219 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7220 ****************************************************************************/
7222 static void call_trans2ioctl(connection_struct *conn,
7223 struct smb_request *req,
7224 char **pparams, int total_params,
7225 char **ppdata, int total_data,
7226 unsigned int max_data_bytes)
7228 char *pdata = *ppdata;
7229 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7231 /* check for an invalid fid before proceeding */
7234 reply_doserror(req, ERRDOS, ERRbadfid);
7238 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7239 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7240 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7241 if (*ppdata == NULL) {
7242 reply_nterror(req, NT_STATUS_NO_MEMORY);
7247 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7248 CAN ACCEPT THIS IN UNICODE. JRA. */
7250 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7251 srvstr_push(pdata, req->flags2, pdata + 2,
7252 global_myname(), 15,
7253 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7254 srvstr_push(pdata, req->flags2, pdata+18,
7255 lp_servicename(SNUM(conn)), 13,
7256 STR_ASCII|STR_TERMINATE); /* Service name */
7257 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7262 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7263 reply_doserror(req, ERRSRV, ERRerror);
7266 /****************************************************************************
7267 Reply to a SMBfindclose (stop trans2 directory search).
7268 ****************************************************************************/
7270 void reply_findclose(struct smb_request *req)
7274 START_PROFILE(SMBfindclose);
7277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7278 END_PROFILE(SMBfindclose);
7282 dptr_num = SVALS(req->inbuf,smb_vwv0);
7284 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7286 dptr_close(&dptr_num);
7288 reply_outbuf(req, 0, 0);
7290 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7292 END_PROFILE(SMBfindclose);
7296 /****************************************************************************
7297 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7298 ****************************************************************************/
7300 void reply_findnclose(struct smb_request *req)
7304 START_PROFILE(SMBfindnclose);
7307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7308 END_PROFILE(SMBfindnclose);
7312 dptr_num = SVAL(req->inbuf,smb_vwv0);
7314 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7316 /* We never give out valid handles for a
7317 findnotifyfirst - so any dptr_num is ok here.
7320 reply_outbuf(req, 0, 0);
7322 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7324 END_PROFILE(SMBfindnclose);
7328 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7329 struct trans_state *state)
7331 if (Protocol >= PROTOCOL_NT1) {
7332 req->flags2 |= 0x40; /* IS_LONG_NAME */
7333 SSVAL(req->inbuf,smb_flg2,req->flags2);
7336 if (conn->encrypt_level == Required && !req->encrypted) {
7337 if (state->call != TRANSACT2_QFSINFO &&
7338 state->call != TRANSACT2_SETFSINFO) {
7339 DEBUG(0,("handle_trans2: encryption required "
7341 (unsigned int)state->call));
7342 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7347 /* Now we must call the relevant TRANS2 function */
7348 switch(state->call) {
7349 case TRANSACT2_OPEN:
7351 START_PROFILE(Trans2_open);
7352 call_trans2open(conn, req,
7353 &state->param, state->total_param,
7354 &state->data, state->total_data,
7355 state->max_data_return);
7356 END_PROFILE(Trans2_open);
7360 case TRANSACT2_FINDFIRST:
7362 START_PROFILE(Trans2_findfirst);
7363 call_trans2findfirst(conn, req,
7364 &state->param, state->total_param,
7365 &state->data, state->total_data,
7366 state->max_data_return);
7367 END_PROFILE(Trans2_findfirst);
7371 case TRANSACT2_FINDNEXT:
7373 START_PROFILE(Trans2_findnext);
7374 call_trans2findnext(conn, req,
7375 &state->param, state->total_param,
7376 &state->data, state->total_data,
7377 state->max_data_return);
7378 END_PROFILE(Trans2_findnext);
7382 case TRANSACT2_QFSINFO:
7384 START_PROFILE(Trans2_qfsinfo);
7385 call_trans2qfsinfo(conn, req,
7386 &state->param, state->total_param,
7387 &state->data, state->total_data,
7388 state->max_data_return);
7389 END_PROFILE(Trans2_qfsinfo);
7393 case TRANSACT2_SETFSINFO:
7395 START_PROFILE(Trans2_setfsinfo);
7396 call_trans2setfsinfo(conn, req,
7397 &state->param, state->total_param,
7398 &state->data, state->total_data,
7399 state->max_data_return);
7400 END_PROFILE(Trans2_setfsinfo);
7404 case TRANSACT2_QPATHINFO:
7405 case TRANSACT2_QFILEINFO:
7407 START_PROFILE(Trans2_qpathinfo);
7408 call_trans2qfilepathinfo(conn, req, state->call,
7409 &state->param, state->total_param,
7410 &state->data, state->total_data,
7411 state->max_data_return);
7412 END_PROFILE(Trans2_qpathinfo);
7416 case TRANSACT2_SETPATHINFO:
7417 case TRANSACT2_SETFILEINFO:
7419 START_PROFILE(Trans2_setpathinfo);
7420 call_trans2setfilepathinfo(conn, req, state->call,
7421 &state->param, state->total_param,
7422 &state->data, state->total_data,
7423 state->max_data_return);
7424 END_PROFILE(Trans2_setpathinfo);
7428 case TRANSACT2_FINDNOTIFYFIRST:
7430 START_PROFILE(Trans2_findnotifyfirst);
7431 call_trans2findnotifyfirst(conn, req,
7432 &state->param, state->total_param,
7433 &state->data, state->total_data,
7434 state->max_data_return);
7435 END_PROFILE(Trans2_findnotifyfirst);
7439 case TRANSACT2_FINDNOTIFYNEXT:
7441 START_PROFILE(Trans2_findnotifynext);
7442 call_trans2findnotifynext(conn, req,
7443 &state->param, state->total_param,
7444 &state->data, state->total_data,
7445 state->max_data_return);
7446 END_PROFILE(Trans2_findnotifynext);
7450 case TRANSACT2_MKDIR:
7452 START_PROFILE(Trans2_mkdir);
7453 call_trans2mkdir(conn, req,
7454 &state->param, state->total_param,
7455 &state->data, state->total_data,
7456 state->max_data_return);
7457 END_PROFILE(Trans2_mkdir);
7461 case TRANSACT2_GET_DFS_REFERRAL:
7463 START_PROFILE(Trans2_get_dfs_referral);
7464 call_trans2getdfsreferral(conn, req,
7465 &state->param, state->total_param,
7466 &state->data, state->total_data,
7467 state->max_data_return);
7468 END_PROFILE(Trans2_get_dfs_referral);
7472 case TRANSACT2_IOCTL:
7474 START_PROFILE(Trans2_ioctl);
7475 call_trans2ioctl(conn, req,
7476 &state->param, state->total_param,
7477 &state->data, state->total_data,
7478 state->max_data_return);
7479 END_PROFILE(Trans2_ioctl);
7484 /* Error in request */
7485 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7486 reply_doserror(req, ERRSRV,ERRerror);
7490 /****************************************************************************
7491 Reply to a SMBtrans2.
7492 ****************************************************************************/
7494 void reply_trans2(struct smb_request *req)
7496 connection_struct *conn = req->conn;
7501 unsigned int tran_call;
7503 unsigned int av_size;
7504 struct trans_state *state;
7507 START_PROFILE(SMBtrans2);
7509 if (req->wct < 14) {
7510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7511 END_PROFILE(SMBtrans2);
7515 dsoff = SVAL(req->inbuf, smb_dsoff);
7516 dscnt = SVAL(req->inbuf, smb_dscnt);
7517 psoff = SVAL(req->inbuf, smb_psoff);
7518 pscnt = SVAL(req->inbuf, smb_pscnt);
7519 tran_call = SVAL(req->inbuf, smb_setup0);
7520 size = smb_len(req->inbuf) + 4;
7521 av_size = smb_len(req->inbuf);
7523 result = allow_new_trans(conn->pending_trans, req->mid);
7524 if (!NT_STATUS_IS_OK(result)) {
7525 DEBUG(2, ("Got invalid trans2 request: %s\n",
7526 nt_errstr(result)));
7527 reply_nterror(req, result);
7528 END_PROFILE(SMBtrans2);
7533 switch (tran_call) {
7534 /* List the allowed trans2 calls on IPC$ */
7535 case TRANSACT2_OPEN:
7536 case TRANSACT2_GET_DFS_REFERRAL:
7537 case TRANSACT2_QFILEINFO:
7538 case TRANSACT2_QFSINFO:
7539 case TRANSACT2_SETFSINFO:
7542 reply_doserror(req, ERRSRV, ERRaccess);
7543 END_PROFILE(SMBtrans2);
7548 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7549 DEBUG(0, ("talloc failed\n"));
7550 reply_nterror(req, NT_STATUS_NO_MEMORY);
7551 END_PROFILE(SMBtrans2);
7555 state->cmd = SMBtrans2;
7557 state->mid = req->mid;
7558 state->vuid = req->vuid;
7559 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7560 state->setup = NULL;
7561 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7562 state->param = NULL;
7563 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7565 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7566 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7567 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7568 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7569 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7571 state->call = tran_call;
7573 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7574 is so as a sanity check */
7575 if (state->setup_count != 1) {
7577 * Need to have rc=0 for ioctl to get job id for OS/2.
7578 * Network printing will fail if function is not successful.
7579 * Similar function in reply.c will be used if protocol
7580 * is LANMAN1.0 instead of LM1.2X002.
7581 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7582 * outbuf doesn't have to be set(only job id is used).
7584 if ( (state->setup_count == 4)
7585 && (tran_call == TRANSACT2_IOCTL)
7586 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7587 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7588 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7590 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7591 DEBUG(2,("Transaction is %d\n",tran_call));
7593 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7594 END_PROFILE(SMBtrans2);
7599 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7602 if (state->total_data) {
7603 /* Can't use talloc here, the core routines do realloc on the
7604 * params and data. */
7605 state->data = (char *)SMB_MALLOC(state->total_data);
7606 if (state->data == NULL) {
7607 DEBUG(0,("reply_trans2: data malloc fail for %u "
7608 "bytes !\n", (unsigned int)state->total_data));
7610 reply_nterror(req, NT_STATUS_NO_MEMORY);
7611 END_PROFILE(SMBtrans2);
7615 if (dscnt > state->total_data ||
7616 dsoff+dscnt < dsoff) {
7620 if (dsoff > av_size ||
7622 dsoff+dscnt > av_size) {
7626 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7629 if (state->total_param) {
7630 /* Can't use talloc here, the core routines do realloc on the
7631 * params and data. */
7632 state->param = (char *)SMB_MALLOC(state->total_param);
7633 if (state->param == NULL) {
7634 DEBUG(0,("reply_trans: param malloc fail for %u "
7635 "bytes !\n", (unsigned int)state->total_param));
7636 SAFE_FREE(state->data);
7638 reply_nterror(req, NT_STATUS_NO_MEMORY);
7639 END_PROFILE(SMBtrans2);
7643 if (pscnt > state->total_param ||
7644 psoff+pscnt < psoff) {
7648 if (psoff > av_size ||
7650 psoff+pscnt > av_size) {
7654 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7657 state->received_data = dscnt;
7658 state->received_param = pscnt;
7660 if ((state->received_param == state->total_param) &&
7661 (state->received_data == state->total_data)) {
7663 handle_trans2(conn, req, state);
7665 SAFE_FREE(state->data);
7666 SAFE_FREE(state->param);
7668 END_PROFILE(SMBtrans2);
7672 DLIST_ADD(conn->pending_trans, state);
7674 /* We need to send an interim response then receive the rest
7675 of the parameter/data bytes */
7676 reply_outbuf(req, 0, 0);
7677 show_msg((char *)req->outbuf);
7678 END_PROFILE(SMBtrans2);
7683 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7684 SAFE_FREE(state->data);
7685 SAFE_FREE(state->param);
7687 END_PROFILE(SMBtrans2);
7688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7692 /****************************************************************************
7693 Reply to a SMBtranss2
7694 ****************************************************************************/
7696 void reply_transs2(struct smb_request *req)
7698 connection_struct *conn = req->conn;
7699 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7700 struct trans_state *state;
7702 unsigned int av_size;
7704 START_PROFILE(SMBtranss2);
7706 show_msg((char *)req->inbuf);
7709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7710 END_PROFILE(SMBtranss2);
7714 size = smb_len(req->inbuf)+4;
7715 av_size = smb_len(req->inbuf);
7717 for (state = conn->pending_trans; state != NULL;
7718 state = state->next) {
7719 if (state->mid == req->mid) {
7724 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7725 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7726 END_PROFILE(SMBtranss2);
7730 /* Revise state->total_param and state->total_data in case they have
7731 changed downwards */
7733 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7734 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7735 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7736 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7738 pcnt = SVAL(req->inbuf, smb_spscnt);
7739 poff = SVAL(req->inbuf, smb_spsoff);
7740 pdisp = SVAL(req->inbuf, smb_spsdisp);
7742 dcnt = SVAL(req->inbuf, smb_sdscnt);
7743 doff = SVAL(req->inbuf, smb_sdsoff);
7744 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7746 state->received_param += pcnt;
7747 state->received_data += dcnt;
7749 if ((state->received_data > state->total_data) ||
7750 (state->received_param > state->total_param))
7754 if (pdisp > state->total_param ||
7755 pcnt > state->total_param ||
7756 pdisp+pcnt > state->total_param ||
7757 pdisp+pcnt < pdisp) {
7761 if (poff > av_size ||
7763 poff+pcnt > av_size ||
7768 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7773 if (ddisp > state->total_data ||
7774 dcnt > state->total_data ||
7775 ddisp+dcnt > state->total_data ||
7776 ddisp+dcnt < ddisp) {
7780 if (ddisp > av_size ||
7782 ddisp+dcnt > av_size ||
7783 ddisp+dcnt < ddisp) {
7787 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7791 if ((state->received_param < state->total_param) ||
7792 (state->received_data < state->total_data)) {
7793 END_PROFILE(SMBtranss2);
7798 * construct_reply_common will copy smb_com from inbuf to
7799 * outbuf. SMBtranss2 is wrong here.
7801 SCVAL(req->inbuf,smb_com,SMBtrans2);
7803 handle_trans2(conn, req, state);
7805 DLIST_REMOVE(conn->pending_trans, state);
7806 SAFE_FREE(state->data);
7807 SAFE_FREE(state->param);
7810 END_PROFILE(SMBtranss2);
7815 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7816 DLIST_REMOVE(conn->pending_trans, state);
7817 SAFE_FREE(state->data);
7818 SAFE_FREE(state->param);
7820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7821 END_PROFILE(SMBtranss2);