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/>.
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 #define DIR_ENTRY_SAFETY_MARGIN 4096
34 static char *store_file_unix_basic(connection_struct *conn,
37 const SMB_STRUCT_STAT *psbuf);
39 static char *store_file_unix_basic_info2(connection_struct *conn,
42 const SMB_STRUCT_STAT *psbuf);
44 /********************************************************************
45 Roundup a value to the nearest allocation roundup size boundary.
46 Only do this for Windows clients.
47 ********************************************************************/
49 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
51 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
53 /* Only roundup for Windows clients. */
54 enum remote_arch_types ra_type = get_remote_arch();
55 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
56 val = SMB_ROUNDUP(val,rval);
61 /****************************************************************************
62 Utility functions for dealing with extended attributes.
63 ****************************************************************************/
65 /****************************************************************************
66 Refuse to allow clients to overwrite our private xattrs.
67 ****************************************************************************/
69 static bool samba_private_attr_name(const char *unix_ea_name)
71 static const char * const prohibited_ea_names[] = {
72 SAMBA_POSIX_INHERITANCE_EA_NAME,
73 SAMBA_XATTR_DOS_ATTRIB,
79 for (i = 0; prohibited_ea_names[i]; i++) {
80 if (strequal( prohibited_ea_names[i], unix_ea_name))
83 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
84 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
90 /****************************************************************************
91 Get one EA value. Fill in a struct ea_struct.
92 ****************************************************************************/
94 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
95 files_struct *fsp, const char *fname,
96 const char *ea_name, struct ea_struct *pea)
98 /* Get the value of this xattr. Max size is 64k. */
99 size_t attr_size = 256;
105 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
107 return NT_STATUS_NO_MEMORY;
110 if (fsp && fsp->fh->fd != -1) {
111 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
113 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
116 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
122 return map_nt_error_from_unix(errno);
125 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
126 dump_data(10, (uint8 *)val, sizeret);
129 if (strnequal(ea_name, "user.", 5)) {
130 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
132 pea->name = talloc_strdup(mem_ctx, ea_name);
134 if (pea->name == NULL) {
136 return NT_STATUS_NO_MEMORY;
138 pea->value.data = (unsigned char *)val;
139 pea->value.length = (size_t)sizeret;
143 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
144 files_struct *fsp, const char *fname,
145 char ***pnames, size_t *pnum_names)
147 /* Get a list of all xattrs. Max namesize is 64k. */
148 size_t ea_namelist_size = 1024;
149 char *ea_namelist = NULL;
154 ssize_t sizeret = -1;
156 if (!lp_ea_support(SNUM(conn))) {
163 * TALLOC the result early to get the talloc hierarchy right.
166 names = TALLOC_ARRAY(mem_ctx, char *, 1);
168 DEBUG(0, ("talloc failed\n"));
169 return NT_STATUS_NO_MEMORY;
172 while (ea_namelist_size <= 65536) {
174 ea_namelist = TALLOC_REALLOC_ARRAY(
175 names, ea_namelist, char, ea_namelist_size);
176 if (ea_namelist == NULL) {
177 DEBUG(0, ("talloc failed\n"));
179 return NT_STATUS_NO_MEMORY;
182 if (fsp && fsp->fh->fd != -1) {
183 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
186 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
190 if ((sizeret == -1) && (errno == ERANGE)) {
191 ea_namelist_size *= 2;
200 return map_nt_error_from_unix(errno);
203 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
204 (unsigned int)sizeret));
214 * Ensure the result is 0-terminated
217 if (ea_namelist[sizeret-1] != '\0') {
219 return NT_STATUS_INTERNAL_ERROR;
227 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
231 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
233 DEBUG(0, ("talloc failed\n"));
235 return NT_STATUS_NO_MEMORY;
241 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
242 names[num_names++] = p;
246 *pnum_names = num_names;
250 /****************************************************************************
251 Return a linked list of the total EA's. Plus the total size
252 ****************************************************************************/
254 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
255 const char *fname, size_t *pea_total_len)
257 /* Get a list of all xattrs. Max namesize is 64k. */
260 struct ea_list *ea_list_head = NULL;
265 if (!lp_ea_support(SNUM(conn))) {
269 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
272 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
276 for (i=0; i<num_names; i++) {
277 struct ea_list *listp;
280 if (strnequal(names[i], "system.", 7)
281 || samba_private_attr_name(names[i]))
284 listp = TALLOC_P(mem_ctx, struct ea_list);
289 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
295 push_ascii_fstring(dos_ea_name, listp->ea.name);
298 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
300 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
301 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
302 (unsigned int)listp->ea.value.length));
304 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
308 /* Add on 4 for total length. */
309 if (*pea_total_len) {
313 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
314 (unsigned int)*pea_total_len));
319 /****************************************************************************
320 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
322 ****************************************************************************/
324 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
325 connection_struct *conn, struct ea_list *ea_list)
327 unsigned int ret_data_size = 4;
330 SMB_ASSERT(total_data_size >= 4);
332 if (!lp_ea_support(SNUM(conn))) {
337 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
340 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
341 dos_namelen = strlen(dos_ea_name);
342 if (dos_namelen > 255 || dos_namelen == 0) {
345 if (ea_list->ea.value.length > 65535) {
348 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
352 /* We know we have room. */
353 SCVAL(p,0,ea_list->ea.flags);
354 SCVAL(p,1,dos_namelen);
355 SSVAL(p,2,ea_list->ea.value.length);
356 fstrcpy(p+4, dos_ea_name);
357 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
359 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
360 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
363 ret_data_size = PTR_DIFF(p, pdata);
364 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
365 SIVAL(pdata,0,ret_data_size);
366 return ret_data_size;
369 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
371 size_t total_ea_len = 0;
372 TALLOC_CTX *mem_ctx = NULL;
374 if (!lp_ea_support(SNUM(conn))) {
377 mem_ctx = talloc_tos();
378 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
382 /****************************************************************************
383 Ensure the EA name is case insensitive by matching any existing EA name.
384 ****************************************************************************/
386 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
389 TALLOC_CTX *mem_ctx = talloc_tos();
390 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
392 for (; ea_list; ea_list = ea_list->next) {
393 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
394 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
395 &unix_ea_name[5], ea_list->ea.name));
396 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
402 /****************************************************************************
403 Set or delete an extended attribute.
404 ****************************************************************************/
406 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
408 if (!lp_ea_support(SNUM(conn))) {
409 return NT_STATUS_EAS_NOT_SUPPORTED;
412 for (;ea_list; ea_list = ea_list->next) {
414 fstring unix_ea_name;
416 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
417 fstrcat(unix_ea_name, ea_list->ea.name);
419 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
421 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
423 if (samba_private_attr_name(unix_ea_name)) {
424 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
425 return NT_STATUS_ACCESS_DENIED;
428 if (ea_list->ea.value.length == 0) {
429 /* Remove the attribute. */
430 if (fsp && (fsp->fh->fd != -1)) {
431 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
432 unix_ea_name, fsp->fsp_name));
433 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
435 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
436 unix_ea_name, fname));
437 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
440 /* Removing a non existent attribute always succeeds. */
441 if (ret == -1 && errno == ENOATTR) {
442 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
448 if (fsp && (fsp->fh->fd != -1)) {
449 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
450 unix_ea_name, fsp->fsp_name));
451 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
452 ea_list->ea.value.data, ea_list->ea.value.length, 0);
454 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
455 unix_ea_name, fname));
456 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
457 ea_list->ea.value.data, ea_list->ea.value.length, 0);
463 if (errno == ENOTSUP) {
464 return NT_STATUS_EAS_NOT_SUPPORTED;
467 return map_nt_error_from_unix(errno);
473 /****************************************************************************
474 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
475 ****************************************************************************/
477 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
479 struct ea_list *ea_list_head = NULL;
480 size_t converted_size, offset = 0;
482 while (offset + 2 < data_size) {
483 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
484 unsigned int namelen = CVAL(pdata,offset);
486 offset++; /* Go past the namelen byte. */
488 /* integer wrap paranioa. */
489 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
490 (offset > data_size) || (namelen > data_size) ||
491 (offset + namelen >= data_size)) {
494 /* Ensure the name is null terminated. */
495 if (pdata[offset + namelen] != '\0') {
498 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
500 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
501 "failed: %s", strerror(errno)));
507 offset += (namelen + 1); /* Go past the name + terminating zero. */
508 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
509 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
515 /****************************************************************************
516 Read one EA list entry from the buffer.
517 ****************************************************************************/
519 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
521 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
523 unsigned int namelen;
524 size_t converted_size;
534 eal->ea.flags = CVAL(pdata,0);
535 namelen = CVAL(pdata,1);
536 val_len = SVAL(pdata,2);
538 if (4 + namelen + 1 + val_len > data_size) {
542 /* Ensure the name is null terminated. */
543 if (pdata[namelen + 4] != '\0') {
546 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
547 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
554 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
555 if (!eal->ea.value.data) {
559 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
561 /* Ensure we're null terminated just in case we print the value. */
562 eal->ea.value.data[val_len] = '\0';
563 /* But don't count the null. */
564 eal->ea.value.length--;
567 *pbytes_used = 4 + namelen + 1 + val_len;
570 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
571 dump_data(10, eal->ea.value.data, eal->ea.value.length);
576 /****************************************************************************
577 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
578 ****************************************************************************/
580 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
582 struct ea_list *ea_list_head = NULL;
584 size_t bytes_used = 0;
586 while (offset < data_size) {
587 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
593 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
594 offset += bytes_used;
600 /****************************************************************************
601 Count the total EA size needed.
602 ****************************************************************************/
604 static size_t ea_list_size(struct ea_list *ealist)
607 struct ea_list *listp;
610 for (listp = ealist; listp; listp = listp->next) {
611 push_ascii_fstring(dos_ea_name, listp->ea.name);
612 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
614 /* Add on 4 for total length. */
622 /****************************************************************************
623 Return a union of EA's from a file list and a list of names.
624 The TALLOC context for the two lists *MUST* be identical as we steal
625 memory from one list to add to another. JRA.
626 ****************************************************************************/
628 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
630 struct ea_list *nlistp, *flistp;
632 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
633 for (flistp = file_list; flistp; flistp = flistp->next) {
634 if (strequal(nlistp->ea.name, flistp->ea.name)) {
640 /* Copy the data from this entry. */
641 nlistp->ea.flags = flistp->ea.flags;
642 nlistp->ea.value = flistp->ea.value;
645 nlistp->ea.flags = 0;
646 ZERO_STRUCT(nlistp->ea.value);
650 *total_ea_len = ea_list_size(name_list);
654 /****************************************************************************
655 Send the required number of replies back.
656 We assume all fields other than the data fields are
657 set correctly for the type of call.
658 HACK ! Always assumes smb_setup field is zero.
659 ****************************************************************************/
661 void send_trans2_replies(connection_struct *conn,
662 struct smb_request *req,
669 /* As we are using a protocol > LANMAN1 then the max_send
670 variable must have been set in the sessetupX call.
671 This takes precedence over the max_xmit field in the
672 global struct. These different max_xmit variables should
673 be merged as this is now too confusing */
675 int data_to_send = datasize;
676 int params_to_send = paramsize;
678 const char *pp = params;
679 const char *pd = pdata;
680 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
681 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
682 int data_alignment_offset = 0;
683 bool overflow = False;
685 /* Modify the data_to_send and datasize and set the error if
686 we're trying to send more than max_data_bytes. We still send
687 the part of the packet(s) that fit. Strange, but needed
690 if (max_data_bytes > 0 && datasize > max_data_bytes) {
691 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
692 max_data_bytes, datasize ));
693 datasize = data_to_send = max_data_bytes;
697 /* If there genuinely are no parameters or data to send just send the empty packet */
699 if(params_to_send == 0 && data_to_send == 0) {
700 reply_outbuf(req, 10, 0);
701 show_msg((char *)req->outbuf);
705 /* When sending params and data ensure that both are nicely aligned */
706 /* Only do this alignment when there is also data to send - else
707 can cause NT redirector problems. */
709 if (((params_to_send % 4) != 0) && (data_to_send != 0))
710 data_alignment_offset = 4 - (params_to_send % 4);
712 /* Space is bufsize minus Netbios over TCP header minus SMB header */
713 /* The alignment_offset is to align the param bytes on an even byte
714 boundary. NT 4.0 Beta needs this to work correctly. */
716 useable_space = max_send - (smb_size
719 + data_alignment_offset);
721 if (useable_space < 0) {
722 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
723 "= %d!!!", useable_space));
724 exit_server_cleanly("send_trans2_replies: Not enough space");
727 while (params_to_send || data_to_send) {
728 /* Calculate whether we will totally or partially fill this packet */
730 total_sent_thistime = params_to_send + data_to_send;
732 /* We can never send more than useable_space */
734 * Note that 'useable_space' does not include the alignment offsets,
735 * but we must include the alignment offsets in the calculation of
736 * the length of the data we send over the wire, as the alignment offsets
737 * are sent here. Fix from Marc_Jacobsen@hp.com.
740 total_sent_thistime = MIN(total_sent_thistime, useable_space);
742 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
743 + data_alignment_offset);
746 * We might have SMBtrans2s in req which was transferred to
747 * the outbuf, fix that.
749 SCVAL(req->outbuf, smb_com, SMBtrans2);
751 /* Set total params and data to be sent */
752 SSVAL(req->outbuf,smb_tprcnt,paramsize);
753 SSVAL(req->outbuf,smb_tdrcnt,datasize);
755 /* Calculate how many parameters and data we can fit into
756 * this packet. Parameters get precedence
759 params_sent_thistime = MIN(params_to_send,useable_space);
760 data_sent_thistime = useable_space - params_sent_thistime;
761 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
763 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
765 /* smb_proff is the offset from the start of the SMB header to the
766 parameter bytes, however the first 4 bytes of outbuf are
767 the Netbios over TCP header. Thus use smb_base() to subtract
768 them from the calculation */
770 SSVAL(req->outbuf,smb_proff,
771 ((smb_buf(req->outbuf)+alignment_offset)
772 - smb_base(req->outbuf)));
774 if(params_sent_thistime == 0)
775 SSVAL(req->outbuf,smb_prdisp,0);
777 /* Absolute displacement of param bytes sent in this packet */
778 SSVAL(req->outbuf,smb_prdisp,pp - params);
780 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
781 if(data_sent_thistime == 0) {
782 SSVAL(req->outbuf,smb_droff,0);
783 SSVAL(req->outbuf,smb_drdisp, 0);
785 /* The offset of the data bytes is the offset of the
786 parameter bytes plus the number of parameters being sent this time */
787 SSVAL(req->outbuf, smb_droff,
788 ((smb_buf(req->outbuf)+alignment_offset)
789 - smb_base(req->outbuf))
790 + params_sent_thistime + data_alignment_offset);
791 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
794 /* Initialize the padding for alignment */
796 if (alignment_offset != 0) {
797 memset(smb_buf(req->outbuf), 0, alignment_offset);
800 /* Copy the param bytes into the packet */
802 if(params_sent_thistime) {
803 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
804 params_sent_thistime);
807 /* Copy in the data bytes */
808 if(data_sent_thistime) {
809 if (data_alignment_offset != 0) {
810 memset((smb_buf(req->outbuf)+alignment_offset+
811 params_sent_thistime), 0,
812 data_alignment_offset);
814 memcpy(smb_buf(req->outbuf)+alignment_offset
815 +params_sent_thistime+data_alignment_offset,
816 pd,data_sent_thistime);
819 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
820 params_sent_thistime, data_sent_thistime, useable_space));
821 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
822 params_to_send, data_to_send, paramsize, datasize));
825 error_packet_set((char *)req->outbuf,
826 ERRDOS,ERRbufferoverflow,
827 STATUS_BUFFER_OVERFLOW,
831 /* Send the packet */
832 show_msg((char *)req->outbuf);
833 if (!srv_send_smb(smbd_server_fd(),
836 IS_CONN_ENCRYPTED(conn),
838 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
840 TALLOC_FREE(req->outbuf);
842 pp += params_sent_thistime;
843 pd += data_sent_thistime;
845 params_to_send -= params_sent_thistime;
846 data_to_send -= data_sent_thistime;
849 if(params_to_send < 0 || data_to_send < 0) {
850 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
851 params_to_send, data_to_send));
859 /****************************************************************************
860 Reply to a TRANSACT2_OPEN.
861 ****************************************************************************/
863 static void call_trans2open(connection_struct *conn,
864 struct smb_request *req,
865 char **pparams, int total_params,
866 char **ppdata, int total_data,
867 unsigned int max_data_bytes)
869 char *params = *pparams;
870 char *pdata = *ppdata;
875 bool return_additional_info;
886 SMB_STRUCT_STAT sbuf;
889 struct ea_list *ea_list = NULL;
894 uint32 create_disposition;
895 uint32 create_options = 0;
896 TALLOC_CTX *ctx = talloc_tos();
898 SET_STAT_INVALID(sbuf);
901 * Ensure we have enough parameters to perform the operation.
904 if (total_params < 29) {
905 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
909 flags = SVAL(params, 0);
910 deny_mode = SVAL(params, 2);
911 open_attr = SVAL(params,6);
912 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
913 if (oplock_request) {
914 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
918 return_additional_info = BITSETW(params,0);
919 open_sattr = SVAL(params, 4);
920 open_time = make_unix_date3(params+8);
922 open_ofun = SVAL(params,12);
923 open_size = IVAL(params,14);
927 reply_doserror(req, ERRSRV, ERRaccess);
931 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
932 total_params - 28, STR_TERMINATE,
934 if (!NT_STATUS_IS_OK(status)) {
935 reply_nterror(req, status);
939 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
940 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
941 (unsigned int)open_ofun, open_size));
943 if (open_ofun == 0) {
944 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
948 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
953 reply_doserror(req, ERRDOS, ERRbadaccess);
957 /* Any data in this call is an EA list. */
958 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
959 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
963 if (total_data != 4) {
964 if (total_data < 10) {
965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
969 if (IVAL(pdata,0) > total_data) {
970 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
971 IVAL(pdata,0), (unsigned int)total_data));
972 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
976 ea_list = read_ea_list(talloc_tos(), pdata + 4,
979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 } else if (IVAL(pdata,0) != 4) {
983 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
987 status = SMB_VFS_CREATE_FILE(
990 0, /* root_dir_fid */
992 CFF_DOS_PATH, /* create_file_flags */
993 access_mask, /* access_mask */
994 share_mode, /* share_access */
995 create_disposition, /* create_disposition*/
996 create_options, /* create_options */
997 open_attr, /* file_attributes */
998 oplock_request, /* oplock_request */
999 open_size, /* allocation_size */
1001 ea_list, /* ea_list */
1003 &smb_action, /* pinfo */
1006 if (!NT_STATUS_IS_OK(status)) {
1007 if (open_was_deferred(req->mid)) {
1008 /* We have re-scheduled this call. */
1011 reply_openerror(req, status);
1015 size = get_file_size_stat(&sbuf);
1016 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1017 mtime = sbuf.st_mtime;
1018 inode = sbuf.st_ino;
1020 close_file(req, fsp, ERROR_CLOSE);
1021 reply_doserror(req, ERRDOS,ERRnoaccess);
1025 /* Realloc the size of parameters and data we will return */
1026 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1027 if(*pparams == NULL ) {
1028 reply_nterror(req, NT_STATUS_NO_MEMORY);
1033 SSVAL(params,0,fsp->fnum);
1034 SSVAL(params,2,fattr);
1035 srv_put_dos_date2(params,4, mtime);
1036 SIVAL(params,8, (uint32)size);
1037 SSVAL(params,12,deny_mode);
1038 SSVAL(params,14,0); /* open_type - file or directory. */
1039 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1041 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1042 smb_action |= EXTENDED_OPLOCK_GRANTED;
1045 SSVAL(params,18,smb_action);
1048 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1050 SIVAL(params,20,inode);
1051 SSVAL(params,24,0); /* Padding. */
1053 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1054 SIVAL(params, 26, ea_size);
1056 SIVAL(params, 26, 0);
1059 /* Send the required number of replies */
1060 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1063 /*********************************************************
1064 Routine to check if a given string matches exactly.
1065 as a special case a mask of "." does NOT match. That
1066 is required for correct wildcard semantics
1067 Case can be significant or not.
1068 **********************************************************/
1070 static bool exact_match(connection_struct *conn,
1074 if (mask[0] == '.' && mask[1] == 0)
1076 if (dptr_has_wild(conn->dirptr)) {
1079 if (conn->case_sensitive)
1080 return strcmp(str,mask)==0;
1082 return StrCaseCmp(str,mask) == 0;
1085 /****************************************************************************
1086 Return the filetype for UNIX extensions.
1087 ****************************************************************************/
1089 static uint32 unix_filetype(mode_t mode)
1092 return UNIX_TYPE_FILE;
1093 else if(S_ISDIR(mode))
1094 return UNIX_TYPE_DIR;
1096 else if(S_ISLNK(mode))
1097 return UNIX_TYPE_SYMLINK;
1100 else if(S_ISCHR(mode))
1101 return UNIX_TYPE_CHARDEV;
1104 else if(S_ISBLK(mode))
1105 return UNIX_TYPE_BLKDEV;
1108 else if(S_ISFIFO(mode))
1109 return UNIX_TYPE_FIFO;
1112 else if(S_ISSOCK(mode))
1113 return UNIX_TYPE_SOCKET;
1116 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1117 return UNIX_TYPE_UNKNOWN;
1120 /****************************************************************************
1121 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1122 ****************************************************************************/
1124 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1126 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1127 SMB_STRUCT_STAT *psbuf,
1129 enum perm_type ptype,
1134 if (perms == SMB_MODE_NO_CHANGE) {
1135 if (!VALID_STAT(*psbuf)) {
1136 return NT_STATUS_INVALID_PARAMETER;
1138 *ret_perms = psbuf->st_mode;
1139 return NT_STATUS_OK;
1143 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1144 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1145 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1146 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1147 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1148 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1149 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1150 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1151 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1153 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1156 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1159 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1164 /* Apply mode mask */
1165 ret &= lp_create_mask(SNUM(conn));
1166 /* Add in force bits */
1167 ret |= lp_force_create_mode(SNUM(conn));
1170 ret &= lp_dir_mask(SNUM(conn));
1171 /* Add in force bits */
1172 ret |= lp_force_dir_mode(SNUM(conn));
1174 case PERM_EXISTING_FILE:
1175 /* Apply mode mask */
1176 ret &= lp_security_mask(SNUM(conn));
1177 /* Add in force bits */
1178 ret |= lp_force_security_mode(SNUM(conn));
1180 case PERM_EXISTING_DIR:
1181 /* Apply mode mask */
1182 ret &= lp_dir_security_mask(SNUM(conn));
1183 /* Add in force bits */
1184 ret |= lp_force_dir_security_mode(SNUM(conn));
1189 return NT_STATUS_OK;
1192 /****************************************************************************
1193 Needed to show the msdfs symlinks as directories. Modifies psbuf
1194 to be a directory if it's a msdfs link.
1195 ****************************************************************************/
1197 static bool check_msdfs_link(connection_struct *conn,
1198 const char *pathname,
1199 SMB_STRUCT_STAT *psbuf)
1201 int saved_errno = errno;
1202 if(lp_host_msdfs() &&
1203 lp_msdfs_root(SNUM(conn)) &&
1204 is_msdfs_link(conn, pathname, psbuf)) {
1206 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1209 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1210 errno = saved_errno;
1213 errno = saved_errno;
1218 /****************************************************************************
1219 Get a level dependent lanman2 dir entry.
1220 ****************************************************************************/
1222 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1223 connection_struct *conn,
1225 const char *path_mask,
1228 int requires_resume_key,
1234 int space_remaining,
1236 bool *got_exact_match,
1237 int *last_entry_off,
1238 struct ea_list *name_list)
1242 SMB_STRUCT_STAT sbuf;
1243 const char *mask = NULL;
1244 char *pathreal = NULL;
1245 const char *fname = NULL;
1246 char *p, *q, *pdata = *ppdata;
1250 SMB_OFF_T file_size = 0;
1251 uint64_t allocation_size = 0;
1253 struct timespec mdate_ts, adate_ts, create_date_ts;
1254 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1256 char *last_entry_ptr;
1258 uint32 nt_extmode; /* Used for NT connections instead of mode */
1259 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1260 bool check_mangled_names = lp_manglednames(conn->params);
1261 char mangled_name[13]; /* mangled 8.3 name. */
1263 *out_of_space = False;
1264 *got_exact_match = False;
1266 ZERO_STRUCT(mdate_ts);
1267 ZERO_STRUCT(adate_ts);
1268 ZERO_STRUCT(create_date_ts);
1270 if (!conn->dirptr) {
1274 p = strrchr_m(path_mask,'/');
1277 mask = talloc_strdup(ctx,"*.*");
1287 bool ms_dfs_link = False;
1289 /* Needed if we run out of space */
1290 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1291 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1294 * Due to bugs in NT client redirectors we are not using
1295 * resume keys any more - set them to zero.
1296 * Check out the related comments in findfirst/findnext.
1302 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1303 (long)conn->dirptr,curr_dirpos));
1310 * fname may get mangled, dname is never mangled.
1311 * Whenever we're accessing the filesystem we use
1312 * pathreal which is composed from dname.
1318 /* Mangle fname if it's an illegal name. */
1319 if (mangle_must_mangle(dname,conn->params)) {
1320 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1321 continue; /* Error - couldn't mangle. */
1323 fname = mangled_name;
1326 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1327 got_match = mask_match(fname, mask, conn->case_sensitive);
1330 if(!got_match && check_mangled_names &&
1331 !mangle_is_8_3(fname, False, conn->params)) {
1333 * It turns out that NT matches wildcards against
1334 * both long *and* short names. This may explain some
1335 * of the wildcard wierdness from old DOS clients
1336 * that some people have been seeing.... JRA.
1338 /* Force the mangling into 8.3. */
1339 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1340 continue; /* Error - couldn't mangle. */
1343 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1344 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1349 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1351 if (dont_descend && !isdots) {
1357 pathreal = talloc_asprintf(ctx,
1362 pathreal = talloc_asprintf(ctx,
1372 if (INFO_LEVEL_IS_UNIX(info_level)) {
1373 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1374 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1375 pathreal,strerror(errno)));
1376 TALLOC_FREE(pathreal);
1379 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1380 /* Needed to show the msdfs symlinks as
1383 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1385 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1386 pathreal,strerror(errno)));
1387 TALLOC_FREE(pathreal);
1393 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1395 mode = dos_mode(conn,pathreal,&sbuf);
1398 if (!dir_check_ftype(conn,mode,dirtype)) {
1399 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1400 TALLOC_FREE(pathreal);
1404 if (!(mode & aDIR)) {
1405 file_size = get_file_size_stat(&sbuf);
1407 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1409 mdate_ts = get_mtimespec(&sbuf);
1410 adate_ts = get_atimespec(&sbuf);
1411 create_date_ts = get_create_timespec(&sbuf,
1412 lp_fake_dir_create_times(SNUM(conn)));
1414 if (ask_sharemode) {
1415 struct timespec write_time_ts;
1416 struct file_id fileid;
1418 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1419 get_file_infos(fileid, NULL, &write_time_ts);
1420 if (!null_timespec(write_time_ts)) {
1421 mdate_ts = write_time_ts;
1425 if (lp_dos_filetime_resolution(SNUM(conn))) {
1426 dos_filetime_timespec(&create_date_ts);
1427 dos_filetime_timespec(&mdate_ts);
1428 dos_filetime_timespec(&adate_ts);
1431 create_date = convert_timespec_to_time_t(create_date_ts);
1432 mdate = convert_timespec_to_time_t(mdate_ts);
1433 adate = convert_timespec_to_time_t(adate_ts);
1435 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1440 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1447 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1449 switch (info_level) {
1450 case SMB_FIND_INFO_STANDARD:
1451 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1452 if(requires_resume_key) {
1456 srv_put_dos_date2(p,0,create_date);
1457 srv_put_dos_date2(p,4,adate);
1458 srv_put_dos_date2(p,8,mdate);
1459 SIVAL(p,12,(uint32)file_size);
1460 SIVAL(p,16,(uint32)allocation_size);
1464 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1465 p += ucs2_align(base_data, p, 0);
1467 len = srvstr_push(base_data, flags2, p,
1468 fname, PTR_DIFF(end_data, p),
1470 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1472 SCVAL(nameptr, -1, len - 2);
1474 SCVAL(nameptr, -1, 0);
1478 SCVAL(nameptr, -1, len - 1);
1480 SCVAL(nameptr, -1, 0);
1486 case SMB_FIND_EA_SIZE:
1487 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1488 if(requires_resume_key) {
1492 srv_put_dos_date2(p,0,create_date);
1493 srv_put_dos_date2(p,4,adate);
1494 srv_put_dos_date2(p,8,mdate);
1495 SIVAL(p,12,(uint32)file_size);
1496 SIVAL(p,16,(uint32)allocation_size);
1499 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1500 SIVAL(p,22,ea_size); /* Extended attributes */
1504 len = srvstr_push(base_data, flags2,
1505 p, fname, PTR_DIFF(end_data, p),
1506 STR_TERMINATE | STR_NOALIGN);
1507 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1520 SCVAL(nameptr,0,len);
1522 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1525 case SMB_FIND_EA_LIST:
1527 struct ea_list *file_list = NULL;
1530 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1534 if(requires_resume_key) {
1538 srv_put_dos_date2(p,0,create_date);
1539 srv_put_dos_date2(p,4,adate);
1540 srv_put_dos_date2(p,8,mdate);
1541 SIVAL(p,12,(uint32)file_size);
1542 SIVAL(p,16,(uint32)allocation_size);
1544 p += 22; /* p now points to the EA area. */
1546 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1547 name_list = ea_list_union(name_list, file_list, &ea_len);
1549 /* We need to determine if this entry will fit in the space available. */
1550 /* Max string size is 255 bytes. */
1551 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1552 /* Move the dirptr back to prev_dirpos */
1553 dptr_SeekDir(conn->dirptr, prev_dirpos);
1554 *out_of_space = True;
1555 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1556 return False; /* Not finished - just out of space */
1559 /* Push the ea_data followed by the name. */
1560 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1562 len = srvstr_push(base_data, flags2,
1563 p + 1, fname, PTR_DIFF(end_data, p+1),
1564 STR_TERMINATE | STR_NOALIGN);
1565 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578 SCVAL(nameptr,0,len);
1580 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1584 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1585 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1586 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1588 SIVAL(p,0,reskey); p += 4;
1589 put_long_date_timespec(p,create_date_ts); p += 8;
1590 put_long_date_timespec(p,adate_ts); p += 8;
1591 put_long_date_timespec(p,mdate_ts); p += 8;
1592 put_long_date_timespec(p,mdate_ts); p += 8;
1593 SOFF_T(p,0,file_size); p += 8;
1594 SOFF_T(p,0,allocation_size); p += 8;
1595 SIVAL(p,0,nt_extmode); p += 4;
1596 q = p; p += 4; /* q is placeholder for name length. */
1598 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1599 SIVAL(p,0,ea_size); /* Extended attributes */
1602 /* Clear the short name buffer. This is
1603 * IMPORTANT as not doing so will trigger
1604 * a Win2k client bug. JRA.
1606 if (!was_8_3 && check_mangled_names) {
1607 if (!name_to_8_3(fname,mangled_name,True,
1609 /* Error - mangle failed ! */
1610 memset(mangled_name,'\0',12);
1612 mangled_name[12] = 0;
1613 len = srvstr_push(base_data, flags2,
1614 p+2, mangled_name, 24,
1615 STR_UPPER|STR_UNICODE);
1617 memset(p + 2 + len,'\0',24 - len);
1624 len = srvstr_push(base_data, flags2, p,
1625 fname, PTR_DIFF(end_data, p),
1626 STR_TERMINATE_ASCII);
1629 SIVAL(p,0,0); /* Ensure any padding is null. */
1630 len = PTR_DIFF(p, pdata);
1631 len = (len + 3) & ~3;
1636 case SMB_FIND_FILE_DIRECTORY_INFO:
1637 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1639 SIVAL(p,0,reskey); p += 4;
1640 put_long_date_timespec(p,create_date_ts); p += 8;
1641 put_long_date_timespec(p,adate_ts); p += 8;
1642 put_long_date_timespec(p,mdate_ts); p += 8;
1643 put_long_date_timespec(p,mdate_ts); p += 8;
1644 SOFF_T(p,0,file_size); p += 8;
1645 SOFF_T(p,0,allocation_size); p += 8;
1646 SIVAL(p,0,nt_extmode); p += 4;
1647 len = srvstr_push(base_data, flags2,
1648 p + 4, fname, PTR_DIFF(end_data, p+4),
1649 STR_TERMINATE_ASCII);
1652 SIVAL(p,0,0); /* Ensure any padding is null. */
1653 len = PTR_DIFF(p, pdata);
1654 len = (len + 3) & ~3;
1659 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1660 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1662 SIVAL(p,0,reskey); p += 4;
1663 put_long_date_timespec(p,create_date_ts); p += 8;
1664 put_long_date_timespec(p,adate_ts); p += 8;
1665 put_long_date_timespec(p,mdate_ts); p += 8;
1666 put_long_date_timespec(p,mdate_ts); p += 8;
1667 SOFF_T(p,0,file_size); p += 8;
1668 SOFF_T(p,0,allocation_size); p += 8;
1669 SIVAL(p,0,nt_extmode); p += 4;
1670 q = p; p += 4; /* q is placeholder for name length. */
1672 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1673 SIVAL(p,0,ea_size); /* Extended attributes */
1676 len = srvstr_push(base_data, flags2, p,
1677 fname, PTR_DIFF(end_data, p),
1678 STR_TERMINATE_ASCII);
1682 SIVAL(p,0,0); /* Ensure any padding is null. */
1683 len = PTR_DIFF(p, pdata);
1684 len = (len + 3) & ~3;
1689 case SMB_FIND_FILE_NAMES_INFO:
1690 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1692 SIVAL(p,0,reskey); p += 4;
1694 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1695 acl on a dir (tridge) */
1696 len = srvstr_push(base_data, flags2, p,
1697 fname, PTR_DIFF(end_data, p),
1698 STR_TERMINATE_ASCII);
1701 SIVAL(p,0,0); /* Ensure any padding is null. */
1702 len = PTR_DIFF(p, pdata);
1703 len = (len + 3) & ~3;
1708 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1709 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1711 SIVAL(p,0,reskey); p += 4;
1712 put_long_date_timespec(p,create_date_ts); p += 8;
1713 put_long_date_timespec(p,adate_ts); p += 8;
1714 put_long_date_timespec(p,mdate_ts); p += 8;
1715 put_long_date_timespec(p,mdate_ts); p += 8;
1716 SOFF_T(p,0,file_size); p += 8;
1717 SOFF_T(p,0,allocation_size); p += 8;
1718 SIVAL(p,0,nt_extmode); p += 4;
1719 q = p; p += 4; /* q is placeholder for name length. */
1721 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1722 SIVAL(p,0,ea_size); /* Extended attributes */
1725 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1726 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1727 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1728 len = srvstr_push(base_data, flags2, p,
1729 fname, PTR_DIFF(end_data, p),
1730 STR_TERMINATE_ASCII);
1733 SIVAL(p,0,0); /* Ensure any padding is null. */
1734 len = PTR_DIFF(p, pdata);
1735 len = (len + 3) & ~3;
1740 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1741 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1742 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1744 SIVAL(p,0,reskey); p += 4;
1745 put_long_date_timespec(p,create_date_ts); p += 8;
1746 put_long_date_timespec(p,adate_ts); p += 8;
1747 put_long_date_timespec(p,mdate_ts); p += 8;
1748 put_long_date_timespec(p,mdate_ts); p += 8;
1749 SOFF_T(p,0,file_size); p += 8;
1750 SOFF_T(p,0,allocation_size); p += 8;
1751 SIVAL(p,0,nt_extmode); p += 4;
1752 q = p; p += 4; /* q is placeholder for name length */
1754 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1755 SIVAL(p,0,ea_size); /* Extended attributes */
1758 /* Clear the short name buffer. This is
1759 * IMPORTANT as not doing so will trigger
1760 * a Win2k client bug. JRA.
1762 if (!was_8_3 && check_mangled_names) {
1763 if (!name_to_8_3(fname,mangled_name,True,
1765 /* Error - mangle failed ! */
1766 memset(mangled_name,'\0',12);
1768 mangled_name[12] = 0;
1769 len = srvstr_push(base_data, flags2,
1770 p+2, mangled_name, 24,
1771 STR_UPPER|STR_UNICODE);
1774 memset(p + 2 + len,'\0',24 - len);
1781 SSVAL(p,0,0); p += 2; /* Reserved ? */
1782 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1783 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1784 len = srvstr_push(base_data, flags2, p,
1785 fname, PTR_DIFF(end_data, p),
1786 STR_TERMINATE_ASCII);
1789 SIVAL(p,0,0); /* Ensure any padding is null. */
1790 len = PTR_DIFF(p, pdata);
1791 len = (len + 3) & ~3;
1796 /* CIFS UNIX Extension. */
1798 case SMB_FIND_FILE_UNIX:
1799 case SMB_FIND_FILE_UNIX_INFO2:
1801 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1803 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1805 if (info_level == SMB_FIND_FILE_UNIX) {
1806 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1807 p = store_file_unix_basic(conn, p,
1809 len = srvstr_push(base_data, flags2, p,
1810 fname, PTR_DIFF(end_data, p),
1813 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1814 p = store_file_unix_basic_info2(conn, p,
1818 len = srvstr_push(base_data, flags2, p, fname,
1819 PTR_DIFF(end_data, p), 0);
1820 SIVAL(nameptr, 0, len);
1824 SIVAL(p,0,0); /* Ensure any padding is null. */
1826 len = PTR_DIFF(p, pdata);
1827 len = (len + 3) & ~3;
1828 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1830 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1839 if (PTR_DIFF(p,pdata) > space_remaining) {
1840 /* Move the dirptr back to prev_dirpos */
1841 dptr_SeekDir(conn->dirptr, prev_dirpos);
1842 *out_of_space = True;
1843 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1844 return False; /* Not finished - just out of space */
1847 /* Setup the last entry pointer, as an offset from base_data */
1848 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1849 /* Advance the data pointer to the next slot */
1855 /****************************************************************************
1856 Reply to a TRANS2_FINDFIRST.
1857 ****************************************************************************/
1859 static void call_trans2findfirst(connection_struct *conn,
1860 struct smb_request *req,
1861 char **pparams, int total_params,
1862 char **ppdata, int total_data,
1863 unsigned int max_data_bytes)
1865 /* We must be careful here that we don't return more than the
1866 allowed number of data bytes. If this means returning fewer than
1867 maxentries then so be it. We assume that the redirector has
1868 enough room for the fixed number of parameter bytes it has
1870 char *params = *pparams;
1871 char *pdata = *ppdata;
1875 uint16 findfirst_flags;
1876 bool close_after_first;
1878 bool requires_resume_key;
1880 char *directory = NULL;
1883 int last_entry_off=0;
1887 bool finished = False;
1888 bool dont_descend = False;
1889 bool out_of_space = False;
1890 int space_remaining;
1891 bool mask_contains_wcard = False;
1892 SMB_STRUCT_STAT sbuf;
1893 struct ea_list *ea_list = NULL;
1894 NTSTATUS ntstatus = NT_STATUS_OK;
1895 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1896 TALLOC_CTX *ctx = talloc_tos();
1898 if (total_params < 13) {
1899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1903 dirtype = SVAL(params,0);
1904 maxentries = SVAL(params,2);
1905 findfirst_flags = SVAL(params,4);
1906 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1907 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1908 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1909 info_level = SVAL(params,6);
1911 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1912 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1913 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1914 info_level, max_data_bytes));
1917 /* W2K3 seems to treat zero as 1. */
1921 switch (info_level) {
1922 case SMB_FIND_INFO_STANDARD:
1923 case SMB_FIND_EA_SIZE:
1924 case SMB_FIND_EA_LIST:
1925 case SMB_FIND_FILE_DIRECTORY_INFO:
1926 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1927 case SMB_FIND_FILE_NAMES_INFO:
1928 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1929 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1930 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1932 case SMB_FIND_FILE_UNIX:
1933 case SMB_FIND_FILE_UNIX_INFO2:
1934 /* Always use filesystem for UNIX mtime query. */
1935 ask_sharemode = false;
1936 if (!lp_unix_extensions()) {
1937 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1942 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1946 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1947 params+12, total_params - 12,
1948 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1949 if (!NT_STATUS_IS_OK(ntstatus)) {
1950 reply_nterror(req, ntstatus);
1954 ntstatus = resolve_dfspath_wcard(ctx, conn,
1955 req->flags2 & FLAGS2_DFS_PATHNAMES,
1958 &mask_contains_wcard);
1959 if (!NT_STATUS_IS_OK(ntstatus)) {
1960 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1961 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1962 ERRSRV, ERRbadpath);
1965 reply_nterror(req, ntstatus);
1969 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1970 if (!NT_STATUS_IS_OK(ntstatus)) {
1971 reply_nterror(req, ntstatus);
1975 ntstatus = check_name(conn, directory);
1976 if (!NT_STATUS_IS_OK(ntstatus)) {
1977 reply_nterror(req, ntstatus);
1981 p = strrchr_m(directory,'/');
1983 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1984 if((directory[0] == '.') && (directory[1] == '\0')) {
1985 mask = talloc_strdup(ctx,"*");
1987 reply_nterror(req, NT_STATUS_NO_MEMORY);
1990 mask_contains_wcard = True;
1992 directory = talloc_strdup(talloc_tos(), "./");
1994 reply_nterror(req, NT_STATUS_NO_MEMORY);
2001 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2003 if (info_level == SMB_FIND_EA_LIST) {
2006 if (total_data < 4) {
2007 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2011 ea_size = IVAL(pdata,0);
2012 if (ea_size != total_data) {
2013 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2014 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2019 if (!lp_ea_support(SNUM(conn))) {
2020 reply_doserror(req, ERRDOS, ERReasnotsupported);
2024 /* Pull out the list of names. */
2025 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2032 *ppdata = (char *)SMB_REALLOC(
2033 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2034 if(*ppdata == NULL ) {
2035 reply_nterror(req, NT_STATUS_NO_MEMORY);
2039 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2041 /* Realloc the params space */
2042 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2043 if (*pparams == NULL) {
2044 reply_nterror(req, NT_STATUS_NO_MEMORY);
2049 /* Save the wildcard match and attribs we are using on this directory -
2050 needed as lanman2 assumes these are being saved between calls */
2052 ntstatus = dptr_create(conn,
2058 mask_contains_wcard,
2062 if (!NT_STATUS_IS_OK(ntstatus)) {
2063 reply_nterror(req, ntstatus);
2067 dptr_num = dptr_dnum(conn->dirptr);
2068 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2070 /* Initialize per TRANS2_FIND_FIRST operation data */
2071 dptr_init_search_op(conn->dirptr);
2073 /* We don't need to check for VOL here as this is returned by
2074 a different TRANS2 call. */
2076 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2077 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2078 dont_descend = True;
2081 space_remaining = max_data_bytes;
2082 out_of_space = False;
2084 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2085 bool got_exact_match = False;
2087 /* this is a heuristic to avoid seeking the dirptr except when
2088 absolutely necessary. It allows for a filename of about 40 chars */
2089 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2090 out_of_space = True;
2093 finished = !get_lanman2_dir_entry(ctx,
2096 mask,dirtype,info_level,
2097 requires_resume_key,dont_descend,
2100 space_remaining, &out_of_space,
2102 &last_entry_off, ea_list);
2105 if (finished && out_of_space)
2108 if (!finished && !out_of_space)
2112 * As an optimisation if we know we aren't looking
2113 * for a wildcard name (ie. the name matches the wildcard exactly)
2114 * then we can finish on any (first) match.
2115 * This speeds up large directory searches. JRA.
2121 /* Ensure space_remaining never goes -ve. */
2122 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2123 space_remaining = 0;
2124 out_of_space = true;
2126 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2130 /* Check if we can close the dirptr */
2131 if(close_after_first || (finished && close_if_end)) {
2132 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2133 dptr_close(&dptr_num);
2137 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2138 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2139 * the protocol level is less than NT1. Tested with smbclient. JRA.
2140 * This should fix the OS/2 client bug #2335.
2143 if(numentries == 0) {
2144 dptr_close(&dptr_num);
2145 if (Protocol < PROTOCOL_NT1) {
2146 reply_doserror(req, ERRDOS, ERRnofiles);
2149 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2150 ERRDOS, ERRbadfile);
2155 /* At this point pdata points to numentries directory entries. */
2157 /* Set up the return parameter block */
2158 SSVAL(params,0,dptr_num);
2159 SSVAL(params,2,numentries);
2160 SSVAL(params,4,finished);
2161 SSVAL(params,6,0); /* Never an EA error */
2162 SSVAL(params,8,last_entry_off);
2164 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2167 if ((! *directory) && dptr_path(dptr_num)) {
2168 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2170 reply_nterror(req, NT_STATUS_NO_MEMORY);
2174 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2175 smb_fn_name(req->cmd),
2176 mask, directory, dirtype, numentries ) );
2179 * Force a name mangle here to ensure that the
2180 * mask as an 8.3 name is top of the mangled cache.
2181 * The reasons for this are subtle. Don't remove
2182 * this code unless you know what you are doing
2183 * (see PR#13758). JRA.
2186 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2187 char mangled_name[13];
2188 name_to_8_3(mask, mangled_name, True, conn->params);
2194 /****************************************************************************
2195 Reply to a TRANS2_FINDNEXT.
2196 ****************************************************************************/
2198 static void call_trans2findnext(connection_struct *conn,
2199 struct smb_request *req,
2200 char **pparams, int total_params,
2201 char **ppdata, int total_data,
2202 unsigned int max_data_bytes)
2204 /* We must be careful here that we don't return more than the
2205 allowed number of data bytes. If this means returning fewer than
2206 maxentries then so be it. We assume that the redirector has
2207 enough room for the fixed number of parameter bytes it has
2209 char *params = *pparams;
2210 char *pdata = *ppdata;
2216 uint16 findnext_flags;
2217 bool close_after_request;
2219 bool requires_resume_key;
2221 bool mask_contains_wcard = False;
2222 char *resume_name = NULL;
2223 const char *mask = NULL;
2224 const char *directory = NULL;
2228 int i, last_entry_off=0;
2229 bool finished = False;
2230 bool dont_descend = False;
2231 bool out_of_space = False;
2232 int space_remaining;
2233 struct ea_list *ea_list = NULL;
2234 NTSTATUS ntstatus = NT_STATUS_OK;
2235 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2236 TALLOC_CTX *ctx = talloc_tos();
2238 if (total_params < 13) {
2239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2243 dptr_num = SVAL(params,0);
2244 maxentries = SVAL(params,2);
2245 info_level = SVAL(params,4);
2246 resume_key = IVAL(params,6);
2247 findnext_flags = SVAL(params,10);
2248 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2249 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2250 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2251 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2253 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2255 total_params - 12, STR_TERMINATE, &ntstatus,
2256 &mask_contains_wcard);
2257 if (!NT_STATUS_IS_OK(ntstatus)) {
2258 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2259 complain (it thinks we're asking for the directory above the shared
2260 path or an invalid name). Catch this as the resume name is only compared, never used in
2261 a file access. JRA. */
2262 srvstr_pull_talloc(ctx, params, req->flags2,
2263 &resume_name, params+12,
2267 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2268 reply_nterror(req, ntstatus);
2273 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2274 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2275 resume_key = %d resume name = %s continue=%d level = %d\n",
2276 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2277 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2280 /* W2K3 seems to treat zero as 1. */
2284 switch (info_level) {
2285 case SMB_FIND_INFO_STANDARD:
2286 case SMB_FIND_EA_SIZE:
2287 case SMB_FIND_EA_LIST:
2288 case SMB_FIND_FILE_DIRECTORY_INFO:
2289 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2290 case SMB_FIND_FILE_NAMES_INFO:
2291 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2292 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2293 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2295 case SMB_FIND_FILE_UNIX:
2296 case SMB_FIND_FILE_UNIX_INFO2:
2297 /* Always use filesystem for UNIX mtime query. */
2298 ask_sharemode = false;
2299 if (!lp_unix_extensions()) {
2300 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2305 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2309 if (info_level == SMB_FIND_EA_LIST) {
2312 if (total_data < 4) {
2313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2317 ea_size = IVAL(pdata,0);
2318 if (ea_size != total_data) {
2319 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2320 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2325 if (!lp_ea_support(SNUM(conn))) {
2326 reply_doserror(req, ERRDOS, ERReasnotsupported);
2330 /* Pull out the list of names. */
2331 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2333 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2338 *ppdata = (char *)SMB_REALLOC(
2339 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2340 if(*ppdata == NULL) {
2341 reply_nterror(req, NT_STATUS_NO_MEMORY);
2346 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2348 /* Realloc the params space */
2349 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2350 if(*pparams == NULL ) {
2351 reply_nterror(req, NT_STATUS_NO_MEMORY);
2357 /* Check that the dptr is valid */
2358 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2359 reply_doserror(req, ERRDOS, ERRnofiles);
2363 string_set(&conn->dirpath,dptr_path(dptr_num));
2365 /* Get the wildcard mask from the dptr */
2366 if((p = dptr_wcard(dptr_num))== NULL) {
2367 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2368 reply_doserror(req, ERRDOS, ERRnofiles);
2373 directory = conn->dirpath;
2375 /* Get the attr mask from the dptr */
2376 dirtype = dptr_attr(dptr_num);
2378 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2379 dptr_num, mask, dirtype,
2381 dptr_TellDir(conn->dirptr)));
2383 /* Initialize per TRANS2_FIND_NEXT operation data */
2384 dptr_init_search_op(conn->dirptr);
2386 /* We don't need to check for VOL here as this is returned by
2387 a different TRANS2 call. */
2389 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2390 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2391 dont_descend = True;
2394 space_remaining = max_data_bytes;
2395 out_of_space = False;
2398 * Seek to the correct position. We no longer use the resume key but
2399 * depend on the last file name instead.
2402 if(*resume_name && !continue_bit) {
2405 long current_pos = 0;
2407 * Remember, name_to_8_3 is called by
2408 * get_lanman2_dir_entry(), so the resume name
2409 * could be mangled. Ensure we check the unmangled name.
2412 if (mangle_is_mangled(resume_name, conn->params)) {
2413 char *new_resume_name = NULL;
2414 mangle_lookup_name_from_8_3(ctx,
2418 if (new_resume_name) {
2419 resume_name = new_resume_name;
2424 * Fix for NT redirector problem triggered by resume key indexes
2425 * changing between directory scans. We now return a resume key of 0
2426 * and instead look for the filename to continue from (also given
2427 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2428 * findfirst/findnext (as is usual) then the directory pointer
2429 * should already be at the correct place.
2432 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2433 } /* end if resume_name && !continue_bit */
2435 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2436 bool got_exact_match = False;
2438 /* this is a heuristic to avoid seeking the dirptr except when
2439 absolutely necessary. It allows for a filename of about 40 chars */
2440 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2441 out_of_space = True;
2444 finished = !get_lanman2_dir_entry(ctx,
2447 mask,dirtype,info_level,
2448 requires_resume_key,dont_descend,
2451 space_remaining, &out_of_space,
2453 &last_entry_off, ea_list);
2456 if (finished && out_of_space)
2459 if (!finished && !out_of_space)
2463 * As an optimisation if we know we aren't looking
2464 * for a wildcard name (ie. the name matches the wildcard exactly)
2465 * then we can finish on any (first) match.
2466 * This speeds up large directory searches. JRA.
2472 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2475 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2476 smb_fn_name(req->cmd),
2477 mask, directory, dirtype, numentries ) );
2479 /* Check if we can close the dirptr */
2480 if(close_after_request || (finished && close_if_end)) {
2481 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2482 dptr_close(&dptr_num); /* This frees up the saved mask */
2485 /* Set up the return parameter block */
2486 SSVAL(params,0,numentries);
2487 SSVAL(params,2,finished);
2488 SSVAL(params,4,0); /* Never an EA error */
2489 SSVAL(params,6,last_entry_off);
2491 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2497 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2499 E_md4hash(lp_servicename(SNUM(conn)),objid);
2503 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2505 SMB_ASSERT(extended_info != NULL);
2507 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2508 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2509 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2510 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2511 #ifdef SAMBA_VERSION_REVISION
2512 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2514 extended_info->samba_subversion = 0;
2515 #ifdef SAMBA_VERSION_RC_RELEASE
2516 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2518 #ifdef SAMBA_VERSION_PRE_RELEASE
2519 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2522 #ifdef SAMBA_VERSION_VENDOR_PATCH
2523 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2525 extended_info->samba_gitcommitdate = 0;
2526 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2527 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2530 memset(extended_info->samba_version_string, 0,
2531 sizeof(extended_info->samba_version_string));
2533 snprintf (extended_info->samba_version_string,
2534 sizeof(extended_info->samba_version_string),
2535 "%s", samba_version_string());
2538 /****************************************************************************
2539 Reply to a TRANS2_QFSINFO (query filesystem info).
2540 ****************************************************************************/
2542 static void call_trans2qfsinfo(connection_struct *conn,
2543 struct smb_request *req,
2544 char **pparams, int total_params,
2545 char **ppdata, int total_data,
2546 unsigned int max_data_bytes)
2548 char *pdata, *end_data;
2549 char *params = *pparams;
2553 const char *vname = volume_label(SNUM(conn));
2554 int snum = SNUM(conn);
2555 char *fstype = lp_fstype(SNUM(conn));
2556 uint32 additional_flags = 0;
2558 if (total_params < 2) {
2559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2563 info_level = SVAL(params,0);
2566 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2567 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2568 "info level (0x%x) on IPC$.\n",
2569 (unsigned int)info_level));
2570 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2575 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2576 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2577 DEBUG(0,("call_trans2qfsinfo: encryption required "
2578 "and info level 0x%x sent.\n",
2579 (unsigned int)info_level));
2580 exit_server_cleanly("encryption required "
2586 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2588 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2589 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2590 reply_doserror(req, ERRSRV, ERRinvdevice);
2594 *ppdata = (char *)SMB_REALLOC(
2595 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2596 if (*ppdata == NULL ) {
2597 reply_nterror(req, NT_STATUS_NO_MEMORY);
2602 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2603 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2605 switch (info_level) {
2606 case SMB_INFO_ALLOCATION:
2608 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2610 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2611 reply_unixerror(req, ERRHRD, ERRgeneral);
2615 block_size = lp_block_size(snum);
2616 if (bsize < block_size) {
2617 uint64_t factor = block_size/bsize;
2622 if (bsize > block_size) {
2623 uint64_t factor = bsize/block_size;
2628 bytes_per_sector = 512;
2629 sectors_per_unit = bsize/bytes_per_sector;
2631 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2632 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2633 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2635 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2636 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2637 SIVAL(pdata,l1_cUnit,dsize);
2638 SIVAL(pdata,l1_cUnitAvail,dfree);
2639 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2643 case SMB_INFO_VOLUME:
2644 /* Return volume name */
2646 * Add volume serial number - hash of a combination of
2647 * the called hostname and the service name.
2649 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2651 * Win2k3 and previous mess this up by sending a name length
2652 * one byte short. I believe only older clients (OS/2 Win9x) use
2653 * this call so try fixing this by adding a terminating null to
2654 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2658 pdata+l2_vol_szVolLabel, vname,
2659 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2660 STR_NOALIGN|STR_TERMINATE);
2661 SCVAL(pdata,l2_vol_cch,len);
2662 data_len = l2_vol_szVolLabel + len;
2663 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2664 (unsigned)st.st_ctime, len, vname));
2667 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2668 case SMB_FS_ATTRIBUTE_INFORMATION:
2670 additional_flags = 0;
2671 #if defined(HAVE_SYS_QUOTAS)
2672 additional_flags |= FILE_VOLUME_QUOTAS;
2675 if(lp_nt_acl_support(SNUM(conn))) {
2676 additional_flags |= FILE_PERSISTENT_ACLS;
2679 /* Capabilities are filled in at connection time through STATVFS call */
2680 additional_flags |= conn->fs_capabilities;
2682 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2683 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2684 additional_flags); /* FS ATTRIBUTES */
2686 SIVAL(pdata,4,255); /* Max filename component length */
2687 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2688 and will think we can't do long filenames */
2689 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2690 PTR_DIFF(end_data, pdata+12),
2693 data_len = 12 + len;
2696 case SMB_QUERY_FS_LABEL_INFO:
2697 case SMB_FS_LABEL_INFORMATION:
2698 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2699 PTR_DIFF(end_data, pdata+4), 0);
2704 case SMB_QUERY_FS_VOLUME_INFO:
2705 case SMB_FS_VOLUME_INFORMATION:
2708 * Add volume serial number - hash of a combination of
2709 * the called hostname and the service name.
2711 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2712 (str_checksum(get_local_machine_name())<<16));
2714 /* Max label len is 32 characters. */
2715 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2716 PTR_DIFF(end_data, pdata+18),
2718 SIVAL(pdata,12,len);
2721 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2722 (int)strlen(vname),vname, lp_servicename(snum)));
2725 case SMB_QUERY_FS_SIZE_INFO:
2726 case SMB_FS_SIZE_INFORMATION:
2728 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2730 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2731 reply_unixerror(req, ERRHRD, ERRgeneral);
2734 block_size = lp_block_size(snum);
2735 if (bsize < block_size) {
2736 uint64_t factor = block_size/bsize;
2741 if (bsize > block_size) {
2742 uint64_t factor = bsize/block_size;
2747 bytes_per_sector = 512;
2748 sectors_per_unit = bsize/bytes_per_sector;
2749 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2750 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2751 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2752 SBIG_UINT(pdata,0,dsize);
2753 SBIG_UINT(pdata,8,dfree);
2754 SIVAL(pdata,16,sectors_per_unit);
2755 SIVAL(pdata,20,bytes_per_sector);
2759 case SMB_FS_FULL_SIZE_INFORMATION:
2761 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2763 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2764 reply_unixerror(req, ERRHRD, ERRgeneral);
2767 block_size = lp_block_size(snum);
2768 if (bsize < block_size) {
2769 uint64_t factor = block_size/bsize;
2774 if (bsize > block_size) {
2775 uint64_t factor = bsize/block_size;
2780 bytes_per_sector = 512;
2781 sectors_per_unit = bsize/bytes_per_sector;
2782 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2783 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2784 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2785 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2786 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2787 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2788 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2789 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2793 case SMB_QUERY_FS_DEVICE_INFO:
2794 case SMB_FS_DEVICE_INFORMATION:
2796 SIVAL(pdata,0,0); /* dev type */
2797 SIVAL(pdata,4,0); /* characteristics */
2800 #ifdef HAVE_SYS_QUOTAS
2801 case SMB_FS_QUOTA_INFORMATION:
2803 * what we have to send --metze:
2805 * Unknown1: 24 NULL bytes
2806 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2807 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2808 * Quota Flags: 2 byte :
2809 * Unknown3: 6 NULL bytes
2813 * details for Quota Flags:
2815 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2816 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2817 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2818 * 0x0001 Enable Quotas: enable quota for this fs
2822 /* we need to fake up a fsp here,
2823 * because its not send in this call
2826 SMB_NTQUOTA_STRUCT quotas;
2829 ZERO_STRUCT(quotas);
2835 if (conn->server_info->utok.uid != 0) {
2836 DEBUG(0,("set_user_quota: access_denied "
2837 "service [%s] user [%s]\n",
2838 lp_servicename(SNUM(conn)),
2839 conn->server_info->unix_name));
2840 reply_doserror(req, ERRDOS, ERRnoaccess);
2844 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2845 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2846 reply_doserror(req, ERRSRV, ERRerror);
2852 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2854 /* Unknown1 24 NULL bytes*/
2855 SBIG_UINT(pdata,0,(uint64_t)0);
2856 SBIG_UINT(pdata,8,(uint64_t)0);
2857 SBIG_UINT(pdata,16,(uint64_t)0);
2859 /* Default Soft Quota 8 bytes */
2860 SBIG_UINT(pdata,24,quotas.softlim);
2862 /* Default Hard Quota 8 bytes */
2863 SBIG_UINT(pdata,32,quotas.hardlim);
2865 /* Quota flag 2 bytes */
2866 SSVAL(pdata,40,quotas.qflags);
2868 /* Unknown3 6 NULL bytes */
2874 #endif /* HAVE_SYS_QUOTAS */
2875 case SMB_FS_OBJECTID_INFORMATION:
2877 unsigned char objid[16];
2878 struct smb_extended_info extended_info;
2879 memcpy(pdata,create_volume_objectid(conn, objid),16);
2880 samba_extended_info_version (&extended_info);
2881 SIVAL(pdata,16,extended_info.samba_magic);
2882 SIVAL(pdata,20,extended_info.samba_version);
2883 SIVAL(pdata,24,extended_info.samba_subversion);
2884 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2885 memcpy(pdata+36,extended_info.samba_version_string,28);
2891 * Query the version and capabilities of the CIFS UNIX extensions
2895 case SMB_QUERY_CIFS_UNIX_INFO:
2897 bool large_write = lp_min_receive_file_size() &&
2898 !srv_is_signing_active(smbd_server_conn);
2899 bool large_read = !srv_is_signing_active(smbd_server_conn);
2900 int encrypt_caps = 0;
2902 if (!lp_unix_extensions()) {
2903 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2907 switch (conn->encrypt_level) {
2913 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2916 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2917 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2918 large_write = false;
2924 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2925 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2927 /* We have POSIX ACLs, pathname, encryption,
2928 * large read/write, and locking capability. */
2930 SBIG_UINT(pdata,4,((uint64_t)(
2931 CIFS_UNIX_POSIX_ACLS_CAP|
2932 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2933 CIFS_UNIX_FCNTL_LOCKS_CAP|
2934 CIFS_UNIX_EXTATTR_CAP|
2935 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2937 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2939 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2943 case SMB_QUERY_POSIX_FS_INFO:
2946 vfs_statvfs_struct svfs;
2948 if (!lp_unix_extensions()) {
2949 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2953 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2957 SIVAL(pdata,0,svfs.OptimalTransferSize);
2958 SIVAL(pdata,4,svfs.BlockSize);
2959 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2960 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2961 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2962 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2963 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2964 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2965 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2967 } else if (rc == EOPNOTSUPP) {
2968 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2970 #endif /* EOPNOTSUPP */
2972 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2973 reply_doserror(req, ERRSRV, ERRerror);
2979 case SMB_QUERY_POSIX_WHOAMI:
2985 if (!lp_unix_extensions()) {
2986 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2990 if (max_data_bytes < 40) {
2991 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2995 /* We ARE guest if global_sid_Builtin_Guests is
2996 * in our list of SIDs.
2998 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2999 conn->server_info->ptok)) {
3000 flags |= SMB_WHOAMI_GUEST;
3003 /* We are NOT guest if global_sid_Authenticated_Users
3004 * is in our list of SIDs.
3006 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3007 conn->server_info->ptok)) {
3008 flags &= ~SMB_WHOAMI_GUEST;
3011 /* NOTE: 8 bytes for UID/GID, irrespective of native
3012 * platform size. This matches
3013 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3015 data_len = 4 /* flags */
3022 + 4 /* pad/reserved */
3023 + (conn->server_info->utok.ngroups * 8)
3025 + (conn->server_info->ptok->num_sids *
3029 SIVAL(pdata, 0, flags);
3030 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3032 (uint64_t)conn->server_info->utok.uid);
3033 SBIG_UINT(pdata, 16,
3034 (uint64_t)conn->server_info->utok.gid);
3037 if (data_len >= max_data_bytes) {
3038 /* Potential overflow, skip the GIDs and SIDs. */
3040 SIVAL(pdata, 24, 0); /* num_groups */
3041 SIVAL(pdata, 28, 0); /* num_sids */
3042 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3043 SIVAL(pdata, 36, 0); /* reserved */
3049 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3050 SIVAL(pdata, 28, conn->server_info->num_sids);
3052 /* We walk the SID list twice, but this call is fairly
3053 * infrequent, and I don't expect that it's performance
3054 * sensitive -- jpeach
3056 for (i = 0, sid_bytes = 0;
3057 i < conn->server_info->ptok->num_sids; ++i) {
3058 sid_bytes += ndr_size_dom_sid(
3059 &conn->server_info->ptok->user_sids[i],
3064 /* SID list byte count */
3065 SIVAL(pdata, 32, sid_bytes);
3067 /* 4 bytes pad/reserved - must be zero */
3068 SIVAL(pdata, 36, 0);
3072 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3073 SBIG_UINT(pdata, data_len,
3074 (uint64_t)conn->server_info->utok.groups[i]);
3080 i < conn->server_info->ptok->num_sids; ++i) {
3081 int sid_len = ndr_size_dom_sid(
3082 &conn->server_info->ptok->user_sids[i],
3086 sid_linearize(pdata + data_len, sid_len,
3087 &conn->server_info->ptok->user_sids[i]);
3088 data_len += sid_len;
3094 case SMB_MAC_QUERY_FS_INFO:
3096 * Thursby MAC extension... ONLY on NTFS filesystems
3097 * once we do streams then we don't need this
3099 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3101 SIVAL(pdata,84,0x100); /* Don't support mac... */
3106 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3111 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3114 DEBUG( 4, ( "%s info_level = %d\n",
3115 smb_fn_name(req->cmd), info_level) );
3120 /****************************************************************************
3121 Reply to a TRANS2_SETFSINFO (set filesystem info).
3122 ****************************************************************************/
3124 static void call_trans2setfsinfo(connection_struct *conn,
3125 struct smb_request *req,
3126 char **pparams, int total_params,
3127 char **ppdata, int total_data,
3128 unsigned int max_data_bytes)
3130 char *pdata = *ppdata;
3131 char *params = *pparams;
3134 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3137 if (total_params < 4) {
3138 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3144 info_level = SVAL(params,2);
3147 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3148 info_level != SMB_SET_CIFS_UNIX_INFO) {
3149 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3150 "info level (0x%x) on IPC$.\n",
3151 (unsigned int)info_level));
3152 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3157 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3158 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3159 DEBUG(0,("call_trans2setfsinfo: encryption required "
3160 "and info level 0x%x sent.\n",
3161 (unsigned int)info_level));
3162 exit_server_cleanly("encryption required "
3168 switch(info_level) {
3169 case SMB_SET_CIFS_UNIX_INFO:
3171 uint16 client_unix_major;
3172 uint16 client_unix_minor;
3173 uint32 client_unix_cap_low;
3174 uint32 client_unix_cap_high;
3176 if (!lp_unix_extensions()) {
3178 NT_STATUS_INVALID_LEVEL);
3182 /* There should be 12 bytes of capabilities set. */
3183 if (total_data < 8) {
3186 NT_STATUS_INVALID_PARAMETER);
3189 client_unix_major = SVAL(pdata,0);
3190 client_unix_minor = SVAL(pdata,2);
3191 client_unix_cap_low = IVAL(pdata,4);
3192 client_unix_cap_high = IVAL(pdata,8);
3193 /* Just print these values for now. */
3194 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3195 cap_low = 0x%x, cap_high = 0x%x\n",
3196 (unsigned int)client_unix_major,
3197 (unsigned int)client_unix_minor,
3198 (unsigned int)client_unix_cap_low,
3199 (unsigned int)client_unix_cap_high ));
3201 /* Here is where we must switch to posix pathname processing... */
3202 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3203 lp_set_posix_pathnames();
3204 mangle_change_to_posix();
3207 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3208 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3209 /* Client that knows how to do posix locks,
3210 * but not posix open/mkdir operations. Set a
3211 * default type for read/write checks. */
3213 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3219 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3222 size_t param_len = 0;
3223 size_t data_len = total_data;
3225 if (!lp_unix_extensions()) {
3228 NT_STATUS_INVALID_LEVEL);
3232 if (lp_smb_encrypt(SNUM(conn)) == false) {
3235 NT_STATUS_NOT_SUPPORTED);
3239 DEBUG( 4,("call_trans2setfsinfo: "
3240 "request transport encryption.\n"));
3242 status = srv_request_encryption_setup(conn,
3243 (unsigned char **)ppdata,
3245 (unsigned char **)pparams,
3248 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3249 !NT_STATUS_IS_OK(status)) {
3250 reply_nterror(req, status);
3254 send_trans2_replies(conn, req,
3261 if (NT_STATUS_IS_OK(status)) {
3262 /* Server-side transport
3263 * encryption is now *on*. */
3264 status = srv_encryption_start(conn);
3265 if (!NT_STATUS_IS_OK(status)) {
3266 exit_server_cleanly(
3267 "Failure in setting "
3268 "up encrypted transport");
3274 case SMB_FS_QUOTA_INFORMATION:
3276 files_struct *fsp = NULL;
3277 SMB_NTQUOTA_STRUCT quotas;
3279 ZERO_STRUCT(quotas);
3282 if ((conn->server_info->utok.uid != 0)
3283 ||!CAN_WRITE(conn)) {
3284 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3285 lp_servicename(SNUM(conn)),
3286 conn->server_info->unix_name));
3287 reply_doserror(req, ERRSRV, ERRaccess);
3291 /* note: normaly there're 48 bytes,
3292 * but we didn't use the last 6 bytes for now
3295 fsp = file_fsp(req, SVAL(params,0));
3297 if (!check_fsp_ntquota_handle(conn, req,
3299 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3301 req, NT_STATUS_INVALID_HANDLE);
3305 if (total_data < 42) {
3306 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3310 NT_STATUS_INVALID_PARAMETER);
3314 /* unknown_1 24 NULL bytes in pdata*/
3316 /* the soft quotas 8 bytes (uint64_t)*/
3317 quotas.softlim = (uint64_t)IVAL(pdata,24);
3318 #ifdef LARGE_SMB_OFF_T
3319 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3320 #else /* LARGE_SMB_OFF_T */
3321 if ((IVAL(pdata,28) != 0)&&
3322 ((quotas.softlim != 0xFFFFFFFF)||
3323 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3324 /* more than 32 bits? */
3327 NT_STATUS_INVALID_PARAMETER);
3330 #endif /* LARGE_SMB_OFF_T */
3332 /* the hard quotas 8 bytes (uint64_t)*/
3333 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3334 #ifdef LARGE_SMB_OFF_T
3335 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3336 #else /* LARGE_SMB_OFF_T */
3337 if ((IVAL(pdata,36) != 0)&&
3338 ((quotas.hardlim != 0xFFFFFFFF)||
3339 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3340 /* more than 32 bits? */
3343 NT_STATUS_INVALID_PARAMETER);
3346 #endif /* LARGE_SMB_OFF_T */
3348 /* quota_flags 2 bytes **/
3349 quotas.qflags = SVAL(pdata,40);
3351 /* unknown_2 6 NULL bytes follow*/
3353 /* now set the quotas */
3354 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3355 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3356 reply_doserror(req, ERRSRV, ERRerror);
3363 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3365 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3371 * sending this reply works fine,
3372 * but I'm not sure it's the same
3373 * like windows do...
3376 reply_outbuf(req, 10, 0);
3379 #if defined(HAVE_POSIX_ACLS)
3380 /****************************************************************************
3381 Utility function to count the number of entries in a POSIX acl.
3382 ****************************************************************************/
3384 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3386 unsigned int ace_count = 0;
3387 int entry_id = SMB_ACL_FIRST_ENTRY;
3388 SMB_ACL_ENTRY_T entry;
3390 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3392 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3393 entry_id = SMB_ACL_NEXT_ENTRY;
3400 /****************************************************************************
3401 Utility function to marshall a POSIX acl into wire format.
3402 ****************************************************************************/
3404 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3406 int entry_id = SMB_ACL_FIRST_ENTRY;
3407 SMB_ACL_ENTRY_T entry;
3409 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3410 SMB_ACL_TAG_T tagtype;
3411 SMB_ACL_PERMSET_T permset;
3412 unsigned char perms = 0;
3413 unsigned int own_grp;
3416 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3417 entry_id = SMB_ACL_NEXT_ENTRY;
3420 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3421 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3425 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3426 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3430 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3431 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3432 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3434 SCVAL(pdata,1,perms);
3437 case SMB_ACL_USER_OBJ:
3438 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3439 own_grp = (unsigned int)pst->st_uid;
3440 SIVAL(pdata,2,own_grp);
3445 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3447 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3450 own_grp = (unsigned int)*puid;
3451 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3452 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3453 SIVAL(pdata,2,own_grp);
3457 case SMB_ACL_GROUP_OBJ:
3458 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3459 own_grp = (unsigned int)pst->st_gid;
3460 SIVAL(pdata,2,own_grp);
3465 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3467 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3470 own_grp = (unsigned int)*pgid;
3471 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3472 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3473 SIVAL(pdata,2,own_grp);
3478 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3479 SIVAL(pdata,2,0xFFFFFFFF);
3480 SIVAL(pdata,6,0xFFFFFFFF);
3483 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3484 SIVAL(pdata,2,0xFFFFFFFF);
3485 SIVAL(pdata,6,0xFFFFFFFF);
3488 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3491 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3498 /****************************************************************************
3499 Store the FILE_UNIX_BASIC info.
3500 ****************************************************************************/
3502 static char *store_file_unix_basic(connection_struct *conn,
3505 const SMB_STRUCT_STAT *psbuf)
3507 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3508 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3510 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3513 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3516 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3517 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3518 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3521 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3525 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3529 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3532 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3536 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3540 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3543 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3547 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3554 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3555 * the chflags(2) (or equivalent) flags.
3557 * XXX: this really should be behind the VFS interface. To do this, we would
3558 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3559 * Each VFS module could then implement its own mapping as appropriate for the
3560 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3562 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3566 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3570 { UF_IMMUTABLE, EXT_IMMUTABLE },
3574 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3578 { UF_HIDDEN, EXT_HIDDEN },
3581 /* Do not remove. We need to guarantee that this array has at least one
3582 * entry to build on HP-UX.
3588 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3589 uint32 *smb_fflags, uint32 *smb_fmask)
3591 #ifdef HAVE_STAT_ST_FLAGS
3594 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3595 *smb_fmask |= info2_flags_map[i].smb_fflag;
3596 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3597 *smb_fflags |= info2_flags_map[i].smb_fflag;
3600 #endif /* HAVE_STAT_ST_FLAGS */
3603 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3604 const uint32 smb_fflags,
3605 const uint32 smb_fmask,
3608 #ifdef HAVE_STAT_ST_FLAGS
3609 uint32 max_fmask = 0;
3612 *stat_fflags = psbuf->st_flags;
3614 /* For each flags requested in smb_fmask, check the state of the
3615 * corresponding flag in smb_fflags and set or clear the matching
3619 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3620 max_fmask |= info2_flags_map[i].smb_fflag;
3621 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3622 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3623 *stat_fflags |= info2_flags_map[i].stat_fflag;
3625 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3630 /* If smb_fmask is asking to set any bits that are not supported by
3631 * our flag mappings, we should fail.
3633 if ((smb_fmask & max_fmask) != smb_fmask) {
3640 #endif /* HAVE_STAT_ST_FLAGS */
3644 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3645 * of file flags and birth (create) time.
3647 static char *store_file_unix_basic_info2(connection_struct *conn,
3650 const SMB_STRUCT_STAT *psbuf)
3652 uint32 file_flags = 0;
3653 uint32 flags_mask = 0;
3655 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3657 /* Create (birth) time 64 bit */
3658 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3661 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3662 SIVAL(pdata, 0, file_flags); /* flags */
3663 SIVAL(pdata, 4, flags_mask); /* mask */
3669 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3670 const struct stream_struct *streams,
3672 unsigned int max_data_bytes,
3673 unsigned int *data_size)
3676 unsigned int ofs = 0;
3678 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3679 unsigned int next_offset;
3681 smb_ucs2_t *namebuf;
3683 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3684 streams[i].name, &namelen) ||
3687 return NT_STATUS_INVALID_PARAMETER;
3691 * name_buf is now null-terminated, we need to marshall as not
3697 SIVAL(data, ofs+4, namelen);
3698 SOFF_T(data, ofs+8, streams[i].size);
3699 SOFF_T(data, ofs+16, streams[i].alloc_size);
3700 memcpy(data+ofs+24, namebuf, namelen);
3701 TALLOC_FREE(namebuf);
3703 next_offset = ofs + 24 + namelen;
3705 if (i == num_streams-1) {
3706 SIVAL(data, ofs, 0);
3709 unsigned int align = ndr_align_size(next_offset, 8);
3711 memset(data+next_offset, 0, align);
3712 next_offset += align;
3714 SIVAL(data, ofs, next_offset - ofs);
3723 return NT_STATUS_OK;
3726 /****************************************************************************
3727 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3728 ****************************************************************************/
3730 static void call_trans2qpipeinfo(connection_struct *conn,
3731 struct smb_request *req,
3732 unsigned int tran_call,
3733 char **pparams, int total_params,
3734 char **ppdata, int total_data,
3735 unsigned int max_data_bytes)
3737 char *params = *pparams;
3738 char *pdata = *ppdata;
3739 unsigned int data_size = 0;
3740 unsigned int param_size = 2;
3745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3749 if (total_params < 4) {
3750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3754 fsp = file_fsp(req, SVAL(params,0));
3755 if (!fsp_is_np(fsp)) {
3756 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3760 info_level = SVAL(params,2);
3762 *pparams = (char *)SMB_REALLOC(*pparams,2);
3763 if (*pparams == NULL) {
3764 reply_nterror(req, NT_STATUS_NO_MEMORY);
3769 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3770 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3771 if (*ppdata == NULL ) {
3772 reply_nterror(req, NT_STATUS_NO_MEMORY);
3777 switch (info_level) {
3778 case SMB_FILE_STANDARD_INFORMATION:
3780 SOFF_T(pdata,0,4096LL);
3787 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3791 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3797 /****************************************************************************
3798 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3799 file name or file id).
3800 ****************************************************************************/
3802 static void call_trans2qfilepathinfo(connection_struct *conn,
3803 struct smb_request *req,
3804 unsigned int tran_call,
3805 char **pparams, int total_params,
3806 char **ppdata, int total_data,
3807 unsigned int max_data_bytes)
3809 char *params = *pparams;
3810 char *pdata = *ppdata;
3811 char *dstart, *dend;
3815 SMB_OFF_T file_size=0;
3816 uint64_t allocation_size=0;
3817 unsigned int data_size = 0;
3818 unsigned int param_size = 2;
3819 SMB_STRUCT_STAT sbuf;
3820 char *dos_fname = NULL;
3826 bool delete_pending = False;
3828 time_t create_time, mtime, atime;
3829 struct timespec create_time_ts, mtime_ts, atime_ts;
3830 struct timespec write_time_ts;
3831 files_struct *fsp = NULL;
3832 struct file_id fileid;
3833 struct ea_list *ea_list = NULL;
3834 char *lock_data = NULL;
3835 bool ms_dfs_link = false;
3836 TALLOC_CTX *ctx = talloc_tos();
3839 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3844 ZERO_STRUCT(write_time_ts);
3846 if (tran_call == TRANSACT2_QFILEINFO) {
3847 if (total_params < 4) {
3848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3853 call_trans2qpipeinfo(conn, req, tran_call,
3854 pparams, total_params,
3860 fsp = file_fsp(req, SVAL(params,0));
3861 info_level = SVAL(params,2);
3863 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3865 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3866 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3870 /* Initial check for valid fsp ptr. */
3871 if (!check_fsp_open(conn, req, fsp)) {
3875 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3877 reply_nterror(req, NT_STATUS_NO_MEMORY);
3881 if(fsp->fake_file_handle) {
3883 * This is actually for the QUOTA_FAKE_FILE --metze
3886 /* We know this name is ok, it's already passed the checks. */
3888 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3890 * This is actually a QFILEINFO on a directory
3891 * handle (returned from an NT SMB). NT5.0 seems
3892 * to do this call. JRA.
3895 if (INFO_LEVEL_IS_UNIX(info_level)) {
3896 /* Always do lstat for UNIX calls. */
3897 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3898 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3899 reply_unixerror(req,ERRDOS,ERRbadpath);
3902 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3903 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3904 reply_unixerror(req, ERRDOS, ERRbadpath);
3908 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3909 get_file_infos(fileid, &delete_pending, &write_time_ts);
3912 * Original code - this is an open file.
3914 if (!check_fsp(conn, req, fsp)) {
3918 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3919 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3920 reply_unixerror(req, ERRDOS, ERRbadfid);
3923 pos = fsp->fh->position_information;
3924 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3925 get_file_infos(fileid, &delete_pending, &write_time_ts);
3929 NTSTATUS status = NT_STATUS_OK;
3932 if (total_params < 7) {
3933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3937 info_level = SVAL(params,0);
3939 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3941 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3942 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3946 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3948 STR_TERMINATE, &status);
3949 if (!NT_STATUS_IS_OK(status)) {
3950 reply_nterror(req, status);
3954 status = resolve_dfspath(ctx,
3956 req->flags2 & FLAGS2_DFS_PATHNAMES,
3959 if (!NT_STATUS_IS_OK(status)) {
3960 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3961 reply_botherror(req,
3962 NT_STATUS_PATH_NOT_COVERED,
3963 ERRSRV, ERRbadpath);
3965 reply_nterror(req, status);
3969 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3970 if (!NT_STATUS_IS_OK(status)) {
3971 reply_nterror(req, status);
3974 status = check_name(conn, fname);
3975 if (!NT_STATUS_IS_OK(status)) {
3976 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3977 reply_nterror(req, status);
3981 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3982 && is_ntfs_stream_name(fname)) {
3984 SMB_STRUCT_STAT bsbuf;
3986 status = split_ntfs_stream_name(talloc_tos(), fname,
3988 if (!NT_STATUS_IS_OK(status)) {
3989 DEBUG(10, ("create_file_unixpath: "
3990 "split_ntfs_stream_name failed: %s\n",
3991 nt_errstr(status)));
3992 reply_nterror(req, status);
3996 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
3998 if (INFO_LEVEL_IS_UNIX(info_level)) {
3999 /* Always do lstat for UNIX calls. */
4000 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4001 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4002 reply_unixerror(req,ERRDOS,ERRbadpath);
4006 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4007 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4008 reply_unixerror(req,ERRDOS,ERRbadpath);
4013 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4014 get_file_infos(fileid, &delete_pending, NULL);
4015 if (delete_pending) {
4016 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4021 if (INFO_LEVEL_IS_UNIX(info_level)) {
4022 /* Always do lstat for UNIX calls. */
4023 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4024 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4025 reply_unixerror(req, ERRDOS, ERRbadpath);
4029 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4030 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4033 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4034 reply_unixerror(req, ERRDOS, ERRbadpath);
4039 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4040 get_file_infos(fileid, &delete_pending, &write_time_ts);
4041 if (delete_pending) {
4042 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4047 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4048 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4052 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4053 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4055 p = strrchr_m(fname,'/');
4062 mode = dos_mode_msdfs(conn,fname,&sbuf);
4064 mode = dos_mode(conn,fname,&sbuf);
4067 mode = FILE_ATTRIBUTE_NORMAL;
4069 nlink = sbuf.st_nlink;
4071 if (nlink && (mode&aDIR)) {
4075 if ((nlink > 0) && delete_pending) {
4079 fullpathname = fname;
4081 file_size = get_file_size_stat(&sbuf);
4083 /* Pull out any data sent here before we realloc. */
4084 switch (info_level) {
4085 case SMB_INFO_QUERY_EAS_FROM_LIST:
4087 /* Pull any EA list from the data portion. */
4090 if (total_data < 4) {
4092 req, NT_STATUS_INVALID_PARAMETER);
4095 ea_size = IVAL(pdata,0);
4097 if (total_data > 0 && ea_size != total_data) {
4098 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4099 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4101 req, NT_STATUS_INVALID_PARAMETER);
4105 if (!lp_ea_support(SNUM(conn))) {
4106 reply_doserror(req, ERRDOS,
4107 ERReasnotsupported);
4111 /* Pull out the list of names. */
4112 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4115 req, NT_STATUS_INVALID_PARAMETER);
4121 case SMB_QUERY_POSIX_LOCK:
4123 if (fsp == NULL || fsp->fh->fd == -1) {
4124 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4128 if (total_data != POSIX_LOCK_DATA_SIZE) {
4130 req, NT_STATUS_INVALID_PARAMETER);
4134 /* Copy the lock range data. */
4135 lock_data = (char *)TALLOC_MEMDUP(
4136 ctx, pdata, total_data);
4138 reply_nterror(req, NT_STATUS_NO_MEMORY);
4146 *pparams = (char *)SMB_REALLOC(*pparams,2);
4147 if (*pparams == NULL) {
4148 reply_nterror(req, NT_STATUS_NO_MEMORY);
4153 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4154 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4155 if (*ppdata == NULL ) {
4156 reply_nterror(req, NT_STATUS_NO_MEMORY);
4161 dend = dstart + data_size - 1;
4163 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4164 mtime_ts = get_mtimespec(&sbuf);
4165 atime_ts = get_atimespec(&sbuf);
4167 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4170 /* Do we have this path open ? */
4172 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4173 fsp1 = file_find_di_first(fileid);
4174 if (fsp1 && fsp1->initial_allocation_size) {
4175 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4179 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4180 mtime_ts = write_time_ts;
4183 if (lp_dos_filetime_resolution(SNUM(conn))) {
4184 dos_filetime_timespec(&create_time_ts);
4185 dos_filetime_timespec(&mtime_ts);
4186 dos_filetime_timespec(&atime_ts);
4189 create_time = convert_timespec_to_time_t(create_time_ts);
4190 mtime = convert_timespec_to_time_t(mtime_ts);
4191 atime = convert_timespec_to_time_t(atime_ts);
4193 /* NT expects the name to be in an exact form of the *full*
4194 filename. See the trans2 torture test */
4195 if (ISDOT(base_name)) {
4196 dos_fname = talloc_strdup(ctx, "\\");
4198 reply_nterror(req, NT_STATUS_NO_MEMORY);
4202 dos_fname = talloc_asprintf(ctx,
4206 reply_nterror(req, NT_STATUS_NO_MEMORY);
4209 string_replace(dos_fname, '/', '\\');
4212 switch (info_level) {
4213 case SMB_INFO_STANDARD:
4214 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4216 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4217 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4218 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4219 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4220 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4221 SSVAL(pdata,l1_attrFile,mode);
4224 case SMB_INFO_QUERY_EA_SIZE:
4226 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4227 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4229 srv_put_dos_date2(pdata,0,create_time);
4230 srv_put_dos_date2(pdata,4,atime);
4231 srv_put_dos_date2(pdata,8,mtime); /* write time */
4232 SIVAL(pdata,12,(uint32)file_size);
4233 SIVAL(pdata,16,(uint32)allocation_size);
4234 SSVAL(pdata,20,mode);
4235 SIVAL(pdata,22,ea_size);
4239 case SMB_INFO_IS_NAME_VALID:
4240 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4241 if (tran_call == TRANSACT2_QFILEINFO) {
4242 /* os/2 needs this ? really ?*/
4243 reply_doserror(req, ERRDOS, ERRbadfunc);
4250 case SMB_INFO_QUERY_EAS_FROM_LIST:
4252 size_t total_ea_len = 0;
4253 struct ea_list *ea_file_list = NULL;
4255 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4257 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4258 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4260 if (!ea_list || (total_ea_len > data_size)) {
4262 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4266 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4270 case SMB_INFO_QUERY_ALL_EAS:
4272 /* We have data_size bytes to put EA's into. */
4273 size_t total_ea_len = 0;
4275 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4277 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4278 if (!ea_list || (total_ea_len > data_size)) {
4280 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4284 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4288 case SMB_FILE_BASIC_INFORMATION:
4289 case SMB_QUERY_FILE_BASIC_INFO:
4291 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4292 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4293 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4295 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4299 put_long_date_timespec(pdata,create_time_ts);
4300 put_long_date_timespec(pdata+8,atime_ts);
4301 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4302 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4303 SIVAL(pdata,32,mode);
4305 DEBUG(5,("SMB_QFBI - "));
4306 DEBUG(5,("create: %s ", ctime(&create_time)));
4307 DEBUG(5,("access: %s ", ctime(&atime)));
4308 DEBUG(5,("write: %s ", ctime(&mtime)));
4309 DEBUG(5,("change: %s ", ctime(&mtime)));
4310 DEBUG(5,("mode: %x\n", mode));
4313 case SMB_FILE_STANDARD_INFORMATION:
4314 case SMB_QUERY_FILE_STANDARD_INFO:
4316 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4318 SOFF_T(pdata,0,allocation_size);
4319 SOFF_T(pdata,8,file_size);
4320 SIVAL(pdata,16,nlink);
4321 SCVAL(pdata,20,delete_pending?1:0);
4322 SCVAL(pdata,21,(mode&aDIR)?1:0);
4323 SSVAL(pdata,22,0); /* Padding. */
4326 case SMB_FILE_EA_INFORMATION:
4327 case SMB_QUERY_FILE_EA_INFO:
4329 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4330 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4332 SIVAL(pdata,0,ea_size);
4336 /* Get the 8.3 name - used if NT SMB was negotiated. */
4337 case SMB_QUERY_FILE_ALT_NAME_INFO:
4338 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4340 char mangled_name[13];
4341 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4342 if (!name_to_8_3(base_name,mangled_name,
4343 True,conn->params)) {
4346 NT_STATUS_NO_MEMORY);
4348 len = srvstr_push(dstart, req->flags2,
4349 pdata+4, mangled_name,
4350 PTR_DIFF(dend, pdata+4),
4352 data_size = 4 + len;
4357 case SMB_QUERY_FILE_NAME_INFO:
4359 this must be *exactly* right for ACLs on mapped drives to work
4361 len = srvstr_push(dstart, req->flags2,
4363 PTR_DIFF(dend, pdata+4),
4365 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4366 data_size = 4 + len;
4370 case SMB_FILE_ALLOCATION_INFORMATION:
4371 case SMB_QUERY_FILE_ALLOCATION_INFO:
4372 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4374 SOFF_T(pdata,0,allocation_size);
4377 case SMB_FILE_END_OF_FILE_INFORMATION:
4378 case SMB_QUERY_FILE_END_OF_FILEINFO:
4379 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4381 SOFF_T(pdata,0,file_size);
4384 case SMB_QUERY_FILE_ALL_INFO:
4385 case SMB_FILE_ALL_INFORMATION:
4387 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4388 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4389 put_long_date_timespec(pdata,create_time_ts);
4390 put_long_date_timespec(pdata+8,atime_ts);
4391 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4392 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4393 SIVAL(pdata,32,mode);
4394 SIVAL(pdata,36,0); /* padding. */
4396 SOFF_T(pdata,0,allocation_size);
4397 SOFF_T(pdata,8,file_size);
4398 SIVAL(pdata,16,nlink);
4399 SCVAL(pdata,20,delete_pending);
4400 SCVAL(pdata,21,(mode&aDIR)?1:0);
4403 SIVAL(pdata,0,ea_size);
4404 pdata += 4; /* EA info */
4405 len = srvstr_push(dstart, req->flags2,
4407 PTR_DIFF(dend, pdata+4),
4411 data_size = PTR_DIFF(pdata,(*ppdata));
4414 case SMB_FILE_INTERNAL_INFORMATION:
4415 /* This should be an index number - looks like
4418 I think this causes us to fail the IFSKIT
4419 BasicFileInformationTest. -tpot */
4421 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4422 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4423 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4427 case SMB_FILE_ACCESS_INFORMATION:
4428 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4430 SIVAL(pdata,0,fsp->access_mask);
4432 /* GENERIC_EXECUTE mapping from Windows */
4433 SIVAL(pdata,0,0x12019F);
4438 case SMB_FILE_NAME_INFORMATION:
4439 /* Pathname with leading '\'. */
4442 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4443 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4444 SIVAL(pdata,0,byte_len);
4445 data_size = 4 + byte_len;
4449 case SMB_FILE_DISPOSITION_INFORMATION:
4450 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4452 SCVAL(pdata,0,delete_pending);
4455 case SMB_FILE_POSITION_INFORMATION:
4456 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4458 SOFF_T(pdata,0,pos);
4461 case SMB_FILE_MODE_INFORMATION:
4462 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4463 SIVAL(pdata,0,mode);
4467 case SMB_FILE_ALIGNMENT_INFORMATION:
4468 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4469 SIVAL(pdata,0,0); /* No alignment needed. */
4474 * NT4 server just returns "invalid query" to this - if we try
4475 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4478 /* The first statement above is false - verified using Thursby
4479 * client against NT4 -- gcolley.
4481 case SMB_QUERY_FILE_STREAM_INFO:
4482 case SMB_FILE_STREAM_INFORMATION: {
4483 unsigned int num_streams;
4484 struct stream_struct *streams;
4487 DEBUG(10,("call_trans2qfilepathinfo: "
4488 "SMB_FILE_STREAM_INFORMATION\n"));
4490 status = SMB_VFS_STREAMINFO(
4491 conn, fsp, fname, talloc_tos(),
4492 &num_streams, &streams);
4494 if (!NT_STATUS_IS_OK(status)) {
4495 DEBUG(10, ("could not get stream info: %s\n",
4496 nt_errstr(status)));
4497 reply_nterror(req, status);
4501 status = marshall_stream_info(num_streams, streams,
4502 pdata, max_data_bytes,
4505 if (!NT_STATUS_IS_OK(status)) {
4506 DEBUG(10, ("marshall_stream_info failed: %s\n",
4507 nt_errstr(status)));
4508 reply_nterror(req, status);
4512 TALLOC_FREE(streams);
4516 case SMB_QUERY_COMPRESSION_INFO:
4517 case SMB_FILE_COMPRESSION_INFORMATION:
4518 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4519 SOFF_T(pdata,0,file_size);
4520 SIVAL(pdata,8,0); /* ??? */
4521 SIVAL(pdata,12,0); /* ??? */
4525 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4526 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4527 put_long_date_timespec(pdata,create_time_ts);
4528 put_long_date_timespec(pdata+8,atime_ts);
4529 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4530 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4531 SOFF_T(pdata,32,allocation_size);
4532 SOFF_T(pdata,40,file_size);
4533 SIVAL(pdata,48,mode);
4534 SIVAL(pdata,52,0); /* ??? */
4538 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4539 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4540 SIVAL(pdata,0,mode);
4546 * CIFS UNIX Extensions.
4549 case SMB_QUERY_FILE_UNIX_BASIC:
4551 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4552 data_size = PTR_DIFF(pdata,(*ppdata));
4556 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4558 for (i=0; i<100; i++)
4559 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4565 case SMB_QUERY_FILE_UNIX_INFO2:
4567 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4568 data_size = PTR_DIFF(pdata,(*ppdata));
4572 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4574 for (i=0; i<100; i++)
4575 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4581 case SMB_QUERY_FILE_UNIX_LINK:
4583 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4586 reply_nterror(req, NT_STATUS_NO_MEMORY);
4590 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4592 if(!S_ISLNK(sbuf.st_mode)) {
4593 reply_unixerror(req, ERRSRV,
4598 reply_unixerror(req, ERRDOS, ERRbadlink);
4601 len = SMB_VFS_READLINK(conn,fullpathname,
4604 reply_unixerror(req, ERRDOS,
4609 len = srvstr_push(dstart, req->flags2,
4611 PTR_DIFF(dend, pdata),
4614 data_size = PTR_DIFF(pdata,(*ppdata));
4619 #if defined(HAVE_POSIX_ACLS)
4620 case SMB_QUERY_POSIX_ACL:
4622 SMB_ACL_T file_acl = NULL;
4623 SMB_ACL_T def_acl = NULL;
4624 uint16 num_file_acls = 0;
4625 uint16 num_def_acls = 0;
4627 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4628 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4630 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4633 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4634 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4638 NT_STATUS_NOT_IMPLEMENTED);
4642 if (S_ISDIR(sbuf.st_mode)) {
4643 if (fsp && fsp->is_directory) {
4644 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4646 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4648 def_acl = free_empty_sys_acl(conn, def_acl);
4651 num_file_acls = count_acl_entries(conn, file_acl);
4652 num_def_acls = count_acl_entries(conn, def_acl);
4654 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4655 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4657 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4658 SMB_POSIX_ACL_HEADER_SIZE) ));
4660 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4663 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4667 NT_STATUS_BUFFER_TOO_SMALL);
4671 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4672 SSVAL(pdata,2,num_file_acls);
4673 SSVAL(pdata,4,num_def_acls);
4674 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4676 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4679 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4682 req, NT_STATUS_INTERNAL_ERROR);
4685 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4687 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4690 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4694 NT_STATUS_INTERNAL_ERROR);
4699 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4702 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4704 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4710 case SMB_QUERY_POSIX_LOCK:
4712 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4716 enum brl_type lock_type;
4718 if (total_data != POSIX_LOCK_DATA_SIZE) {
4720 req, NT_STATUS_INVALID_PARAMETER);
4724 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4725 case POSIX_LOCK_TYPE_READ:
4726 lock_type = READ_LOCK;
4728 case POSIX_LOCK_TYPE_WRITE:
4729 lock_type = WRITE_LOCK;
4731 case POSIX_LOCK_TYPE_UNLOCK:
4733 /* There's no point in asking for an unlock... */
4736 NT_STATUS_INVALID_PARAMETER);
4740 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4741 #if defined(HAVE_LONGLONG)
4742 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4743 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4744 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4745 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4746 #else /* HAVE_LONGLONG */
4747 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4748 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4749 #endif /* HAVE_LONGLONG */
4751 status = query_lock(fsp,
4758 if (ERROR_WAS_LOCK_DENIED(status)) {
4759 /* Here we need to report who has it locked... */
4760 data_size = POSIX_LOCK_DATA_SIZE;
4762 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4763 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4764 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4765 #if defined(HAVE_LONGLONG)
4766 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4767 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4768 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4769 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4770 #else /* HAVE_LONGLONG */
4771 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4772 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4773 #endif /* HAVE_LONGLONG */
4775 } else if (NT_STATUS_IS_OK(status)) {
4776 /* For success we just return a copy of what we sent
4777 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4778 data_size = POSIX_LOCK_DATA_SIZE;
4779 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4780 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4782 reply_nterror(req, status);
4789 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4793 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4799 /****************************************************************************
4800 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4802 ****************************************************************************/
4804 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4805 connection_struct *conn,
4806 const char *oldname_in,
4807 const char *newname_in)
4809 SMB_STRUCT_STAT sbuf1, sbuf2;
4810 char *last_component_oldname = NULL;
4811 char *last_component_newname = NULL;
4812 char *oldname = NULL;
4813 char *newname = NULL;
4814 NTSTATUS status = NT_STATUS_OK;
4819 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4820 &last_component_oldname, &sbuf1);
4821 if (!NT_STATUS_IS_OK(status)) {
4825 status = check_name(conn, oldname);
4826 if (!NT_STATUS_IS_OK(status)) {
4830 /* source must already exist. */
4831 if (!VALID_STAT(sbuf1)) {
4832 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4835 status = unix_convert(ctx, conn, newname_in, False, &newname,
4836 &last_component_newname, &sbuf2);
4837 if (!NT_STATUS_IS_OK(status)) {
4841 status = check_name(conn, newname);
4842 if (!NT_STATUS_IS_OK(status)) {
4846 /* Disallow if newname already exists. */
4847 if (VALID_STAT(sbuf2)) {
4848 return NT_STATUS_OBJECT_NAME_COLLISION;
4851 /* No links from a directory. */
4852 if (S_ISDIR(sbuf1.st_mode)) {
4853 return NT_STATUS_FILE_IS_A_DIRECTORY;
4856 /* Ensure this is within the share. */
4857 status = check_reduced_name(conn, oldname);
4858 if (!NT_STATUS_IS_OK(status)) {
4862 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4864 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4865 status = map_nt_error_from_unix(errno);
4866 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4867 nt_errstr(status), newname, oldname));
4873 /****************************************************************************
4874 Deal with setting the time from any of the setfilepathinfo functions.
4875 ****************************************************************************/
4877 NTSTATUS smb_set_file_time(connection_struct *conn,
4880 const SMB_STRUCT_STAT *psbuf,
4881 struct smb_file_time *ft,
4882 bool setting_write_time)
4885 FILE_NOTIFY_CHANGE_LAST_ACCESS
4886 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4888 if (!VALID_STAT(*psbuf)) {
4889 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4892 /* get some defaults (no modifications) if any info is zero or -1. */
4893 if (null_timespec(ft->atime)) {
4894 ft->atime= get_atimespec(psbuf);
4895 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4898 if (null_timespec(ft->mtime)) {
4899 ft->mtime = get_mtimespec(psbuf);
4900 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4903 if (!setting_write_time) {
4904 /* ft->mtime comes from change time, not write time. */
4905 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4908 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4909 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4910 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4911 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4912 if (!null_timespec(ft->create_time)) {
4913 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4914 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4918 * Try and set the times of this file if
4919 * they are different from the current values.
4923 struct timespec mts = get_mtimespec(psbuf);
4924 struct timespec ats = get_atimespec(psbuf);
4925 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4926 (timespec_compare(&ft->mtime, &mts) == 0)) {
4927 return NT_STATUS_OK;
4931 if (setting_write_time) {
4933 * This was a setfileinfo on an open file.
4934 * NT does this a lot. We also need to
4935 * set the time here, as it can be read by
4936 * FindFirst/FindNext and with the patch for bug #2045
4937 * in smbd/fileio.c it ensures that this timestamp is
4938 * kept sticky even after a write. We save the request
4939 * away and will set it on file close and after a write. JRA.
4942 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4943 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4946 if (fsp->base_fsp) {
4947 set_sticky_write_time_fsp(fsp->base_fsp,
4950 set_sticky_write_time_fsp(fsp, ft->mtime);
4953 set_sticky_write_time_path(conn, fname,
4954 vfs_file_id_from_sbuf(conn, psbuf),
4959 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4961 if (fsp && fsp->base_fsp) {
4962 fname = fsp->base_fsp->fsp_name;
4965 if(file_ntimes(conn, fname, ft)!=0) {
4966 return map_nt_error_from_unix(errno);
4968 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4970 return NT_STATUS_OK;
4973 /****************************************************************************
4974 Deal with setting the dosmode from any of the setfilepathinfo functions.
4975 ****************************************************************************/
4977 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4980 SMB_STRUCT_STAT *psbuf,
4983 if (!VALID_STAT(*psbuf)) {
4984 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4988 if (fsp->base_fsp) {
4989 fname = fsp->base_fsp->fsp_name;
4991 fname = fsp->fsp_name;
4996 if (S_ISDIR(psbuf->st_mode)) {
5003 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5005 /* check the mode isn't different, before changing it */
5006 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5008 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5009 fname, (unsigned int)dosmode ));
5011 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5012 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5013 fname, strerror(errno)));
5014 return map_nt_error_from_unix(errno);
5017 return NT_STATUS_OK;
5020 /****************************************************************************
5021 Deal with setting the size from any of the setfilepathinfo functions.
5022 ****************************************************************************/
5024 static NTSTATUS smb_set_file_size(connection_struct *conn,
5025 struct smb_request *req,
5028 SMB_STRUCT_STAT *psbuf,
5031 NTSTATUS status = NT_STATUS_OK;
5032 files_struct *new_fsp = NULL;
5034 if (!VALID_STAT(*psbuf)) {
5035 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5038 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5040 if (size == get_file_size_stat(psbuf)) {
5041 return NT_STATUS_OK;
5044 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5045 fname, (double)size ));
5047 if (fsp && fsp->fh->fd != -1) {
5048 /* Handle based call. */
5049 if (vfs_set_filelen(fsp, size) == -1) {
5050 return map_nt_error_from_unix(errno);
5052 trigger_write_time_update_immediate(fsp);
5053 return NT_STATUS_OK;
5056 status = SMB_VFS_CREATE_FILE(
5059 0, /* root_dir_fid */
5061 0, /* create_file_flags */
5062 FILE_WRITE_ATTRIBUTES, /* access_mask */
5063 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5065 FILE_OPEN, /* create_disposition*/
5066 0, /* create_options */
5067 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5068 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5069 0, /* allocation_size */
5072 &new_fsp, /* result */
5076 if (!NT_STATUS_IS_OK(status)) {
5077 /* NB. We check for open_was_deferred in the caller. */
5081 if (vfs_set_filelen(new_fsp, size) == -1) {
5082 status = map_nt_error_from_unix(errno);
5083 close_file(req, new_fsp,NORMAL_CLOSE);
5087 trigger_write_time_update_immediate(new_fsp);
5088 close_file(req, new_fsp,NORMAL_CLOSE);
5089 return NT_STATUS_OK;
5092 /****************************************************************************
5093 Deal with SMB_INFO_SET_EA.
5094 ****************************************************************************/
5096 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5102 struct ea_list *ea_list = NULL;
5103 TALLOC_CTX *ctx = NULL;
5104 NTSTATUS status = NT_STATUS_OK;
5106 if (total_data < 10) {
5108 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5109 length. They seem to have no effect. Bug #3212. JRA */
5111 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5112 /* We're done. We only get EA info in this call. */
5113 return NT_STATUS_OK;
5116 return NT_STATUS_INVALID_PARAMETER;
5119 if (IVAL(pdata,0) > total_data) {
5120 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5121 IVAL(pdata,0), (unsigned int)total_data));
5122 return NT_STATUS_INVALID_PARAMETER;
5126 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5128 return NT_STATUS_INVALID_PARAMETER;
5130 status = set_ea(conn, fsp, fname, ea_list);
5135 /****************************************************************************
5136 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5137 ****************************************************************************/
5139 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5144 SMB_STRUCT_STAT *psbuf)
5146 NTSTATUS status = NT_STATUS_OK;
5147 bool delete_on_close;
5150 if (total_data < 1) {
5151 return NT_STATUS_INVALID_PARAMETER;
5155 return NT_STATUS_INVALID_HANDLE;
5158 delete_on_close = (CVAL(pdata,0) ? True : False);
5159 dosmode = dos_mode(conn, fname, psbuf);
5161 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5162 "delete_on_close = %u\n",
5164 (unsigned int)dosmode,
5165 (unsigned int)delete_on_close ));
5167 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5169 if (!NT_STATUS_IS_OK(status)) {
5173 /* The set is across all open files on this dev/inode pair. */
5174 if (!set_delete_on_close(fsp, delete_on_close,
5175 &conn->server_info->utok)) {
5176 return NT_STATUS_ACCESS_DENIED;
5178 return NT_STATUS_OK;
5181 /****************************************************************************
5182 Deal with SMB_FILE_POSITION_INFORMATION.
5183 ****************************************************************************/
5185 static NTSTATUS smb_file_position_information(connection_struct *conn,
5190 uint64_t position_information;
5192 if (total_data < 8) {
5193 return NT_STATUS_INVALID_PARAMETER;
5197 /* Ignore on pathname based set. */
5198 return NT_STATUS_OK;
5201 position_information = (uint64_t)IVAL(pdata,0);
5202 #ifdef LARGE_SMB_OFF_T
5203 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5204 #else /* LARGE_SMB_OFF_T */
5205 if (IVAL(pdata,4) != 0) {
5206 /* more than 32 bits? */
5207 return NT_STATUS_INVALID_PARAMETER;
5209 #endif /* LARGE_SMB_OFF_T */
5211 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5212 fsp->fsp_name, (double)position_information ));
5213 fsp->fh->position_information = position_information;
5214 return NT_STATUS_OK;
5217 /****************************************************************************
5218 Deal with SMB_FILE_MODE_INFORMATION.
5219 ****************************************************************************/
5221 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5227 if (total_data < 4) {
5228 return NT_STATUS_INVALID_PARAMETER;
5230 mode = IVAL(pdata,0);
5231 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5232 return NT_STATUS_INVALID_PARAMETER;
5234 return NT_STATUS_OK;
5237 /****************************************************************************
5238 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5239 ****************************************************************************/
5241 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5242 struct smb_request *req,
5247 char *link_target = NULL;
5248 const char *newname = fname;
5249 NTSTATUS status = NT_STATUS_OK;
5250 TALLOC_CTX *ctx = talloc_tos();
5252 /* Set a symbolic link. */
5253 /* Don't allow this if follow links is false. */
5255 if (total_data == 0) {
5256 return NT_STATUS_INVALID_PARAMETER;
5259 if (!lp_symlinks(SNUM(conn))) {
5260 return NT_STATUS_ACCESS_DENIED;
5263 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5264 total_data, STR_TERMINATE);
5267 return NT_STATUS_INVALID_PARAMETER;
5270 /* !widelinks forces the target path to be within the share. */
5271 /* This means we can interpret the target as a pathname. */
5272 if (!lp_widelinks(SNUM(conn))) {
5273 char *rel_name = NULL;
5274 char *last_dirp = NULL;
5276 if (*link_target == '/') {
5277 /* No absolute paths allowed. */
5278 return NT_STATUS_ACCESS_DENIED;
5280 rel_name = talloc_strdup(ctx,newname);
5282 return NT_STATUS_NO_MEMORY;
5284 last_dirp = strrchr_m(rel_name, '/');
5286 last_dirp[1] = '\0';
5288 rel_name = talloc_strdup(ctx,"./");
5290 return NT_STATUS_NO_MEMORY;
5293 rel_name = talloc_asprintf_append(rel_name,
5297 return NT_STATUS_NO_MEMORY;
5300 status = check_name(conn, rel_name);
5301 if (!NT_STATUS_IS_OK(status)) {
5306 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5307 newname, link_target ));
5309 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5310 return map_nt_error_from_unix(errno);
5313 return NT_STATUS_OK;
5316 /****************************************************************************
5317 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5318 ****************************************************************************/
5320 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5321 struct smb_request *req,
5322 const char *pdata, int total_data,
5325 char *oldname = NULL;
5326 TALLOC_CTX *ctx = talloc_tos();
5327 NTSTATUS status = NT_STATUS_OK;
5329 /* Set a hard link. */
5330 if (total_data == 0) {
5331 return NT_STATUS_INVALID_PARAMETER;
5334 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5335 total_data, STR_TERMINATE, &status);
5336 if (!NT_STATUS_IS_OK(status)) {
5340 status = resolve_dfspath(ctx, conn,
5341 req->flags2 & FLAGS2_DFS_PATHNAMES,
5344 if (!NT_STATUS_IS_OK(status)) {
5348 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5351 return hardlink_internals(ctx, conn, oldname, fname);
5354 /****************************************************************************
5355 Deal with SMB_FILE_RENAME_INFORMATION.
5356 ****************************************************************************/
5358 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5359 struct smb_request *req,
5368 char *newname = NULL;
5369 char *base_name = NULL;
5370 bool dest_has_wcard = False;
5371 SMB_STRUCT_STAT sbuf;
5372 char *newname_last_component = NULL;
5373 NTSTATUS status = NT_STATUS_OK;
5375 TALLOC_CTX *ctx = talloc_tos();
5377 if (total_data < 13) {
5378 return NT_STATUS_INVALID_PARAMETER;
5383 overwrite = (CVAL(pdata,0) ? True : False);
5384 root_fid = IVAL(pdata,4);
5385 len = IVAL(pdata,8);
5387 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5388 return NT_STATUS_INVALID_PARAMETER;
5391 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5394 if (!NT_STATUS_IS_OK(status)) {
5398 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5401 status = resolve_dfspath_wcard(ctx, conn,
5402 req->flags2 & FLAGS2_DFS_PATHNAMES,
5406 if (!NT_STATUS_IS_OK(status)) {
5410 /* Check the new name has no '/' characters. */
5411 if (strchr_m(newname, '/')) {
5412 return NT_STATUS_NOT_SUPPORTED;
5415 if (fsp && fsp->base_fsp) {
5416 /* newname must be a stream name. */
5417 if (newname[0] != ':') {
5418 return NT_STATUS_NOT_SUPPORTED;
5420 base_name = talloc_asprintf(ctx, "%s%s",
5421 fsp->base_fsp->fsp_name,
5424 return NT_STATUS_NO_MEMORY;
5427 /* newname must *not* be a stream name. */
5428 if (is_ntfs_stream_name(newname)) {
5429 return NT_STATUS_NOT_SUPPORTED;
5432 /* Create the base directory. */
5433 base_name = talloc_strdup(ctx, fname);
5435 return NT_STATUS_NO_MEMORY;
5437 p = strrchr_m(base_name, '/');
5441 base_name = talloc_strdup(ctx, "./");
5443 return NT_STATUS_NO_MEMORY;
5446 /* Append the new name. */
5447 base_name = talloc_asprintf_append(base_name,
5451 return NT_STATUS_NO_MEMORY;
5454 status = unix_convert(ctx, conn, newname, False,
5456 &newname_last_component,
5459 /* If an error we expect this to be
5460 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5462 if (!NT_STATUS_IS_OK(status)
5463 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5470 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5471 fsp->fnum, fsp->fsp_name, base_name ));
5472 status = rename_internals_fsp(conn, fsp, base_name,
5473 newname_last_component, 0,
5476 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5477 fname, base_name ));
5478 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5479 overwrite, False, dest_has_wcard,
5480 FILE_WRITE_ATTRIBUTES);
5486 /****************************************************************************
5487 Deal with SMB_SET_POSIX_ACL.
5488 ****************************************************************************/
5490 #if defined(HAVE_POSIX_ACLS)
5491 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5496 SMB_STRUCT_STAT *psbuf)
5498 uint16 posix_acl_version;
5499 uint16 num_file_acls;
5500 uint16 num_def_acls;
5501 bool valid_file_acls = True;
5502 bool valid_def_acls = True;
5504 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5505 return NT_STATUS_INVALID_PARAMETER;
5507 posix_acl_version = SVAL(pdata,0);
5508 num_file_acls = SVAL(pdata,2);
5509 num_def_acls = SVAL(pdata,4);
5511 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5512 valid_file_acls = False;
5516 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5517 valid_def_acls = False;
5521 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5522 return NT_STATUS_INVALID_PARAMETER;
5525 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5526 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5527 return NT_STATUS_INVALID_PARAMETER;
5530 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5531 fname ? fname : fsp->fsp_name,
5532 (unsigned int)num_file_acls,
5533 (unsigned int)num_def_acls));
5535 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5536 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5537 return map_nt_error_from_unix(errno);
5540 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5541 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5542 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5543 return map_nt_error_from_unix(errno);
5545 return NT_STATUS_OK;
5549 /****************************************************************************
5550 Deal with SMB_SET_POSIX_LOCK.
5551 ****************************************************************************/
5553 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5554 struct smb_request *req,
5562 bool blocking_lock = False;
5563 enum brl_type lock_type;
5565 NTSTATUS status = NT_STATUS_OK;
5567 if (fsp == NULL || fsp->fh->fd == -1) {
5568 return NT_STATUS_INVALID_HANDLE;
5571 if (total_data != POSIX_LOCK_DATA_SIZE) {
5572 return NT_STATUS_INVALID_PARAMETER;
5575 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5576 case POSIX_LOCK_TYPE_READ:
5577 lock_type = READ_LOCK;
5579 case POSIX_LOCK_TYPE_WRITE:
5580 /* Return the right POSIX-mappable error code for files opened read-only. */
5581 if (!fsp->can_write) {
5582 return NT_STATUS_INVALID_HANDLE;
5584 lock_type = WRITE_LOCK;
5586 case POSIX_LOCK_TYPE_UNLOCK:
5587 lock_type = UNLOCK_LOCK;
5590 return NT_STATUS_INVALID_PARAMETER;
5593 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5594 blocking_lock = False;
5595 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5596 blocking_lock = True;
5598 return NT_STATUS_INVALID_PARAMETER;
5601 if (!lp_blocking_locks(SNUM(conn))) {
5602 blocking_lock = False;
5605 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5606 #if defined(HAVE_LONGLONG)
5607 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5608 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5609 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5610 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5611 #else /* HAVE_LONGLONG */
5612 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5613 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5614 #endif /* HAVE_LONGLONG */
5616 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5617 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5619 (unsigned int)lock_type,
5620 (unsigned int)lock_pid,
5624 if (lock_type == UNLOCK_LOCK) {
5625 status = do_unlock(smbd_messaging_context(),
5632 uint32 block_smbpid;
5634 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5646 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5648 * A blocking lock was requested. Package up
5649 * this smb into a queued request and push it
5650 * onto the blocking lock queue.
5652 if(push_blocking_lock_request(br_lck,
5655 -1, /* infinite timeout. */
5663 TALLOC_FREE(br_lck);
5667 TALLOC_FREE(br_lck);
5673 /****************************************************************************
5674 Deal with SMB_INFO_STANDARD.
5675 ****************************************************************************/
5677 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5682 const SMB_STRUCT_STAT *psbuf)
5684 struct smb_file_time ft;
5687 if (total_data < 12) {
5688 return NT_STATUS_INVALID_PARAMETER;
5692 ft.create_time = interpret_long_date(pdata);
5695 ft.atime = interpret_long_date(pdata + 8);
5698 ft.mtime = interpret_long_date(pdata + 16);
5700 DEBUG(10,("smb_set_info_standard: file %s\n",
5701 fname ? fname : fsp->fsp_name ));
5703 return smb_set_file_time(conn,
5711 /****************************************************************************
5712 Deal with SMB_SET_FILE_BASIC_INFO.
5713 ****************************************************************************/
5715 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5720 SMB_STRUCT_STAT *psbuf)
5722 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5723 struct timespec write_time;
5724 struct timespec changed_time;
5725 struct smb_file_time ft;
5727 NTSTATUS status = NT_STATUS_OK;
5728 bool setting_write_time = true;
5732 if (total_data < 36) {
5733 return NT_STATUS_INVALID_PARAMETER;
5736 /* Set the attributes */
5737 dosmode = IVAL(pdata,32);
5738 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5739 if (!NT_STATUS_IS_OK(status)) {
5744 ft.atime = interpret_long_date(pdata+8);
5746 write_time = interpret_long_date(pdata+16);
5747 changed_time = interpret_long_date(pdata+24);
5750 ft.mtime = timespec_min(&write_time, &changed_time);
5753 ft.create_time = interpret_long_date(pdata);
5755 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5756 !null_timespec(write_time)) {
5757 ft.mtime = write_time;
5760 /* Prefer a defined time to an undefined one. */
5761 if (null_timespec(ft.mtime)) {
5762 if (null_timespec(write_time)) {
5763 ft.mtime = changed_time;
5764 setting_write_time = false;
5766 ft.mtime = write_time;
5770 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5771 fname ? fname : fsp->fsp_name ));
5773 return smb_set_file_time(conn,
5778 setting_write_time);
5781 /****************************************************************************
5782 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5783 ****************************************************************************/
5785 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5786 struct smb_request *req,
5791 SMB_STRUCT_STAT *psbuf)
5793 uint64_t allocation_size = 0;
5794 NTSTATUS status = NT_STATUS_OK;
5795 files_struct *new_fsp = NULL;
5797 if (!VALID_STAT(*psbuf)) {
5798 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5801 if (total_data < 8) {
5802 return NT_STATUS_INVALID_PARAMETER;
5805 allocation_size = (uint64_t)IVAL(pdata,0);
5806 #ifdef LARGE_SMB_OFF_T
5807 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5808 #else /* LARGE_SMB_OFF_T */
5809 if (IVAL(pdata,4) != 0) {
5810 /* more than 32 bits? */
5811 return NT_STATUS_INVALID_PARAMETER;
5813 #endif /* LARGE_SMB_OFF_T */
5815 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5816 fname, (double)allocation_size ));
5818 if (allocation_size) {
5819 allocation_size = smb_roundup(conn, allocation_size);
5822 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5823 fname, (double)allocation_size ));
5825 if (fsp && fsp->fh->fd != -1) {
5826 /* Open file handle. */
5827 /* Only change if needed. */
5828 if (allocation_size != get_file_size_stat(psbuf)) {
5829 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5830 return map_nt_error_from_unix(errno);
5833 /* But always update the time. */
5835 * This is equivalent to a write. Ensure it's seen immediately
5836 * if there are no pending writes.
5838 trigger_write_time_update_immediate(fsp);
5839 return NT_STATUS_OK;
5842 /* Pathname or stat or directory file. */
5844 status = SMB_VFS_CREATE_FILE(
5847 0, /* root_dir_fid */
5849 0, /* create_file_flags */
5850 FILE_WRITE_DATA, /* access_mask */
5851 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5853 FILE_OPEN, /* create_disposition*/
5854 0, /* create_options */
5855 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5856 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5857 0, /* allocation_size */
5860 &new_fsp, /* result */
5864 if (!NT_STATUS_IS_OK(status)) {
5865 /* NB. We check for open_was_deferred in the caller. */
5869 /* Only change if needed. */
5870 if (allocation_size != get_file_size_stat(psbuf)) {
5871 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5872 status = map_nt_error_from_unix(errno);
5873 close_file(req, new_fsp, NORMAL_CLOSE);
5878 /* Changing the allocation size should set the last mod time. */
5880 * This is equivalent to a write. Ensure it's seen immediately
5881 * if there are no pending writes.
5883 trigger_write_time_update_immediate(new_fsp);
5885 close_file(req, new_fsp, NORMAL_CLOSE);
5886 return NT_STATUS_OK;
5889 /****************************************************************************
5890 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5891 ****************************************************************************/
5893 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5894 struct smb_request *req,
5899 SMB_STRUCT_STAT *psbuf)
5903 if (total_data < 8) {
5904 return NT_STATUS_INVALID_PARAMETER;
5907 size = IVAL(pdata,0);
5908 #ifdef LARGE_SMB_OFF_T
5909 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5910 #else /* LARGE_SMB_OFF_T */
5911 if (IVAL(pdata,4) != 0) {
5912 /* more than 32 bits? */
5913 return NT_STATUS_INVALID_PARAMETER;
5915 #endif /* LARGE_SMB_OFF_T */
5916 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5917 "file %s to %.0f\n", fname, (double)size ));
5919 return smb_set_file_size(conn, req,
5926 /****************************************************************************
5927 Allow a UNIX info mknod.
5928 ****************************************************************************/
5930 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5934 SMB_STRUCT_STAT *psbuf)
5936 uint32 file_type = IVAL(pdata,56);
5937 #if defined(HAVE_MAKEDEV)
5938 uint32 dev_major = IVAL(pdata,60);
5939 uint32 dev_minor = IVAL(pdata,68);
5941 SMB_DEV_T dev = (SMB_DEV_T)0;
5942 uint32 raw_unixmode = IVAL(pdata,84);
5946 if (total_data < 100) {
5947 return NT_STATUS_INVALID_PARAMETER;
5950 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5951 if (!NT_STATUS_IS_OK(status)) {
5955 #if defined(HAVE_MAKEDEV)
5956 dev = makedev(dev_major, dev_minor);
5959 switch (file_type) {
5960 #if defined(S_IFIFO)
5961 case UNIX_TYPE_FIFO:
5962 unixmode |= S_IFIFO;
5965 #if defined(S_IFSOCK)
5966 case UNIX_TYPE_SOCKET:
5967 unixmode |= S_IFSOCK;
5970 #if defined(S_IFCHR)
5971 case UNIX_TYPE_CHARDEV:
5972 unixmode |= S_IFCHR;
5975 #if defined(S_IFBLK)
5976 case UNIX_TYPE_BLKDEV:
5977 unixmode |= S_IFBLK;
5981 return NT_STATUS_INVALID_PARAMETER;
5984 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5985 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5987 /* Ok - do the mknod. */
5988 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5989 return map_nt_error_from_unix(errno);
5992 /* If any of the other "set" calls fail we
5993 * don't want to end up with a half-constructed mknod.
5996 if (lp_inherit_perms(SNUM(conn))) {
5998 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
5999 return NT_STATUS_NO_MEMORY;
6001 inherit_access_posix_acl(conn, parent, fname, unixmode);
6002 TALLOC_FREE(parent);
6005 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6006 status = map_nt_error_from_unix(errno);
6007 SMB_VFS_UNLINK(conn,fname);
6010 return NT_STATUS_OK;
6013 /****************************************************************************
6014 Deal with SMB_SET_FILE_UNIX_BASIC.
6015 ****************************************************************************/
6017 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6018 struct smb_request *req,
6023 SMB_STRUCT_STAT *psbuf)
6025 struct smb_file_time ft;
6026 uint32 raw_unixmode;
6029 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6030 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6031 NTSTATUS status = NT_STATUS_OK;
6032 bool delete_on_fail = False;
6033 enum perm_type ptype;
6037 if (total_data < 100) {
6038 return NT_STATUS_INVALID_PARAMETER;
6041 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6042 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6043 size=IVAL(pdata,0); /* first 8 Bytes are size */
6044 #ifdef LARGE_SMB_OFF_T
6045 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6046 #else /* LARGE_SMB_OFF_T */
6047 if (IVAL(pdata,4) != 0) {
6048 /* more than 32 bits? */
6049 return NT_STATUS_INVALID_PARAMETER;
6051 #endif /* LARGE_SMB_OFF_T */
6054 ft.atime = interpret_long_date(pdata+24); /* access_time */
6055 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6056 set_owner = (uid_t)IVAL(pdata,40);
6057 set_grp = (gid_t)IVAL(pdata,48);
6058 raw_unixmode = IVAL(pdata,84);
6060 if (VALID_STAT(*psbuf)) {
6061 if (S_ISDIR(psbuf->st_mode)) {
6062 ptype = PERM_EXISTING_DIR;
6064 ptype = PERM_EXISTING_FILE;
6067 ptype = PERM_NEW_FILE;
6070 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6071 if (!NT_STATUS_IS_OK(status)) {
6075 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6076 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6077 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6079 if (!VALID_STAT(*psbuf)) {
6081 * The only valid use of this is to create character and block
6082 * devices, and named pipes. This is deprecated (IMHO) and
6083 * a new info level should be used for mknod. JRA.
6086 status = smb_unix_mknod(conn,
6091 if (!NT_STATUS_IS_OK(status)) {
6095 /* Ensure we don't try and change anything else. */
6096 raw_unixmode = SMB_MODE_NO_CHANGE;
6097 size = get_file_size_stat(psbuf);
6098 ft.atime = get_atimespec(psbuf);
6099 ft.mtime = get_mtimespec(psbuf);
6101 * We continue here as we might want to change the
6104 delete_on_fail = True;
6108 /* Horrible backwards compatibility hack as an old server bug
6109 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6113 size = get_file_size_stat(psbuf);
6118 * Deal with the UNIX specific mode set.
6121 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6122 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6123 (unsigned int)unixmode, fname ));
6124 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6125 return map_nt_error_from_unix(errno);
6130 * Deal with the UNIX specific uid set.
6133 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6136 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6137 (unsigned int)set_owner, fname ));
6139 if (S_ISLNK(psbuf->st_mode)) {
6140 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6142 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6146 status = map_nt_error_from_unix(errno);
6147 if (delete_on_fail) {
6148 SMB_VFS_UNLINK(conn,fname);
6155 * Deal with the UNIX specific gid set.
6158 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6159 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6160 (unsigned int)set_owner, fname ));
6161 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6162 status = map_nt_error_from_unix(errno);
6163 if (delete_on_fail) {
6164 SMB_VFS_UNLINK(conn,fname);
6170 /* Deal with any size changes. */
6172 status = smb_set_file_size(conn, req,
6177 if (!NT_STATUS_IS_OK(status)) {
6181 /* Deal with any time changes. */
6183 return smb_set_file_time(conn,
6191 /****************************************************************************
6192 Deal with SMB_SET_FILE_UNIX_INFO2.
6193 ****************************************************************************/
6195 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6196 struct smb_request *req,
6201 SMB_STRUCT_STAT *psbuf)
6207 if (total_data < 116) {
6208 return NT_STATUS_INVALID_PARAMETER;
6211 /* Start by setting all the fields that are common between UNIX_BASIC
6214 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6216 if (!NT_STATUS_IS_OK(status)) {
6220 smb_fflags = IVAL(pdata, 108);
6221 smb_fmask = IVAL(pdata, 112);
6223 /* NB: We should only attempt to alter the file flags if the client
6224 * sends a non-zero mask.
6226 if (smb_fmask != 0) {
6227 int stat_fflags = 0;
6229 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6231 /* Client asked to alter a flag we don't understand. */
6232 return NT_STATUS_INVALID_PARAMETER;
6235 if (fsp && fsp->fh->fd != -1) {
6236 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6237 return NT_STATUS_NOT_SUPPORTED;
6239 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6240 return map_nt_error_from_unix(errno);
6245 /* XXX: need to add support for changing the create_time here. You
6246 * can do this for paths on Darwin with setattrlist(2). The right way
6247 * to hook this up is probably by extending the VFS utimes interface.
6250 return NT_STATUS_OK;
6253 /****************************************************************************
6254 Create a directory with POSIX semantics.
6255 ****************************************************************************/
6257 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6258 struct smb_request *req,
6262 SMB_STRUCT_STAT *psbuf,
6263 int *pdata_return_size)
6265 NTSTATUS status = NT_STATUS_OK;
6266 uint32 raw_unixmode = 0;
6267 uint32 mod_unixmode = 0;
6268 mode_t unixmode = (mode_t)0;
6269 files_struct *fsp = NULL;
6270 uint16 info_level_return = 0;
6272 char *pdata = *ppdata;
6274 if (total_data < 18) {
6275 return NT_STATUS_INVALID_PARAMETER;
6278 raw_unixmode = IVAL(pdata,8);
6279 /* Next 4 bytes are not yet defined. */
6281 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6282 if (!NT_STATUS_IS_OK(status)) {
6286 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6288 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6289 fname, (unsigned int)unixmode ));
6291 status = SMB_VFS_CREATE_FILE(
6294 0, /* root_dir_fid */
6296 0, /* create_file_flags */
6297 FILE_READ_ATTRIBUTES, /* access_mask */
6298 FILE_SHARE_NONE, /* share_access */
6299 FILE_CREATE, /* create_disposition*/
6300 FILE_DIRECTORY_FILE, /* create_options */
6301 mod_unixmode, /* file_attributes */
6302 0, /* oplock_request */
6303 0, /* allocation_size */
6310 if (NT_STATUS_IS_OK(status)) {
6311 close_file(req, fsp, NORMAL_CLOSE);
6314 info_level_return = SVAL(pdata,16);
6316 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6317 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6318 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6319 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6321 *pdata_return_size = 12;
6324 /* Realloc the data size */
6325 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6326 if (*ppdata == NULL) {
6327 *pdata_return_size = 0;
6328 return NT_STATUS_NO_MEMORY;
6332 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6333 SSVAL(pdata,2,0); /* No fnum. */
6334 SIVAL(pdata,4,info); /* Was directory created. */
6336 switch (info_level_return) {
6337 case SMB_QUERY_FILE_UNIX_BASIC:
6338 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6339 SSVAL(pdata,10,0); /* Padding. */
6340 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6342 case SMB_QUERY_FILE_UNIX_INFO2:
6343 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6344 SSVAL(pdata,10,0); /* Padding. */
6345 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6348 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6349 SSVAL(pdata,10,0); /* Padding. */
6356 /****************************************************************************
6357 Open/Create a file with POSIX semantics.
6358 ****************************************************************************/
6360 static NTSTATUS smb_posix_open(connection_struct *conn,
6361 struct smb_request *req,
6365 SMB_STRUCT_STAT *psbuf,
6366 int *pdata_return_size)
6368 bool extended_oplock_granted = False;
6369 char *pdata = *ppdata;
6371 uint32 wire_open_mode = 0;
6372 uint32 raw_unixmode = 0;
6373 uint32 mod_unixmode = 0;
6374 uint32 create_disp = 0;
6375 uint32 access_mask = 0;
6376 uint32 create_options = 0;
6377 NTSTATUS status = NT_STATUS_OK;
6378 mode_t unixmode = (mode_t)0;
6379 files_struct *fsp = NULL;
6380 int oplock_request = 0;
6382 uint16 info_level_return = 0;
6384 if (total_data < 18) {
6385 return NT_STATUS_INVALID_PARAMETER;
6388 flags = IVAL(pdata,0);
6389 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6390 if (oplock_request) {
6391 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6394 wire_open_mode = IVAL(pdata,4);
6396 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6397 return smb_posix_mkdir(conn, req,
6405 switch (wire_open_mode & SMB_ACCMODE) {
6407 access_mask = FILE_READ_DATA;
6410 access_mask = FILE_WRITE_DATA;
6413 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6416 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6417 (unsigned int)wire_open_mode ));
6418 return NT_STATUS_INVALID_PARAMETER;
6421 wire_open_mode &= ~SMB_ACCMODE;
6423 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6424 create_disp = FILE_CREATE;
6425 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6426 create_disp = FILE_OVERWRITE_IF;
6427 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6428 create_disp = FILE_OPEN_IF;
6429 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6430 create_disp = FILE_OPEN;
6432 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6433 (unsigned int)wire_open_mode ));
6434 return NT_STATUS_INVALID_PARAMETER;
6437 raw_unixmode = IVAL(pdata,8);
6438 /* Next 4 bytes are not yet defined. */
6440 status = unix_perms_from_wire(conn,
6443 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6446 if (!NT_STATUS_IS_OK(status)) {
6450 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6452 if (wire_open_mode & SMB_O_SYNC) {
6453 create_options |= FILE_WRITE_THROUGH;
6455 if (wire_open_mode & SMB_O_APPEND) {
6456 access_mask |= FILE_APPEND_DATA;
6458 if (wire_open_mode & SMB_O_DIRECT) {
6459 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6462 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6464 (unsigned int)wire_open_mode,
6465 (unsigned int)unixmode ));
6467 status = SMB_VFS_CREATE_FILE(
6470 0, /* root_dir_fid */
6472 0, /* create_file_flags */
6473 access_mask, /* access_mask */
6474 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6476 create_disp, /* create_disposition*/
6477 0, /* create_options */
6478 mod_unixmode, /* file_attributes */
6479 oplock_request, /* oplock_request */
6480 0, /* allocation_size */
6487 if (!NT_STATUS_IS_OK(status)) {
6491 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6492 extended_oplock_granted = True;
6495 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6496 extended_oplock_granted = True;
6499 info_level_return = SVAL(pdata,16);
6501 /* Allocate the correct return size. */
6503 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6504 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6505 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6506 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6508 *pdata_return_size = 12;
6511 /* Realloc the data size */
6512 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6513 if (*ppdata == NULL) {
6514 close_file(req, fsp, ERROR_CLOSE);
6515 *pdata_return_size = 0;
6516 return NT_STATUS_NO_MEMORY;
6520 if (extended_oplock_granted) {
6521 if (flags & REQUEST_BATCH_OPLOCK) {
6522 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6524 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6526 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6527 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6529 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6532 SSVAL(pdata,2,fsp->fnum);
6533 SIVAL(pdata,4,info); /* Was file created etc. */
6535 switch (info_level_return) {
6536 case SMB_QUERY_FILE_UNIX_BASIC:
6537 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6538 SSVAL(pdata,10,0); /* padding. */
6539 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6541 case SMB_QUERY_FILE_UNIX_INFO2:
6542 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6543 SSVAL(pdata,10,0); /* padding. */
6544 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6547 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6548 SSVAL(pdata,10,0); /* padding. */
6551 return NT_STATUS_OK;
6554 /****************************************************************************
6555 Delete a file with POSIX semantics.
6556 ****************************************************************************/
6558 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6559 struct smb_request *req,
6563 SMB_STRUCT_STAT *psbuf)
6565 NTSTATUS status = NT_STATUS_OK;
6566 files_struct *fsp = NULL;
6570 int create_options = 0;
6572 struct share_mode_lock *lck = NULL;
6574 if (total_data < 2) {
6575 return NT_STATUS_INVALID_PARAMETER;
6578 flags = SVAL(pdata,0);
6580 if (!VALID_STAT(*psbuf)) {
6581 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6584 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6585 !VALID_STAT_OF_DIR(*psbuf)) {
6586 return NT_STATUS_NOT_A_DIRECTORY;
6589 DEBUG(10,("smb_posix_unlink: %s %s\n",
6590 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6593 if (VALID_STAT_OF_DIR(*psbuf)) {
6594 create_options |= FILE_DIRECTORY_FILE;
6597 status = SMB_VFS_CREATE_FILE(
6600 0, /* root_dir_fid */
6602 0, /* create_file_flags */
6603 DELETE_ACCESS, /* access_mask */
6604 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6606 FILE_OPEN, /* create_disposition*/
6607 create_options, /* create_options */
6608 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6609 0, /* oplock_request */
6610 0, /* allocation_size */
6617 if (!NT_STATUS_IS_OK(status)) {
6622 * Don't lie to client. If we can't really delete due to
6623 * non-POSIX opens return SHARING_VIOLATION.
6626 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6629 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6630 "lock for file %s\n", fsp->fsp_name));
6631 close_file(req, fsp, NORMAL_CLOSE);
6632 return NT_STATUS_INVALID_PARAMETER;
6636 * See if others still have the file open. If this is the case, then
6637 * don't delete. If all opens are POSIX delete we can set the delete
6638 * on close disposition.
6640 for (i=0; i<lck->num_share_modes; i++) {
6641 struct share_mode_entry *e = &lck->share_modes[i];
6642 if (is_valid_share_mode_entry(e)) {
6643 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6646 /* Fail with sharing violation. */
6647 close_file(req, fsp, NORMAL_CLOSE);
6649 return NT_STATUS_SHARING_VIOLATION;
6654 * Set the delete on close.
6656 status = smb_set_file_disposition_info(conn,
6663 if (!NT_STATUS_IS_OK(status)) {
6664 close_file(req, fsp, NORMAL_CLOSE);
6669 return close_file(req, fsp, NORMAL_CLOSE);
6672 /****************************************************************************
6673 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6674 ****************************************************************************/
6676 static void call_trans2setfilepathinfo(connection_struct *conn,
6677 struct smb_request *req,
6678 unsigned int tran_call,
6679 char **pparams, int total_params,
6680 char **ppdata, int total_data,
6681 unsigned int max_data_bytes)
6683 char *params = *pparams;
6684 char *pdata = *ppdata;
6686 SMB_STRUCT_STAT sbuf;
6688 files_struct *fsp = NULL;
6689 NTSTATUS status = NT_STATUS_OK;
6690 int data_return_size = 0;
6691 TALLOC_CTX *ctx = talloc_tos();
6694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6700 if (tran_call == TRANSACT2_SETFILEINFO) {
6701 if (total_params < 4) {
6702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6706 fsp = file_fsp(req, SVAL(params,0));
6707 /* Basic check for non-null fsp. */
6708 if (!check_fsp_open(conn, req, fsp)) {
6711 info_level = SVAL(params,2);
6713 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6715 reply_nterror(req, NT_STATUS_NO_MEMORY);
6719 if(fsp->is_directory || fsp->fh->fd == -1) {
6721 * This is actually a SETFILEINFO on a directory
6722 * handle (returned from an NT SMB). NT5.0 seems
6723 * to do this call. JRA.
6725 if (INFO_LEVEL_IS_UNIX(info_level)) {
6726 /* Always do lstat for UNIX calls. */
6727 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6728 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6729 reply_unixerror(req,ERRDOS,ERRbadpath);
6733 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6734 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6735 reply_unixerror(req,ERRDOS,ERRbadpath);
6739 } else if (fsp->print_file) {
6741 * Doing a DELETE_ON_CLOSE should cancel a print job.
6743 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6744 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6746 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6749 send_trans2_replies(conn, req, params, 2,
6754 reply_unixerror(req, ERRDOS, ERRbadpath);
6759 * Original code - this is an open file.
6761 if (!check_fsp(conn, req, fsp)) {
6765 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6766 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6767 reply_unixerror(req, ERRDOS, ERRbadfid);
6773 if (total_params < 7) {
6774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6778 info_level = SVAL(params,0);
6779 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6780 total_params - 6, STR_TERMINATE,
6782 if (!NT_STATUS_IS_OK(status)) {
6783 reply_nterror(req, status);
6787 status = resolve_dfspath(ctx, conn,
6788 req->flags2 & FLAGS2_DFS_PATHNAMES,
6791 if (!NT_STATUS_IS_OK(status)) {
6792 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6793 reply_botherror(req,
6794 NT_STATUS_PATH_NOT_COVERED,
6795 ERRSRV, ERRbadpath);
6798 reply_nterror(req, status);
6802 status = unix_convert(ctx, conn, fname, False,
6803 &fname, NULL, &sbuf);
6804 if (!NT_STATUS_IS_OK(status)) {
6805 reply_nterror(req, status);
6809 status = check_name(conn, fname);
6810 if (!NT_STATUS_IS_OK(status)) {
6811 reply_nterror(req, status);
6815 if (INFO_LEVEL_IS_UNIX(info_level)) {
6817 * For CIFS UNIX extensions the target name may not exist.
6820 /* Always do lstat for UNIX calls. */
6821 SMB_VFS_LSTAT(conn,fname,&sbuf);
6823 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6824 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6825 reply_unixerror(req, ERRDOS, ERRbadpath);
6830 if (!CAN_WRITE(conn)) {
6831 reply_doserror(req, ERRSRV, ERRaccess);
6835 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6836 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6840 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6841 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6843 /* Realloc the parameter size */
6844 *pparams = (char *)SMB_REALLOC(*pparams,2);
6845 if (*pparams == NULL) {
6846 reply_nterror(req, NT_STATUS_NO_MEMORY);
6853 switch (info_level) {
6855 case SMB_INFO_STANDARD:
6857 status = smb_set_info_standard(conn,
6866 case SMB_INFO_SET_EA:
6868 status = smb_info_set_ea(conn,
6876 case SMB_SET_FILE_BASIC_INFO:
6877 case SMB_FILE_BASIC_INFORMATION:
6879 status = smb_set_file_basic_info(conn,
6888 case SMB_FILE_ALLOCATION_INFORMATION:
6889 case SMB_SET_FILE_ALLOCATION_INFO:
6891 status = smb_set_file_allocation_info(conn, req,
6900 case SMB_FILE_END_OF_FILE_INFORMATION:
6901 case SMB_SET_FILE_END_OF_FILE_INFO:
6903 status = smb_set_file_end_of_file_info(conn, req,
6912 case SMB_FILE_DISPOSITION_INFORMATION:
6913 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6916 /* JRA - We used to just ignore this on a path ?
6917 * Shouldn't this be invalid level on a pathname
6920 if (tran_call != TRANSACT2_SETFILEINFO) {
6921 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6924 status = smb_set_file_disposition_info(conn,
6933 case SMB_FILE_POSITION_INFORMATION:
6935 status = smb_file_position_information(conn,
6942 /* From tridge Samba4 :
6943 * MODE_INFORMATION in setfileinfo (I have no
6944 * idea what "mode information" on a file is - it takes a value of 0,
6945 * 2, 4 or 6. What could it be?).
6948 case SMB_FILE_MODE_INFORMATION:
6950 status = smb_file_mode_information(conn,
6957 * CIFS UNIX extensions.
6960 case SMB_SET_FILE_UNIX_BASIC:
6962 status = smb_set_file_unix_basic(conn, req,
6971 case SMB_SET_FILE_UNIX_INFO2:
6973 status = smb_set_file_unix_info2(conn, req,
6982 case SMB_SET_FILE_UNIX_LINK:
6984 if (tran_call != TRANSACT2_SETPATHINFO) {
6985 /* We must have a pathname for this. */
6986 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6989 status = smb_set_file_unix_link(conn, req, pdata,
6994 case SMB_SET_FILE_UNIX_HLINK:
6996 if (tran_call != TRANSACT2_SETPATHINFO) {
6997 /* We must have a pathname for this. */
6998 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7001 status = smb_set_file_unix_hlink(conn, req,
7007 case SMB_FILE_RENAME_INFORMATION:
7009 status = smb_file_rename_information(conn, req,
7015 #if defined(HAVE_POSIX_ACLS)
7016 case SMB_SET_POSIX_ACL:
7018 status = smb_set_posix_acl(conn,
7028 case SMB_SET_POSIX_LOCK:
7030 if (tran_call != TRANSACT2_SETFILEINFO) {
7031 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7034 status = smb_set_posix_lock(conn, req,
7035 pdata, total_data, fsp);
7039 case SMB_POSIX_PATH_OPEN:
7041 if (tran_call != TRANSACT2_SETPATHINFO) {
7042 /* We must have a pathname for this. */
7043 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7047 status = smb_posix_open(conn, req,
7056 case SMB_POSIX_PATH_UNLINK:
7058 if (tran_call != TRANSACT2_SETPATHINFO) {
7059 /* We must have a pathname for this. */
7060 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7064 status = smb_posix_unlink(conn, req,
7073 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7078 if (!NT_STATUS_IS_OK(status)) {
7079 if (open_was_deferred(req->mid)) {
7080 /* We have re-scheduled this call. */
7083 if (blocking_lock_was_deferred(req->mid)) {
7084 /* We have re-scheduled this call. */
7087 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7088 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7089 ERRSRV, ERRbadpath);
7092 if (info_level == SMB_POSIX_PATH_OPEN) {
7093 reply_openerror(req, status);
7097 reply_nterror(req, status);
7102 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7108 /****************************************************************************
7109 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7110 ****************************************************************************/
7112 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7113 char **pparams, int total_params,
7114 char **ppdata, int total_data,
7115 unsigned int max_data_bytes)
7117 char *params = *pparams;
7118 char *pdata = *ppdata;
7119 char *directory = NULL;
7120 SMB_STRUCT_STAT sbuf;
7121 NTSTATUS status = NT_STATUS_OK;
7122 struct ea_list *ea_list = NULL;
7123 TALLOC_CTX *ctx = talloc_tos();
7125 if (!CAN_WRITE(conn)) {
7126 reply_doserror(req, ERRSRV, ERRaccess);
7130 if (total_params < 5) {
7131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7135 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7136 total_params - 4, STR_TERMINATE,
7138 if (!NT_STATUS_IS_OK(status)) {
7139 reply_nterror(req, status);
7143 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7145 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7146 if (!NT_STATUS_IS_OK(status)) {
7147 reply_nterror(req, status);
7151 status = check_name(conn, directory);
7152 if (!NT_STATUS_IS_OK(status)) {
7153 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7154 reply_nterror(req, status);
7158 /* Any data in this call is an EA list. */
7159 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7160 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7165 * OS/2 workplace shell seems to send SET_EA requests of "null"
7166 * length (4 bytes containing IVAL 4).
7167 * They seem to have no effect. Bug #3212. JRA.
7170 if (total_data != 4) {
7171 if (total_data < 10) {
7172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7176 if (IVAL(pdata,0) > total_data) {
7177 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7178 IVAL(pdata,0), (unsigned int)total_data));
7179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7183 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7190 /* If total_data == 4 Windows doesn't care what values
7191 * are placed in that field, it just ignores them.
7192 * The System i QNTC IBM SMB client puts bad values here,
7193 * so ignore them. */
7195 status = create_directory(conn, req, directory);
7197 if (!NT_STATUS_IS_OK(status)) {
7198 reply_nterror(req, status);
7202 /* Try and set any given EA. */
7204 status = set_ea(conn, NULL, directory, ea_list);
7205 if (!NT_STATUS_IS_OK(status)) {
7206 reply_nterror(req, status);
7211 /* Realloc the parameter and data sizes */
7212 *pparams = (char *)SMB_REALLOC(*pparams,2);
7213 if(*pparams == NULL) {
7214 reply_nterror(req, NT_STATUS_NO_MEMORY);
7221 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7226 /****************************************************************************
7227 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7228 We don't actually do this - we just send a null response.
7229 ****************************************************************************/
7231 static void call_trans2findnotifyfirst(connection_struct *conn,
7232 struct smb_request *req,
7233 char **pparams, int total_params,
7234 char **ppdata, int total_data,
7235 unsigned int max_data_bytes)
7237 char *params = *pparams;
7240 if (total_params < 6) {
7241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7245 info_level = SVAL(params,4);
7246 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7248 switch (info_level) {
7253 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7257 /* Realloc the parameter and data sizes */
7258 *pparams = (char *)SMB_REALLOC(*pparams,6);
7259 if (*pparams == NULL) {
7260 reply_nterror(req, NT_STATUS_NO_MEMORY);
7265 SSVAL(params,0,fnf_handle);
7266 SSVAL(params,2,0); /* No changes */
7267 SSVAL(params,4,0); /* No EA errors */
7274 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7279 /****************************************************************************
7280 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7281 changes). Currently this does nothing.
7282 ****************************************************************************/
7284 static void call_trans2findnotifynext(connection_struct *conn,
7285 struct smb_request *req,
7286 char **pparams, int total_params,
7287 char **ppdata, int total_data,
7288 unsigned int max_data_bytes)
7290 char *params = *pparams;
7292 DEBUG(3,("call_trans2findnotifynext\n"));
7294 /* Realloc the parameter and data sizes */
7295 *pparams = (char *)SMB_REALLOC(*pparams,4);
7296 if (*pparams == NULL) {
7297 reply_nterror(req, NT_STATUS_NO_MEMORY);
7302 SSVAL(params,0,0); /* No changes */
7303 SSVAL(params,2,0); /* No EA errors */
7305 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7310 /****************************************************************************
7311 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7312 ****************************************************************************/
7314 static void call_trans2getdfsreferral(connection_struct *conn,
7315 struct smb_request *req,
7316 char **pparams, int total_params,
7317 char **ppdata, int total_data,
7318 unsigned int max_data_bytes)
7320 char *params = *pparams;
7321 char *pathname = NULL;
7323 int max_referral_level;
7324 NTSTATUS status = NT_STATUS_OK;
7325 TALLOC_CTX *ctx = talloc_tos();
7327 DEBUG(10,("call_trans2getdfsreferral\n"));
7329 if (total_params < 3) {
7330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7334 max_referral_level = SVAL(params,0);
7336 if(!lp_host_msdfs()) {
7337 reply_doserror(req, ERRDOS, ERRbadfunc);
7341 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7342 total_params - 2, STR_TERMINATE);
7344 reply_nterror(req, NT_STATUS_NOT_FOUND);
7347 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7348 ppdata,&status)) < 0) {
7349 reply_nterror(req, status);
7353 SSVAL(req->inbuf, smb_flg2,
7354 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7355 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7360 #define LMCAT_SPL 0x53
7361 #define LMFUNC_GETJOBID 0x60
7363 /****************************************************************************
7364 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7365 ****************************************************************************/
7367 static void call_trans2ioctl(connection_struct *conn,
7368 struct smb_request *req,
7369 char **pparams, int total_params,
7370 char **ppdata, int total_data,
7371 unsigned int max_data_bytes)
7373 char *pdata = *ppdata;
7374 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7376 /* check for an invalid fid before proceeding */
7379 reply_doserror(req, ERRDOS, ERRbadfid);
7383 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7384 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7385 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7386 if (*ppdata == NULL) {
7387 reply_nterror(req, NT_STATUS_NO_MEMORY);
7392 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7393 CAN ACCEPT THIS IN UNICODE. JRA. */
7395 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7396 srvstr_push(pdata, req->flags2, pdata + 2,
7397 global_myname(), 15,
7398 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7399 srvstr_push(pdata, req->flags2, pdata+18,
7400 lp_servicename(SNUM(conn)), 13,
7401 STR_ASCII|STR_TERMINATE); /* Service name */
7402 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7407 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7408 reply_doserror(req, ERRSRV, ERRerror);
7411 /****************************************************************************
7412 Reply to a SMBfindclose (stop trans2 directory search).
7413 ****************************************************************************/
7415 void reply_findclose(struct smb_request *req)
7419 START_PROFILE(SMBfindclose);
7422 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7423 END_PROFILE(SMBfindclose);
7427 dptr_num = SVALS(req->vwv+0, 0);
7429 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7431 dptr_close(&dptr_num);
7433 reply_outbuf(req, 0, 0);
7435 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7437 END_PROFILE(SMBfindclose);
7441 /****************************************************************************
7442 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7443 ****************************************************************************/
7445 void reply_findnclose(struct smb_request *req)
7449 START_PROFILE(SMBfindnclose);
7452 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7453 END_PROFILE(SMBfindnclose);
7457 dptr_num = SVAL(req->vwv+0, 0);
7459 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7461 /* We never give out valid handles for a
7462 findnotifyfirst - so any dptr_num is ok here.
7465 reply_outbuf(req, 0, 0);
7467 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7469 END_PROFILE(SMBfindnclose);
7473 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7474 struct trans_state *state)
7476 if (Protocol >= PROTOCOL_NT1) {
7477 req->flags2 |= 0x40; /* IS_LONG_NAME */
7478 SSVAL(req->inbuf,smb_flg2,req->flags2);
7481 if (conn->encrypt_level == Required && !req->encrypted) {
7482 if (state->call != TRANSACT2_QFSINFO &&
7483 state->call != TRANSACT2_SETFSINFO) {
7484 DEBUG(0,("handle_trans2: encryption required "
7486 (unsigned int)state->call));
7487 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7492 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7494 /* Now we must call the relevant TRANS2 function */
7495 switch(state->call) {
7496 case TRANSACT2_OPEN:
7498 START_PROFILE(Trans2_open);
7499 call_trans2open(conn, req,
7500 &state->param, state->total_param,
7501 &state->data, state->total_data,
7502 state->max_data_return);
7503 END_PROFILE(Trans2_open);
7507 case TRANSACT2_FINDFIRST:
7509 START_PROFILE(Trans2_findfirst);
7510 call_trans2findfirst(conn, req,
7511 &state->param, state->total_param,
7512 &state->data, state->total_data,
7513 state->max_data_return);
7514 END_PROFILE(Trans2_findfirst);
7518 case TRANSACT2_FINDNEXT:
7520 START_PROFILE(Trans2_findnext);
7521 call_trans2findnext(conn, req,
7522 &state->param, state->total_param,
7523 &state->data, state->total_data,
7524 state->max_data_return);
7525 END_PROFILE(Trans2_findnext);
7529 case TRANSACT2_QFSINFO:
7531 START_PROFILE(Trans2_qfsinfo);
7532 call_trans2qfsinfo(conn, req,
7533 &state->param, state->total_param,
7534 &state->data, state->total_data,
7535 state->max_data_return);
7536 END_PROFILE(Trans2_qfsinfo);
7540 case TRANSACT2_SETFSINFO:
7542 START_PROFILE(Trans2_setfsinfo);
7543 call_trans2setfsinfo(conn, req,
7544 &state->param, state->total_param,
7545 &state->data, state->total_data,
7546 state->max_data_return);
7547 END_PROFILE(Trans2_setfsinfo);
7551 case TRANSACT2_QPATHINFO:
7552 case TRANSACT2_QFILEINFO:
7554 START_PROFILE(Trans2_qpathinfo);
7555 call_trans2qfilepathinfo(conn, req, state->call,
7556 &state->param, state->total_param,
7557 &state->data, state->total_data,
7558 state->max_data_return);
7559 END_PROFILE(Trans2_qpathinfo);
7563 case TRANSACT2_SETPATHINFO:
7564 case TRANSACT2_SETFILEINFO:
7566 START_PROFILE(Trans2_setpathinfo);
7567 call_trans2setfilepathinfo(conn, req, state->call,
7568 &state->param, state->total_param,
7569 &state->data, state->total_data,
7570 state->max_data_return);
7571 END_PROFILE(Trans2_setpathinfo);
7575 case TRANSACT2_FINDNOTIFYFIRST:
7577 START_PROFILE(Trans2_findnotifyfirst);
7578 call_trans2findnotifyfirst(conn, req,
7579 &state->param, state->total_param,
7580 &state->data, state->total_data,
7581 state->max_data_return);
7582 END_PROFILE(Trans2_findnotifyfirst);
7586 case TRANSACT2_FINDNOTIFYNEXT:
7588 START_PROFILE(Trans2_findnotifynext);
7589 call_trans2findnotifynext(conn, req,
7590 &state->param, state->total_param,
7591 &state->data, state->total_data,
7592 state->max_data_return);
7593 END_PROFILE(Trans2_findnotifynext);
7597 case TRANSACT2_MKDIR:
7599 START_PROFILE(Trans2_mkdir);
7600 call_trans2mkdir(conn, req,
7601 &state->param, state->total_param,
7602 &state->data, state->total_data,
7603 state->max_data_return);
7604 END_PROFILE(Trans2_mkdir);
7608 case TRANSACT2_GET_DFS_REFERRAL:
7610 START_PROFILE(Trans2_get_dfs_referral);
7611 call_trans2getdfsreferral(conn, req,
7612 &state->param, state->total_param,
7613 &state->data, state->total_data,
7614 state->max_data_return);
7615 END_PROFILE(Trans2_get_dfs_referral);
7619 case TRANSACT2_IOCTL:
7621 START_PROFILE(Trans2_ioctl);
7622 call_trans2ioctl(conn, req,
7623 &state->param, state->total_param,
7624 &state->data, state->total_data,
7625 state->max_data_return);
7626 END_PROFILE(Trans2_ioctl);
7631 /* Error in request */
7632 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7633 reply_doserror(req, ERRSRV,ERRerror);
7637 /****************************************************************************
7638 Reply to a SMBtrans2.
7639 ****************************************************************************/
7641 void reply_trans2(struct smb_request *req)
7643 connection_struct *conn = req->conn;
7648 unsigned int tran_call;
7649 struct trans_state *state;
7652 START_PROFILE(SMBtrans2);
7654 if (req->wct < 14) {
7655 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7656 END_PROFILE(SMBtrans2);
7660 dsoff = SVAL(req->vwv+12, 0);
7661 dscnt = SVAL(req->vwv+11, 0);
7662 psoff = SVAL(req->vwv+10, 0);
7663 pscnt = SVAL(req->vwv+9, 0);
7664 tran_call = SVAL(req->vwv+14, 0);
7666 result = allow_new_trans(conn->pending_trans, req->mid);
7667 if (!NT_STATUS_IS_OK(result)) {
7668 DEBUG(2, ("Got invalid trans2 request: %s\n",
7669 nt_errstr(result)));
7670 reply_nterror(req, result);
7671 END_PROFILE(SMBtrans2);
7676 switch (tran_call) {
7677 /* List the allowed trans2 calls on IPC$ */
7678 case TRANSACT2_OPEN:
7679 case TRANSACT2_GET_DFS_REFERRAL:
7680 case TRANSACT2_QFILEINFO:
7681 case TRANSACT2_QFSINFO:
7682 case TRANSACT2_SETFSINFO:
7685 reply_doserror(req, ERRSRV, ERRaccess);
7686 END_PROFILE(SMBtrans2);
7691 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7692 DEBUG(0, ("talloc failed\n"));
7693 reply_nterror(req, NT_STATUS_NO_MEMORY);
7694 END_PROFILE(SMBtrans2);
7698 state->cmd = SMBtrans2;
7700 state->mid = req->mid;
7701 state->vuid = req->vuid;
7702 state->setup_count = SVAL(req->vwv+13, 0);
7703 state->setup = NULL;
7704 state->total_param = SVAL(req->vwv+0, 0);
7705 state->param = NULL;
7706 state->total_data = SVAL(req->vwv+1, 0);
7708 state->max_param_return = SVAL(req->vwv+2, 0);
7709 state->max_data_return = SVAL(req->vwv+3, 0);
7710 state->max_setup_return = SVAL(req->vwv+4, 0);
7711 state->close_on_completion = BITSETW(req->vwv+5, 0);
7712 state->one_way = BITSETW(req->vwv+5, 1);
7714 state->call = tran_call;
7716 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7717 is so as a sanity check */
7718 if (state->setup_count != 1) {
7720 * Need to have rc=0 for ioctl to get job id for OS/2.
7721 * Network printing will fail if function is not successful.
7722 * Similar function in reply.c will be used if protocol
7723 * is LANMAN1.0 instead of LM1.2X002.
7724 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7725 * outbuf doesn't have to be set(only job id is used).
7727 if ( (state->setup_count == 4)
7728 && (tran_call == TRANSACT2_IOCTL)
7729 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7730 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7731 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7733 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7734 DEBUG(2,("Transaction is %d\n",tran_call));
7736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7737 END_PROFILE(SMBtrans2);
7742 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7745 if (state->total_data) {
7747 if (trans_oob(state->total_data, 0, dscnt)
7748 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7752 /* Can't use talloc here, the core routines do realloc on the
7753 * params and data. */
7754 state->data = (char *)SMB_MALLOC(state->total_data);
7755 if (state->data == NULL) {
7756 DEBUG(0,("reply_trans2: data malloc fail for %u "
7757 "bytes !\n", (unsigned int)state->total_data));
7759 reply_nterror(req, NT_STATUS_NO_MEMORY);
7760 END_PROFILE(SMBtrans2);
7764 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7767 if (state->total_param) {
7769 if (trans_oob(state->total_param, 0, pscnt)
7770 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7774 /* Can't use talloc here, the core routines do realloc on the
7775 * params and data. */
7776 state->param = (char *)SMB_MALLOC(state->total_param);
7777 if (state->param == NULL) {
7778 DEBUG(0,("reply_trans: param malloc fail for %u "
7779 "bytes !\n", (unsigned int)state->total_param));
7780 SAFE_FREE(state->data);
7782 reply_nterror(req, NT_STATUS_NO_MEMORY);
7783 END_PROFILE(SMBtrans2);
7787 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7790 state->received_data = dscnt;
7791 state->received_param = pscnt;
7793 if ((state->received_param == state->total_param) &&
7794 (state->received_data == state->total_data)) {
7796 handle_trans2(conn, req, state);
7798 SAFE_FREE(state->data);
7799 SAFE_FREE(state->param);
7801 END_PROFILE(SMBtrans2);
7805 DLIST_ADD(conn->pending_trans, state);
7807 /* We need to send an interim response then receive the rest
7808 of the parameter/data bytes */
7809 reply_outbuf(req, 0, 0);
7810 show_msg((char *)req->outbuf);
7811 END_PROFILE(SMBtrans2);
7816 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7817 SAFE_FREE(state->data);
7818 SAFE_FREE(state->param);
7820 END_PROFILE(SMBtrans2);
7821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7825 /****************************************************************************
7826 Reply to a SMBtranss2
7827 ****************************************************************************/
7829 void reply_transs2(struct smb_request *req)
7831 connection_struct *conn = req->conn;
7832 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7833 struct trans_state *state;
7835 START_PROFILE(SMBtranss2);
7837 show_msg((char *)req->inbuf);
7840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7841 END_PROFILE(SMBtranss2);
7845 for (state = conn->pending_trans; state != NULL;
7846 state = state->next) {
7847 if (state->mid == req->mid) {
7852 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7853 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7854 END_PROFILE(SMBtranss2);
7858 /* Revise state->total_param and state->total_data in case they have
7859 changed downwards */
7861 if (SVAL(req->vwv+0, 0) < state->total_param)
7862 state->total_param = SVAL(req->vwv+0, 0);
7863 if (SVAL(req->vwv+1, 0) < state->total_data)
7864 state->total_data = SVAL(req->vwv+1, 0);
7866 pcnt = SVAL(req->vwv+2, 0);
7867 poff = SVAL(req->vwv+3, 0);
7868 pdisp = SVAL(req->vwv+4, 0);
7870 dcnt = SVAL(req->vwv+5, 0);
7871 doff = SVAL(req->vwv+6, 0);
7872 ddisp = SVAL(req->vwv+7, 0);
7874 state->received_param += pcnt;
7875 state->received_data += dcnt;
7877 if ((state->received_data > state->total_data) ||
7878 (state->received_param > state->total_param))
7882 if (trans_oob(state->total_param, pdisp, pcnt)
7883 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7886 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7890 if (trans_oob(state->total_data, ddisp, dcnt)
7891 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7894 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7897 if ((state->received_param < state->total_param) ||
7898 (state->received_data < state->total_data)) {
7899 END_PROFILE(SMBtranss2);
7903 handle_trans2(conn, req, state);
7905 DLIST_REMOVE(conn->pending_trans, state);
7906 SAFE_FREE(state->data);
7907 SAFE_FREE(state->param);
7910 END_PROFILE(SMBtranss2);
7915 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7916 DLIST_REMOVE(conn->pending_trans, state);
7917 SAFE_FREE(state->data);
7918 SAFE_FREE(state->param);
7920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7921 END_PROFILE(SMBtranss2);