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(),
835 IS_CONN_ENCRYPTED(conn),
837 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
839 TALLOC_FREE(req->outbuf);
841 pp += params_sent_thistime;
842 pd += data_sent_thistime;
844 params_to_send -= params_sent_thistime;
845 data_to_send -= data_sent_thistime;
848 if(params_to_send < 0 || data_to_send < 0) {
849 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
850 params_to_send, data_to_send));
858 /****************************************************************************
859 Reply to a TRANSACT2_OPEN.
860 ****************************************************************************/
862 static void call_trans2open(connection_struct *conn,
863 struct smb_request *req,
864 char **pparams, int total_params,
865 char **ppdata, int total_data,
866 unsigned int max_data_bytes)
868 char *params = *pparams;
869 char *pdata = *ppdata;
874 bool return_additional_info;
885 SMB_STRUCT_STAT sbuf;
888 struct ea_list *ea_list = NULL;
893 uint32 create_disposition;
894 uint32 create_options = 0;
895 TALLOC_CTX *ctx = talloc_tos();
897 SET_STAT_INVALID(sbuf);
900 * Ensure we have enough parameters to perform the operation.
903 if (total_params < 29) {
904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
908 flags = SVAL(params, 0);
909 deny_mode = SVAL(params, 2);
910 open_attr = SVAL(params,6);
911 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
912 if (oplock_request) {
913 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
917 return_additional_info = BITSETW(params,0);
918 open_sattr = SVAL(params, 4);
919 open_time = make_unix_date3(params+8);
921 open_ofun = SVAL(params,12);
922 open_size = IVAL(params,14);
926 reply_doserror(req, ERRSRV, ERRaccess);
930 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
931 total_params - 28, STR_TERMINATE,
933 if (!NT_STATUS_IS_OK(status)) {
934 reply_nterror(req, status);
938 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
939 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
940 (unsigned int)open_ofun, open_size));
942 if (open_ofun == 0) {
943 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
947 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
952 reply_doserror(req, ERRDOS, ERRbadaccess);
956 /* Any data in this call is an EA list. */
957 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
958 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
962 if (total_data != 4) {
963 if (total_data < 10) {
964 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
968 if (IVAL(pdata,0) > total_data) {
969 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
970 IVAL(pdata,0), (unsigned int)total_data));
971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
975 ea_list = read_ea_list(talloc_tos(), pdata + 4,
978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
981 } else if (IVAL(pdata,0) != 4) {
982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
986 status = SMB_VFS_CREATE_FILE(
989 0, /* root_dir_fid */
991 CFF_DOS_PATH, /* create_file_flags */
992 access_mask, /* access_mask */
993 share_mode, /* share_access */
994 create_disposition, /* create_disposition*/
995 create_options, /* create_options */
996 open_attr, /* file_attributes */
997 oplock_request, /* oplock_request */
998 open_size, /* allocation_size */
1000 ea_list, /* ea_list */
1002 &smb_action, /* pinfo */
1005 if (!NT_STATUS_IS_OK(status)) {
1006 if (open_was_deferred(req->mid)) {
1007 /* We have re-scheduled this call. */
1010 reply_openerror(req, status);
1014 size = get_file_size_stat(&sbuf);
1015 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1016 mtime = sbuf.st_mtime;
1017 inode = sbuf.st_ino;
1019 close_file(req, fsp, ERROR_CLOSE);
1020 reply_doserror(req, ERRDOS,ERRnoaccess);
1024 /* Realloc the size of parameters and data we will return */
1025 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1026 if(*pparams == NULL ) {
1027 reply_nterror(req, NT_STATUS_NO_MEMORY);
1032 SSVAL(params,0,fsp->fnum);
1033 SSVAL(params,2,fattr);
1034 srv_put_dos_date2(params,4, mtime);
1035 SIVAL(params,8, (uint32)size);
1036 SSVAL(params,12,deny_mode);
1037 SSVAL(params,14,0); /* open_type - file or directory. */
1038 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1040 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1041 smb_action |= EXTENDED_OPLOCK_GRANTED;
1044 SSVAL(params,18,smb_action);
1047 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1049 SIVAL(params,20,inode);
1050 SSVAL(params,24,0); /* Padding. */
1052 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1053 SIVAL(params, 26, ea_size);
1055 SIVAL(params, 26, 0);
1058 /* Send the required number of replies */
1059 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1062 /*********************************************************
1063 Routine to check if a given string matches exactly.
1064 as a special case a mask of "." does NOT match. That
1065 is required for correct wildcard semantics
1066 Case can be significant or not.
1067 **********************************************************/
1069 static bool exact_match(connection_struct *conn,
1073 if (mask[0] == '.' && mask[1] == 0)
1075 if (dptr_has_wild(conn->dirptr)) {
1078 if (conn->case_sensitive)
1079 return strcmp(str,mask)==0;
1081 return StrCaseCmp(str,mask) == 0;
1084 /****************************************************************************
1085 Return the filetype for UNIX extensions.
1086 ****************************************************************************/
1088 static uint32 unix_filetype(mode_t mode)
1091 return UNIX_TYPE_FILE;
1092 else if(S_ISDIR(mode))
1093 return UNIX_TYPE_DIR;
1095 else if(S_ISLNK(mode))
1096 return UNIX_TYPE_SYMLINK;
1099 else if(S_ISCHR(mode))
1100 return UNIX_TYPE_CHARDEV;
1103 else if(S_ISBLK(mode))
1104 return UNIX_TYPE_BLKDEV;
1107 else if(S_ISFIFO(mode))
1108 return UNIX_TYPE_FIFO;
1111 else if(S_ISSOCK(mode))
1112 return UNIX_TYPE_SOCKET;
1115 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1116 return UNIX_TYPE_UNKNOWN;
1119 /****************************************************************************
1120 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1121 ****************************************************************************/
1123 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1125 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1126 SMB_STRUCT_STAT *psbuf,
1128 enum perm_type ptype,
1133 if (perms == SMB_MODE_NO_CHANGE) {
1134 if (!VALID_STAT(*psbuf)) {
1135 return NT_STATUS_INVALID_PARAMETER;
1137 *ret_perms = psbuf->st_mode;
1138 return NT_STATUS_OK;
1142 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1143 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1144 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1145 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1146 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1147 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1148 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1149 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1150 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1152 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1155 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1158 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1163 /* Apply mode mask */
1164 ret &= lp_create_mask(SNUM(conn));
1165 /* Add in force bits */
1166 ret |= lp_force_create_mode(SNUM(conn));
1169 ret &= lp_dir_mask(SNUM(conn));
1170 /* Add in force bits */
1171 ret |= lp_force_dir_mode(SNUM(conn));
1173 case PERM_EXISTING_FILE:
1174 /* Apply mode mask */
1175 ret &= lp_security_mask(SNUM(conn));
1176 /* Add in force bits */
1177 ret |= lp_force_security_mode(SNUM(conn));
1179 case PERM_EXISTING_DIR:
1180 /* Apply mode mask */
1181 ret &= lp_dir_security_mask(SNUM(conn));
1182 /* Add in force bits */
1183 ret |= lp_force_dir_security_mode(SNUM(conn));
1188 return NT_STATUS_OK;
1191 /****************************************************************************
1192 Needed to show the msdfs symlinks as directories. Modifies psbuf
1193 to be a directory if it's a msdfs link.
1194 ****************************************************************************/
1196 static bool check_msdfs_link(connection_struct *conn,
1197 const char *pathname,
1198 SMB_STRUCT_STAT *psbuf)
1200 int saved_errno = errno;
1201 if(lp_host_msdfs() &&
1202 lp_msdfs_root(SNUM(conn)) &&
1203 is_msdfs_link(conn, pathname, psbuf)) {
1205 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1208 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1209 errno = saved_errno;
1212 errno = saved_errno;
1217 /****************************************************************************
1218 Get a level dependent lanman2 dir entry.
1219 ****************************************************************************/
1221 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1222 connection_struct *conn,
1224 const char *path_mask,
1227 int requires_resume_key,
1233 int space_remaining,
1235 bool *got_exact_match,
1236 int *last_entry_off,
1237 struct ea_list *name_list)
1241 SMB_STRUCT_STAT sbuf;
1242 const char *mask = NULL;
1243 char *pathreal = NULL;
1245 char *p, *q, *pdata = *ppdata;
1249 SMB_OFF_T file_size = 0;
1250 uint64_t allocation_size = 0;
1252 struct timespec mdate_ts, adate_ts, create_date_ts;
1253 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1255 char *last_entry_ptr;
1257 uint32 nt_extmode; /* Used for NT connections instead of mode */
1258 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1259 bool check_mangled_names = lp_manglednames(conn->params);
1260 char mangled_name[13]; /* mangled 8.3 name. */
1262 *out_of_space = False;
1263 *got_exact_match = False;
1265 ZERO_STRUCT(mdate_ts);
1266 ZERO_STRUCT(adate_ts);
1267 ZERO_STRUCT(create_date_ts);
1269 if (!conn->dirptr) {
1273 p = strrchr_m(path_mask,'/');
1276 mask = talloc_strdup(ctx,"*.*");
1286 bool ms_dfs_link = False;
1288 /* Needed if we run out of space */
1289 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1290 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1293 * Due to bugs in NT client redirectors we are not using
1294 * resume keys any more - set them to zero.
1295 * Check out the related comments in findfirst/findnext.
1301 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1302 (long)conn->dirptr,curr_dirpos));
1309 * fname may get mangled, dname is never mangled.
1310 * Whenever we're accessing the filesystem we use
1311 * pathreal which is composed from dname.
1317 /* Mangle fname if it's an illegal name. */
1318 if (mangle_must_mangle(dname,conn->params)) {
1319 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1321 continue; /* Error - couldn't mangle. */
1323 fname = talloc_strdup(ctx, mangled_name);
1329 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1330 got_match = mask_match(fname, mask, conn->case_sensitive);
1333 if(!got_match && check_mangled_names &&
1334 !mangle_is_8_3(fname, False, conn->params)) {
1336 * It turns out that NT matches wildcards against
1337 * both long *and* short names. This may explain some
1338 * of the wildcard wierdness from old DOS clients
1339 * that some people have been seeing.... JRA.
1341 /* Force the mangling into 8.3. */
1342 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1344 continue; /* Error - couldn't mangle. */
1347 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1348 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1353 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1355 if (dont_descend && !isdots) {
1362 pathreal = talloc_asprintf(ctx,
1367 pathreal = talloc_asprintf(ctx,
1378 if (INFO_LEVEL_IS_UNIX(info_level)) {
1379 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1380 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1381 pathreal,strerror(errno)));
1382 TALLOC_FREE(pathreal);
1386 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1387 /* Needed to show the msdfs symlinks as
1390 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1392 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1393 pathreal,strerror(errno)));
1394 TALLOC_FREE(pathreal);
1401 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1403 mode = dos_mode(conn,pathreal,&sbuf);
1406 if (!dir_check_ftype(conn,mode,dirtype)) {
1407 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1408 TALLOC_FREE(pathreal);
1413 if (!(mode & aDIR)) {
1414 file_size = get_file_size_stat(&sbuf);
1416 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1418 mdate_ts = get_mtimespec(&sbuf);
1419 adate_ts = get_atimespec(&sbuf);
1420 create_date_ts = get_create_timespec(&sbuf,
1421 lp_fake_dir_create_times(SNUM(conn)));
1423 if (ask_sharemode) {
1424 struct timespec write_time_ts;
1425 struct file_id fileid;
1427 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1428 get_file_infos(fileid, NULL, &write_time_ts);
1429 if (!null_timespec(write_time_ts)) {
1430 mdate_ts = write_time_ts;
1434 if (lp_dos_filetime_resolution(SNUM(conn))) {
1435 dos_filetime_timespec(&create_date_ts);
1436 dos_filetime_timespec(&mdate_ts);
1437 dos_filetime_timespec(&adate_ts);
1440 create_date = convert_timespec_to_time_t(create_date_ts);
1441 mdate = convert_timespec_to_time_t(mdate_ts);
1442 adate = convert_timespec_to_time_t(adate_ts);
1444 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1449 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1459 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1461 switch (info_level) {
1462 case SMB_FIND_INFO_STANDARD:
1463 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1464 if(requires_resume_key) {
1468 srv_put_dos_date2(p,0,create_date);
1469 srv_put_dos_date2(p,4,adate);
1470 srv_put_dos_date2(p,8,mdate);
1471 SIVAL(p,12,(uint32)file_size);
1472 SIVAL(p,16,(uint32)allocation_size);
1476 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1477 p += ucs2_align(base_data, p, 0);
1479 len = srvstr_push(base_data, flags2, p,
1480 fname, PTR_DIFF(end_data, p),
1482 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1484 SCVAL(nameptr, -1, len - 2);
1486 SCVAL(nameptr, -1, 0);
1490 SCVAL(nameptr, -1, len - 1);
1492 SCVAL(nameptr, -1, 0);
1498 case SMB_FIND_EA_SIZE:
1499 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1500 if(requires_resume_key) {
1504 srv_put_dos_date2(p,0,create_date);
1505 srv_put_dos_date2(p,4,adate);
1506 srv_put_dos_date2(p,8,mdate);
1507 SIVAL(p,12,(uint32)file_size);
1508 SIVAL(p,16,(uint32)allocation_size);
1511 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1512 SIVAL(p,22,ea_size); /* Extended attributes */
1516 len = srvstr_push(base_data, flags2,
1517 p, fname, PTR_DIFF(end_data, p),
1518 STR_TERMINATE | STR_NOALIGN);
1519 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1532 SCVAL(nameptr,0,len);
1534 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1537 case SMB_FIND_EA_LIST:
1539 struct ea_list *file_list = NULL;
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1546 if(requires_resume_key) {
1550 srv_put_dos_date2(p,0,create_date);
1551 srv_put_dos_date2(p,4,adate);
1552 srv_put_dos_date2(p,8,mdate);
1553 SIVAL(p,12,(uint32)file_size);
1554 SIVAL(p,16,(uint32)allocation_size);
1556 p += 22; /* p now points to the EA area. */
1558 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1559 name_list = ea_list_union(name_list, file_list, &ea_len);
1561 /* We need to determine if this entry will fit in the space available. */
1562 /* Max string size is 255 bytes. */
1563 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1564 /* Move the dirptr back to prev_dirpos */
1565 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566 *out_of_space = True;
1567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568 return False; /* Not finished - just out of space */
1571 /* Push the ea_data followed by the name. */
1572 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1574 len = srvstr_push(base_data, flags2,
1575 p + 1, fname, PTR_DIFF(end_data, p+1),
1576 STR_TERMINATE | STR_NOALIGN);
1577 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1590 SCVAL(nameptr,0,len);
1592 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1596 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1597 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1598 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1600 SIVAL(p,0,reskey); p += 4;
1601 put_long_date_timespec(p,create_date_ts); p += 8;
1602 put_long_date_timespec(p,adate_ts); p += 8;
1603 put_long_date_timespec(p,mdate_ts); p += 8;
1604 put_long_date_timespec(p,mdate_ts); p += 8;
1605 SOFF_T(p,0,file_size); p += 8;
1606 SOFF_T(p,0,allocation_size); p += 8;
1607 SIVAL(p,0,nt_extmode); p += 4;
1608 q = p; p += 4; /* q is placeholder for name length. */
1610 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1611 SIVAL(p,0,ea_size); /* Extended attributes */
1614 /* Clear the short name buffer. This is
1615 * IMPORTANT as not doing so will trigger
1616 * a Win2k client bug. JRA.
1618 if (!was_8_3 && check_mangled_names) {
1619 if (!name_to_8_3(fname,mangled_name,True,
1621 /* Error - mangle failed ! */
1622 memset(mangled_name,'\0',12);
1624 mangled_name[12] = 0;
1625 len = srvstr_push(base_data, flags2,
1626 p+2, mangled_name, 24,
1627 STR_UPPER|STR_UNICODE);
1629 memset(p + 2 + len,'\0',24 - len);
1636 len = srvstr_push(base_data, flags2, p,
1637 fname, PTR_DIFF(end_data, p),
1638 STR_TERMINATE_ASCII);
1641 SIVAL(p,0,0); /* Ensure any padding is null. */
1642 len = PTR_DIFF(p, pdata);
1643 len = (len + 3) & ~3;
1648 case SMB_FIND_FILE_DIRECTORY_INFO:
1649 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1651 SIVAL(p,0,reskey); p += 4;
1652 put_long_date_timespec(p,create_date_ts); p += 8;
1653 put_long_date_timespec(p,adate_ts); p += 8;
1654 put_long_date_timespec(p,mdate_ts); p += 8;
1655 put_long_date_timespec(p,mdate_ts); p += 8;
1656 SOFF_T(p,0,file_size); p += 8;
1657 SOFF_T(p,0,allocation_size); p += 8;
1658 SIVAL(p,0,nt_extmode); p += 4;
1659 len = srvstr_push(base_data, flags2,
1660 p + 4, fname, PTR_DIFF(end_data, p+4),
1661 STR_TERMINATE_ASCII);
1664 SIVAL(p,0,0); /* Ensure any padding is null. */
1665 len = PTR_DIFF(p, pdata);
1666 len = (len + 3) & ~3;
1671 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1672 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1674 SIVAL(p,0,reskey); p += 4;
1675 put_long_date_timespec(p,create_date_ts); p += 8;
1676 put_long_date_timespec(p,adate_ts); p += 8;
1677 put_long_date_timespec(p,mdate_ts); p += 8;
1678 put_long_date_timespec(p,mdate_ts); p += 8;
1679 SOFF_T(p,0,file_size); p += 8;
1680 SOFF_T(p,0,allocation_size); p += 8;
1681 SIVAL(p,0,nt_extmode); p += 4;
1682 q = p; p += 4; /* q is placeholder for name length. */
1684 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1685 SIVAL(p,0,ea_size); /* Extended attributes */
1688 len = srvstr_push(base_data, flags2, p,
1689 fname, PTR_DIFF(end_data, p),
1690 STR_TERMINATE_ASCII);
1694 SIVAL(p,0,0); /* Ensure any padding is null. */
1695 len = PTR_DIFF(p, pdata);
1696 len = (len + 3) & ~3;
1701 case SMB_FIND_FILE_NAMES_INFO:
1702 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1704 SIVAL(p,0,reskey); p += 4;
1706 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1707 acl on a dir (tridge) */
1708 len = srvstr_push(base_data, flags2, p,
1709 fname, PTR_DIFF(end_data, p),
1710 STR_TERMINATE_ASCII);
1713 SIVAL(p,0,0); /* Ensure any padding is null. */
1714 len = PTR_DIFF(p, pdata);
1715 len = (len + 3) & ~3;
1720 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1721 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1723 SIVAL(p,0,reskey); p += 4;
1724 put_long_date_timespec(p,create_date_ts); p += 8;
1725 put_long_date_timespec(p,adate_ts); p += 8;
1726 put_long_date_timespec(p,mdate_ts); p += 8;
1727 put_long_date_timespec(p,mdate_ts); p += 8;
1728 SOFF_T(p,0,file_size); p += 8;
1729 SOFF_T(p,0,allocation_size); p += 8;
1730 SIVAL(p,0,nt_extmode); p += 4;
1731 q = p; p += 4; /* q is placeholder for name length. */
1733 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1734 SIVAL(p,0,ea_size); /* Extended attributes */
1737 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1738 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1739 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1740 len = srvstr_push(base_data, flags2, p,
1741 fname, PTR_DIFF(end_data, p),
1742 STR_TERMINATE_ASCII);
1745 SIVAL(p,0,0); /* Ensure any padding is null. */
1746 len = PTR_DIFF(p, pdata);
1747 len = (len + 3) & ~3;
1752 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1753 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1754 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1756 SIVAL(p,0,reskey); p += 4;
1757 put_long_date_timespec(p,create_date_ts); p += 8;
1758 put_long_date_timespec(p,adate_ts); p += 8;
1759 put_long_date_timespec(p,mdate_ts); p += 8;
1760 put_long_date_timespec(p,mdate_ts); p += 8;
1761 SOFF_T(p,0,file_size); p += 8;
1762 SOFF_T(p,0,allocation_size); p += 8;
1763 SIVAL(p,0,nt_extmode); p += 4;
1764 q = p; p += 4; /* q is placeholder for name length */
1766 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1767 SIVAL(p,0,ea_size); /* Extended attributes */
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1774 if (!was_8_3 && check_mangled_names) {
1775 if (!name_to_8_3(fname,mangled_name,True,
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1786 memset(p + 2 + len,'\0',24 - len);
1793 SSVAL(p,0,0); p += 2; /* Reserved ? */
1794 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1795 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1796 len = srvstr_push(base_data, flags2, p,
1797 fname, PTR_DIFF(end_data, p),
1798 STR_TERMINATE_ASCII);
1801 SIVAL(p,0,0); /* Ensure any padding is null. */
1802 len = PTR_DIFF(p, pdata);
1803 len = (len + 3) & ~3;
1808 /* CIFS UNIX Extension. */
1810 case SMB_FIND_FILE_UNIX:
1811 case SMB_FIND_FILE_UNIX_INFO2:
1813 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1815 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1817 if (info_level == SMB_FIND_FILE_UNIX) {
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1819 p = store_file_unix_basic(conn, p,
1821 len = srvstr_push(base_data, flags2, p,
1822 fname, PTR_DIFF(end_data, p),
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1826 p = store_file_unix_basic_info2(conn, p,
1830 len = srvstr_push(base_data, flags2, p, fname,
1831 PTR_DIFF(end_data, p), 0);
1832 SIVAL(nameptr, 0, len);
1836 SIVAL(p,0,0); /* Ensure any padding is null. */
1838 len = PTR_DIFF(p, pdata);
1839 len = (len + 3) & ~3;
1840 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1842 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1852 if (PTR_DIFF(p,pdata) > space_remaining) {
1853 /* Move the dirptr back to prev_dirpos */
1854 dptr_SeekDir(conn->dirptr, prev_dirpos);
1855 *out_of_space = True;
1856 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1857 return False; /* Not finished - just out of space */
1860 /* Setup the last entry pointer, as an offset from base_data */
1861 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1862 /* Advance the data pointer to the next slot */
1868 /****************************************************************************
1869 Reply to a TRANS2_FINDFIRST.
1870 ****************************************************************************/
1872 static void call_trans2findfirst(connection_struct *conn,
1873 struct smb_request *req,
1874 char **pparams, int total_params,
1875 char **ppdata, int total_data,
1876 unsigned int max_data_bytes)
1878 /* We must be careful here that we don't return more than the
1879 allowed number of data bytes. If this means returning fewer than
1880 maxentries then so be it. We assume that the redirector has
1881 enough room for the fixed number of parameter bytes it has
1883 char *params = *pparams;
1884 char *pdata = *ppdata;
1888 uint16 findfirst_flags;
1889 bool close_after_first;
1891 bool requires_resume_key;
1893 char *directory = NULL;
1896 int last_entry_off=0;
1900 bool finished = False;
1901 bool dont_descend = False;
1902 bool out_of_space = False;
1903 int space_remaining;
1904 bool mask_contains_wcard = False;
1905 SMB_STRUCT_STAT sbuf;
1906 struct ea_list *ea_list = NULL;
1907 NTSTATUS ntstatus = NT_STATUS_OK;
1908 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1909 TALLOC_CTX *ctx = talloc_tos();
1911 if (total_params < 13) {
1912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1916 dirtype = SVAL(params,0);
1917 maxentries = SVAL(params,2);
1918 findfirst_flags = SVAL(params,4);
1919 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1920 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1921 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1922 info_level = SVAL(params,6);
1924 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1925 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1926 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1927 info_level, max_data_bytes));
1930 /* W2K3 seems to treat zero as 1. */
1934 switch (info_level) {
1935 case SMB_FIND_INFO_STANDARD:
1936 case SMB_FIND_EA_SIZE:
1937 case SMB_FIND_EA_LIST:
1938 case SMB_FIND_FILE_DIRECTORY_INFO:
1939 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1940 case SMB_FIND_FILE_NAMES_INFO:
1941 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1942 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1943 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1945 case SMB_FIND_FILE_UNIX:
1946 case SMB_FIND_FILE_UNIX_INFO2:
1947 /* Always use filesystem for UNIX mtime query. */
1948 ask_sharemode = false;
1949 if (!lp_unix_extensions()) {
1950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1955 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1959 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1960 params+12, total_params - 12,
1961 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1962 if (!NT_STATUS_IS_OK(ntstatus)) {
1963 reply_nterror(req, ntstatus);
1967 ntstatus = resolve_dfspath_wcard(ctx, conn,
1968 req->flags2 & FLAGS2_DFS_PATHNAMES,
1971 &mask_contains_wcard);
1972 if (!NT_STATUS_IS_OK(ntstatus)) {
1973 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1974 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1975 ERRSRV, ERRbadpath);
1978 reply_nterror(req, ntstatus);
1982 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1983 if (!NT_STATUS_IS_OK(ntstatus)) {
1984 reply_nterror(req, ntstatus);
1988 ntstatus = check_name(conn, directory);
1989 if (!NT_STATUS_IS_OK(ntstatus)) {
1990 reply_nterror(req, ntstatus);
1994 p = strrchr_m(directory,'/');
1996 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1997 if((directory[0] == '.') && (directory[1] == '\0')) {
1998 mask = talloc_strdup(ctx,"*");
2000 reply_nterror(req, NT_STATUS_NO_MEMORY);
2003 mask_contains_wcard = True;
2005 directory = talloc_strdup(talloc_tos(), "./");
2007 reply_nterror(req, NT_STATUS_NO_MEMORY);
2014 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2016 if (info_level == SMB_FIND_EA_LIST) {
2019 if (total_data < 4) {
2020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2024 ea_size = IVAL(pdata,0);
2025 if (ea_size != total_data) {
2026 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2027 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2032 if (!lp_ea_support(SNUM(conn))) {
2033 reply_doserror(req, ERRDOS, ERReasnotsupported);
2037 /* Pull out the list of names. */
2038 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2045 *ppdata = (char *)SMB_REALLOC(
2046 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2047 if(*ppdata == NULL ) {
2048 reply_nterror(req, NT_STATUS_NO_MEMORY);
2052 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2054 /* Realloc the params space */
2055 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2056 if (*pparams == NULL) {
2057 reply_nterror(req, NT_STATUS_NO_MEMORY);
2062 /* Save the wildcard match and attribs we are using on this directory -
2063 needed as lanman2 assumes these are being saved between calls */
2065 ntstatus = dptr_create(conn,
2071 mask_contains_wcard,
2075 if (!NT_STATUS_IS_OK(ntstatus)) {
2076 reply_nterror(req, ntstatus);
2080 dptr_num = dptr_dnum(conn->dirptr);
2081 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2083 /* Initialize per TRANS2_FIND_FIRST operation data */
2084 dptr_init_search_op(conn->dirptr);
2086 /* We don't need to check for VOL here as this is returned by
2087 a different TRANS2 call. */
2089 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2090 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2091 dont_descend = True;
2094 space_remaining = max_data_bytes;
2095 out_of_space = False;
2097 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2098 bool got_exact_match = False;
2100 /* this is a heuristic to avoid seeking the dirptr except when
2101 absolutely necessary. It allows for a filename of about 40 chars */
2102 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2103 out_of_space = True;
2106 finished = !get_lanman2_dir_entry(ctx,
2109 mask,dirtype,info_level,
2110 requires_resume_key,dont_descend,
2113 space_remaining, &out_of_space,
2115 &last_entry_off, ea_list);
2118 if (finished && out_of_space)
2121 if (!finished && !out_of_space)
2125 * As an optimisation if we know we aren't looking
2126 * for a wildcard name (ie. the name matches the wildcard exactly)
2127 * then we can finish on any (first) match.
2128 * This speeds up large directory searches. JRA.
2134 /* Ensure space_remaining never goes -ve. */
2135 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2136 space_remaining = 0;
2137 out_of_space = true;
2139 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2143 /* Check if we can close the dirptr */
2144 if(close_after_first || (finished && close_if_end)) {
2145 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2146 dptr_close(&dptr_num);
2150 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2151 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2152 * the protocol level is less than NT1. Tested with smbclient. JRA.
2153 * This should fix the OS/2 client bug #2335.
2156 if(numentries == 0) {
2157 dptr_close(&dptr_num);
2158 if (Protocol < PROTOCOL_NT1) {
2159 reply_doserror(req, ERRDOS, ERRnofiles);
2162 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2163 ERRDOS, ERRbadfile);
2168 /* At this point pdata points to numentries directory entries. */
2170 /* Set up the return parameter block */
2171 SSVAL(params,0,dptr_num);
2172 SSVAL(params,2,numentries);
2173 SSVAL(params,4,finished);
2174 SSVAL(params,6,0); /* Never an EA error */
2175 SSVAL(params,8,last_entry_off);
2177 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2180 if ((! *directory) && dptr_path(dptr_num)) {
2181 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2183 reply_nterror(req, NT_STATUS_NO_MEMORY);
2187 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2188 smb_fn_name(req->cmd),
2189 mask, directory, dirtype, numentries ) );
2192 * Force a name mangle here to ensure that the
2193 * mask as an 8.3 name is top of the mangled cache.
2194 * The reasons for this are subtle. Don't remove
2195 * this code unless you know what you are doing
2196 * (see PR#13758). JRA.
2199 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2200 char mangled_name[13];
2201 name_to_8_3(mask, mangled_name, True, conn->params);
2207 /****************************************************************************
2208 Reply to a TRANS2_FINDNEXT.
2209 ****************************************************************************/
2211 static void call_trans2findnext(connection_struct *conn,
2212 struct smb_request *req,
2213 char **pparams, int total_params,
2214 char **ppdata, int total_data,
2215 unsigned int max_data_bytes)
2217 /* We must be careful here that we don't return more than the
2218 allowed number of data bytes. If this means returning fewer than
2219 maxentries then so be it. We assume that the redirector has
2220 enough room for the fixed number of parameter bytes it has
2222 char *params = *pparams;
2223 char *pdata = *ppdata;
2229 uint16 findnext_flags;
2230 bool close_after_request;
2232 bool requires_resume_key;
2234 bool mask_contains_wcard = False;
2235 char *resume_name = NULL;
2236 const char *mask = NULL;
2237 const char *directory = NULL;
2241 int i, last_entry_off=0;
2242 bool finished = False;
2243 bool dont_descend = False;
2244 bool out_of_space = False;
2245 int space_remaining;
2246 struct ea_list *ea_list = NULL;
2247 NTSTATUS ntstatus = NT_STATUS_OK;
2248 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2249 TALLOC_CTX *ctx = talloc_tos();
2251 if (total_params < 13) {
2252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2256 dptr_num = SVAL(params,0);
2257 maxentries = SVAL(params,2);
2258 info_level = SVAL(params,4);
2259 resume_key = IVAL(params,6);
2260 findnext_flags = SVAL(params,10);
2261 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2262 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2263 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2264 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2266 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2268 total_params - 12, STR_TERMINATE, &ntstatus,
2269 &mask_contains_wcard);
2270 if (!NT_STATUS_IS_OK(ntstatus)) {
2271 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2272 complain (it thinks we're asking for the directory above the shared
2273 path or an invalid name). Catch this as the resume name is only compared, never used in
2274 a file access. JRA. */
2275 srvstr_pull_talloc(ctx, params, req->flags2,
2276 &resume_name, params+12,
2280 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2281 reply_nterror(req, ntstatus);
2286 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2287 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2288 resume_key = %d resume name = %s continue=%d level = %d\n",
2289 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2290 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2293 /* W2K3 seems to treat zero as 1. */
2297 switch (info_level) {
2298 case SMB_FIND_INFO_STANDARD:
2299 case SMB_FIND_EA_SIZE:
2300 case SMB_FIND_EA_LIST:
2301 case SMB_FIND_FILE_DIRECTORY_INFO:
2302 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_NAMES_INFO:
2304 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2305 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2306 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2308 case SMB_FIND_FILE_UNIX:
2309 case SMB_FIND_FILE_UNIX_INFO2:
2310 /* Always use filesystem for UNIX mtime query. */
2311 ask_sharemode = false;
2312 if (!lp_unix_extensions()) {
2313 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2322 if (info_level == SMB_FIND_EA_LIST) {
2325 if (total_data < 4) {
2326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2330 ea_size = IVAL(pdata,0);
2331 if (ea_size != total_data) {
2332 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2333 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2338 if (!lp_ea_support(SNUM(conn))) {
2339 reply_doserror(req, ERRDOS, ERReasnotsupported);
2343 /* Pull out the list of names. */
2344 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2351 *ppdata = (char *)SMB_REALLOC(
2352 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2353 if(*ppdata == NULL) {
2354 reply_nterror(req, NT_STATUS_NO_MEMORY);
2359 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2361 /* Realloc the params space */
2362 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2363 if(*pparams == NULL ) {
2364 reply_nterror(req, NT_STATUS_NO_MEMORY);
2370 /* Check that the dptr is valid */
2371 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2372 reply_doserror(req, ERRDOS, ERRnofiles);
2376 string_set(&conn->dirpath,dptr_path(dptr_num));
2378 /* Get the wildcard mask from the dptr */
2379 if((p = dptr_wcard(dptr_num))== NULL) {
2380 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2381 reply_doserror(req, ERRDOS, ERRnofiles);
2386 directory = conn->dirpath;
2388 /* Get the attr mask from the dptr */
2389 dirtype = dptr_attr(dptr_num);
2391 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2392 dptr_num, mask, dirtype,
2394 dptr_TellDir(conn->dirptr)));
2396 /* Initialize per TRANS2_FIND_NEXT operation data */
2397 dptr_init_search_op(conn->dirptr);
2399 /* We don't need to check for VOL here as this is returned by
2400 a different TRANS2 call. */
2402 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2403 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2404 dont_descend = True;
2407 space_remaining = max_data_bytes;
2408 out_of_space = False;
2411 * Seek to the correct position. We no longer use the resume key but
2412 * depend on the last file name instead.
2415 if(*resume_name && !continue_bit) {
2418 long current_pos = 0;
2420 * Remember, name_to_8_3 is called by
2421 * get_lanman2_dir_entry(), so the resume name
2422 * could be mangled. Ensure we check the unmangled name.
2425 if (mangle_is_mangled(resume_name, conn->params)) {
2426 char *new_resume_name = NULL;
2427 mangle_lookup_name_from_8_3(ctx,
2431 if (new_resume_name) {
2432 resume_name = new_resume_name;
2437 * Fix for NT redirector problem triggered by resume key indexes
2438 * changing between directory scans. We now return a resume key of 0
2439 * and instead look for the filename to continue from (also given
2440 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2441 * findfirst/findnext (as is usual) then the directory pointer
2442 * should already be at the correct place.
2445 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2446 } /* end if resume_name && !continue_bit */
2448 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2449 bool got_exact_match = False;
2451 /* this is a heuristic to avoid seeking the dirptr except when
2452 absolutely necessary. It allows for a filename of about 40 chars */
2453 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2454 out_of_space = True;
2457 finished = !get_lanman2_dir_entry(ctx,
2460 mask,dirtype,info_level,
2461 requires_resume_key,dont_descend,
2464 space_remaining, &out_of_space,
2466 &last_entry_off, ea_list);
2469 if (finished && out_of_space)
2472 if (!finished && !out_of_space)
2476 * As an optimisation if we know we aren't looking
2477 * for a wildcard name (ie. the name matches the wildcard exactly)
2478 * then we can finish on any (first) match.
2479 * This speeds up large directory searches. JRA.
2485 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2488 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2489 smb_fn_name(req->cmd),
2490 mask, directory, dirtype, numentries ) );
2492 /* Check if we can close the dirptr */
2493 if(close_after_request || (finished && close_if_end)) {
2494 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2495 dptr_close(&dptr_num); /* This frees up the saved mask */
2498 /* Set up the return parameter block */
2499 SSVAL(params,0,numentries);
2500 SSVAL(params,2,finished);
2501 SSVAL(params,4,0); /* Never an EA error */
2502 SSVAL(params,6,last_entry_off);
2504 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2510 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2512 E_md4hash(lp_servicename(SNUM(conn)),objid);
2516 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2518 SMB_ASSERT(extended_info != NULL);
2520 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2521 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2522 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2523 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2524 #ifdef SAMBA_VERSION_REVISION
2525 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2527 extended_info->samba_subversion = 0;
2528 #ifdef SAMBA_VERSION_RC_RELEASE
2529 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2531 #ifdef SAMBA_VERSION_PRE_RELEASE
2532 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2535 #ifdef SAMBA_VERSION_VENDOR_PATCH
2536 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2538 extended_info->samba_gitcommitdate = 0;
2539 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2540 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2543 memset(extended_info->samba_version_string, 0,
2544 sizeof(extended_info->samba_version_string));
2546 snprintf (extended_info->samba_version_string,
2547 sizeof(extended_info->samba_version_string),
2548 "%s", samba_version_string());
2551 /****************************************************************************
2552 Reply to a TRANS2_QFSINFO (query filesystem info).
2553 ****************************************************************************/
2555 static void call_trans2qfsinfo(connection_struct *conn,
2556 struct smb_request *req,
2557 char **pparams, int total_params,
2558 char **ppdata, int total_data,
2559 unsigned int max_data_bytes)
2561 char *pdata, *end_data;
2562 char *params = *pparams;
2566 const char *vname = volume_label(SNUM(conn));
2567 int snum = SNUM(conn);
2568 char *fstype = lp_fstype(SNUM(conn));
2569 uint32 additional_flags = 0;
2571 if (total_params < 2) {
2572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2576 info_level = SVAL(params,0);
2579 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2580 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2581 "info level (0x%x) on IPC$.\n",
2582 (unsigned int)info_level));
2583 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2588 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2589 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2590 DEBUG(0,("call_trans2qfsinfo: encryption required "
2591 "and info level 0x%x sent.\n",
2592 (unsigned int)info_level));
2593 exit_server_cleanly("encryption required "
2599 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2601 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2602 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2603 reply_doserror(req, ERRSRV, ERRinvdevice);
2607 *ppdata = (char *)SMB_REALLOC(
2608 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2609 if (*ppdata == NULL ) {
2610 reply_nterror(req, NT_STATUS_NO_MEMORY);
2615 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2616 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2618 switch (info_level) {
2619 case SMB_INFO_ALLOCATION:
2621 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2623 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2624 reply_unixerror(req, ERRHRD, ERRgeneral);
2628 block_size = lp_block_size(snum);
2629 if (bsize < block_size) {
2630 uint64_t factor = block_size/bsize;
2635 if (bsize > block_size) {
2636 uint64_t factor = bsize/block_size;
2641 bytes_per_sector = 512;
2642 sectors_per_unit = bsize/bytes_per_sector;
2644 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2645 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2646 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2648 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2649 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2650 SIVAL(pdata,l1_cUnit,dsize);
2651 SIVAL(pdata,l1_cUnitAvail,dfree);
2652 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2656 case SMB_INFO_VOLUME:
2657 /* Return volume name */
2659 * Add volume serial number - hash of a combination of
2660 * the called hostname and the service name.
2662 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2664 * Win2k3 and previous mess this up by sending a name length
2665 * one byte short. I believe only older clients (OS/2 Win9x) use
2666 * this call so try fixing this by adding a terminating null to
2667 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2671 pdata+l2_vol_szVolLabel, vname,
2672 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2673 STR_NOALIGN|STR_TERMINATE);
2674 SCVAL(pdata,l2_vol_cch,len);
2675 data_len = l2_vol_szVolLabel + len;
2676 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2677 (unsigned)st.st_ctime, len, vname));
2680 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2681 case SMB_FS_ATTRIBUTE_INFORMATION:
2683 additional_flags = 0;
2684 #if defined(HAVE_SYS_QUOTAS)
2685 additional_flags |= FILE_VOLUME_QUOTAS;
2688 if(lp_nt_acl_support(SNUM(conn))) {
2689 additional_flags |= FILE_PERSISTENT_ACLS;
2692 /* Capabilities are filled in at connection time through STATVFS call */
2693 additional_flags |= conn->fs_capabilities;
2695 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2696 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2697 additional_flags); /* FS ATTRIBUTES */
2699 SIVAL(pdata,4,255); /* Max filename component length */
2700 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2701 and will think we can't do long filenames */
2702 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2703 PTR_DIFF(end_data, pdata+12),
2706 data_len = 12 + len;
2709 case SMB_QUERY_FS_LABEL_INFO:
2710 case SMB_FS_LABEL_INFORMATION:
2711 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2712 PTR_DIFF(end_data, pdata+4), 0);
2717 case SMB_QUERY_FS_VOLUME_INFO:
2718 case SMB_FS_VOLUME_INFORMATION:
2721 * Add volume serial number - hash of a combination of
2722 * the called hostname and the service name.
2724 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2725 (str_checksum(get_local_machine_name())<<16));
2727 /* Max label len is 32 characters. */
2728 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2729 PTR_DIFF(end_data, pdata+18),
2731 SIVAL(pdata,12,len);
2734 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2735 (int)strlen(vname),vname, lp_servicename(snum)));
2738 case SMB_QUERY_FS_SIZE_INFO:
2739 case SMB_FS_SIZE_INFORMATION:
2741 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2743 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2744 reply_unixerror(req, ERRHRD, ERRgeneral);
2747 block_size = lp_block_size(snum);
2748 if (bsize < block_size) {
2749 uint64_t factor = block_size/bsize;
2754 if (bsize > block_size) {
2755 uint64_t factor = bsize/block_size;
2760 bytes_per_sector = 512;
2761 sectors_per_unit = bsize/bytes_per_sector;
2762 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2763 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2764 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2765 SBIG_UINT(pdata,0,dsize);
2766 SBIG_UINT(pdata,8,dfree);
2767 SIVAL(pdata,16,sectors_per_unit);
2768 SIVAL(pdata,20,bytes_per_sector);
2772 case SMB_FS_FULL_SIZE_INFORMATION:
2774 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2776 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2777 reply_unixerror(req, ERRHRD, ERRgeneral);
2780 block_size = lp_block_size(snum);
2781 if (bsize < block_size) {
2782 uint64_t factor = block_size/bsize;
2787 if (bsize > block_size) {
2788 uint64_t factor = bsize/block_size;
2793 bytes_per_sector = 512;
2794 sectors_per_unit = bsize/bytes_per_sector;
2795 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2796 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2797 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2798 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2799 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2800 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2801 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2802 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2806 case SMB_QUERY_FS_DEVICE_INFO:
2807 case SMB_FS_DEVICE_INFORMATION:
2809 SIVAL(pdata,0,0); /* dev type */
2810 SIVAL(pdata,4,0); /* characteristics */
2813 #ifdef HAVE_SYS_QUOTAS
2814 case SMB_FS_QUOTA_INFORMATION:
2816 * what we have to send --metze:
2818 * Unknown1: 24 NULL bytes
2819 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2820 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2821 * Quota Flags: 2 byte :
2822 * Unknown3: 6 NULL bytes
2826 * details for Quota Flags:
2828 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2829 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2830 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2831 * 0x0001 Enable Quotas: enable quota for this fs
2835 /* we need to fake up a fsp here,
2836 * because its not send in this call
2839 SMB_NTQUOTA_STRUCT quotas;
2842 ZERO_STRUCT(quotas);
2848 if (conn->server_info->utok.uid != 0) {
2849 DEBUG(0,("set_user_quota: access_denied "
2850 "service [%s] user [%s]\n",
2851 lp_servicename(SNUM(conn)),
2852 conn->server_info->unix_name));
2853 reply_doserror(req, ERRDOS, ERRnoaccess);
2857 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2858 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2859 reply_doserror(req, ERRSRV, ERRerror);
2865 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2867 /* Unknown1 24 NULL bytes*/
2868 SBIG_UINT(pdata,0,(uint64_t)0);
2869 SBIG_UINT(pdata,8,(uint64_t)0);
2870 SBIG_UINT(pdata,16,(uint64_t)0);
2872 /* Default Soft Quota 8 bytes */
2873 SBIG_UINT(pdata,24,quotas.softlim);
2875 /* Default Hard Quota 8 bytes */
2876 SBIG_UINT(pdata,32,quotas.hardlim);
2878 /* Quota flag 2 bytes */
2879 SSVAL(pdata,40,quotas.qflags);
2881 /* Unknown3 6 NULL bytes */
2887 #endif /* HAVE_SYS_QUOTAS */
2888 case SMB_FS_OBJECTID_INFORMATION:
2890 unsigned char objid[16];
2891 struct smb_extended_info extended_info;
2892 memcpy(pdata,create_volume_objectid(conn, objid),16);
2893 samba_extended_info_version (&extended_info);
2894 SIVAL(pdata,16,extended_info.samba_magic);
2895 SIVAL(pdata,20,extended_info.samba_version);
2896 SIVAL(pdata,24,extended_info.samba_subversion);
2897 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2898 memcpy(pdata+36,extended_info.samba_version_string,28);
2904 * Query the version and capabilities of the CIFS UNIX extensions
2908 case SMB_QUERY_CIFS_UNIX_INFO:
2910 bool large_write = lp_min_receive_file_size() &&
2911 !srv_is_signing_active();
2912 bool large_read = !srv_is_signing_active();
2913 int encrypt_caps = 0;
2915 if (!lp_unix_extensions()) {
2916 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2920 switch (conn->encrypt_level) {
2926 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2929 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2930 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2931 large_write = false;
2937 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2938 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2940 /* We have POSIX ACLs, pathname, encryption,
2941 * large read/write, and locking capability. */
2943 SBIG_UINT(pdata,4,((uint64_t)(
2944 CIFS_UNIX_POSIX_ACLS_CAP|
2945 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2946 CIFS_UNIX_FCNTL_LOCKS_CAP|
2947 CIFS_UNIX_EXTATTR_CAP|
2948 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2950 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2952 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2956 case SMB_QUERY_POSIX_FS_INFO:
2959 vfs_statvfs_struct svfs;
2961 if (!lp_unix_extensions()) {
2962 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2966 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2970 SIVAL(pdata,0,svfs.OptimalTransferSize);
2971 SIVAL(pdata,4,svfs.BlockSize);
2972 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2973 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2974 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2975 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2976 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2977 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2978 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2980 } else if (rc == EOPNOTSUPP) {
2981 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2983 #endif /* EOPNOTSUPP */
2985 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2986 reply_doserror(req, ERRSRV, ERRerror);
2992 case SMB_QUERY_POSIX_WHOAMI:
2998 if (!lp_unix_extensions()) {
2999 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3003 if (max_data_bytes < 40) {
3004 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3008 /* We ARE guest if global_sid_Builtin_Guests is
3009 * in our list of SIDs.
3011 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3012 conn->server_info->ptok)) {
3013 flags |= SMB_WHOAMI_GUEST;
3016 /* We are NOT guest if global_sid_Authenticated_Users
3017 * is in our list of SIDs.
3019 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3020 conn->server_info->ptok)) {
3021 flags &= ~SMB_WHOAMI_GUEST;
3024 /* NOTE: 8 bytes for UID/GID, irrespective of native
3025 * platform size. This matches
3026 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3028 data_len = 4 /* flags */
3035 + 4 /* pad/reserved */
3036 + (conn->server_info->utok.ngroups * 8)
3038 + (conn->server_info->ptok->num_sids *
3042 SIVAL(pdata, 0, flags);
3043 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3045 (uint64_t)conn->server_info->utok.uid);
3046 SBIG_UINT(pdata, 16,
3047 (uint64_t)conn->server_info->utok.gid);
3050 if (data_len >= max_data_bytes) {
3051 /* Potential overflow, skip the GIDs and SIDs. */
3053 SIVAL(pdata, 24, 0); /* num_groups */
3054 SIVAL(pdata, 28, 0); /* num_sids */
3055 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3056 SIVAL(pdata, 36, 0); /* reserved */
3062 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3063 SIVAL(pdata, 28, conn->server_info->num_sids);
3065 /* We walk the SID list twice, but this call is fairly
3066 * infrequent, and I don't expect that it's performance
3067 * sensitive -- jpeach
3069 for (i = 0, sid_bytes = 0;
3070 i < conn->server_info->ptok->num_sids; ++i) {
3071 sid_bytes += ndr_size_dom_sid(
3072 &conn->server_info->ptok->user_sids[i],
3077 /* SID list byte count */
3078 SIVAL(pdata, 32, sid_bytes);
3080 /* 4 bytes pad/reserved - must be zero */
3081 SIVAL(pdata, 36, 0);
3085 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3086 SBIG_UINT(pdata, data_len,
3087 (uint64_t)conn->server_info->utok.groups[i]);
3093 i < conn->server_info->ptok->num_sids; ++i) {
3094 int sid_len = ndr_size_dom_sid(
3095 &conn->server_info->ptok->user_sids[i],
3099 sid_linearize(pdata + data_len, sid_len,
3100 &conn->server_info->ptok->user_sids[i]);
3101 data_len += sid_len;
3107 case SMB_MAC_QUERY_FS_INFO:
3109 * Thursby MAC extension... ONLY on NTFS filesystems
3110 * once we do streams then we don't need this
3112 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3114 SIVAL(pdata,84,0x100); /* Don't support mac... */
3119 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3124 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3127 DEBUG( 4, ( "%s info_level = %d\n",
3128 smb_fn_name(req->cmd), info_level) );
3133 /****************************************************************************
3134 Reply to a TRANS2_SETFSINFO (set filesystem info).
3135 ****************************************************************************/
3137 static void call_trans2setfsinfo(connection_struct *conn,
3138 struct smb_request *req,
3139 char **pparams, int total_params,
3140 char **ppdata, int total_data,
3141 unsigned int max_data_bytes)
3143 char *pdata = *ppdata;
3144 char *params = *pparams;
3147 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3150 if (total_params < 4) {
3151 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3157 info_level = SVAL(params,2);
3160 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3161 info_level != SMB_SET_CIFS_UNIX_INFO) {
3162 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3163 "info level (0x%x) on IPC$.\n",
3164 (unsigned int)info_level));
3165 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3170 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3171 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3172 DEBUG(0,("call_trans2setfsinfo: encryption required "
3173 "and info level 0x%x sent.\n",
3174 (unsigned int)info_level));
3175 exit_server_cleanly("encryption required "
3181 switch(info_level) {
3182 case SMB_SET_CIFS_UNIX_INFO:
3184 uint16 client_unix_major;
3185 uint16 client_unix_minor;
3186 uint32 client_unix_cap_low;
3187 uint32 client_unix_cap_high;
3189 if (!lp_unix_extensions()) {
3191 NT_STATUS_INVALID_LEVEL);
3195 /* There should be 12 bytes of capabilities set. */
3196 if (total_data < 8) {
3199 NT_STATUS_INVALID_PARAMETER);
3202 client_unix_major = SVAL(pdata,0);
3203 client_unix_minor = SVAL(pdata,2);
3204 client_unix_cap_low = IVAL(pdata,4);
3205 client_unix_cap_high = IVAL(pdata,8);
3206 /* Just print these values for now. */
3207 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3208 cap_low = 0x%x, cap_high = 0x%x\n",
3209 (unsigned int)client_unix_major,
3210 (unsigned int)client_unix_minor,
3211 (unsigned int)client_unix_cap_low,
3212 (unsigned int)client_unix_cap_high ));
3214 /* Here is where we must switch to posix pathname processing... */
3215 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3216 lp_set_posix_pathnames();
3217 mangle_change_to_posix();
3220 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3221 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3222 /* Client that knows how to do posix locks,
3223 * but not posix open/mkdir operations. Set a
3224 * default type for read/write checks. */
3226 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3232 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3235 size_t param_len = 0;
3236 size_t data_len = total_data;
3238 if (!lp_unix_extensions()) {
3241 NT_STATUS_INVALID_LEVEL);
3245 if (lp_smb_encrypt(SNUM(conn)) == false) {
3248 NT_STATUS_NOT_SUPPORTED);
3252 DEBUG( 4,("call_trans2setfsinfo: "
3253 "request transport encryption.\n"));
3255 status = srv_request_encryption_setup(conn,
3256 (unsigned char **)ppdata,
3258 (unsigned char **)pparams,
3261 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3262 !NT_STATUS_IS_OK(status)) {
3263 reply_nterror(req, status);
3267 send_trans2_replies(conn, req,
3274 if (NT_STATUS_IS_OK(status)) {
3275 /* Server-side transport
3276 * encryption is now *on*. */
3277 status = srv_encryption_start(conn);
3278 if (!NT_STATUS_IS_OK(status)) {
3279 exit_server_cleanly(
3280 "Failure in setting "
3281 "up encrypted transport");
3287 case SMB_FS_QUOTA_INFORMATION:
3289 files_struct *fsp = NULL;
3290 SMB_NTQUOTA_STRUCT quotas;
3292 ZERO_STRUCT(quotas);
3295 if ((conn->server_info->utok.uid != 0)
3296 ||!CAN_WRITE(conn)) {
3297 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3298 lp_servicename(SNUM(conn)),
3299 conn->server_info->unix_name));
3300 reply_doserror(req, ERRSRV, ERRaccess);
3304 /* note: normaly there're 48 bytes,
3305 * but we didn't use the last 6 bytes for now
3308 fsp = file_fsp(req, SVAL(params,0));
3310 if (!check_fsp_ntquota_handle(conn, req,
3312 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3314 req, NT_STATUS_INVALID_HANDLE);
3318 if (total_data < 42) {
3319 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3323 NT_STATUS_INVALID_PARAMETER);
3327 /* unknown_1 24 NULL bytes in pdata*/
3329 /* the soft quotas 8 bytes (uint64_t)*/
3330 quotas.softlim = (uint64_t)IVAL(pdata,24);
3331 #ifdef LARGE_SMB_OFF_T
3332 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3333 #else /* LARGE_SMB_OFF_T */
3334 if ((IVAL(pdata,28) != 0)&&
3335 ((quotas.softlim != 0xFFFFFFFF)||
3336 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3337 /* more than 32 bits? */
3340 NT_STATUS_INVALID_PARAMETER);
3343 #endif /* LARGE_SMB_OFF_T */
3345 /* the hard quotas 8 bytes (uint64_t)*/
3346 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3347 #ifdef LARGE_SMB_OFF_T
3348 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3349 #else /* LARGE_SMB_OFF_T */
3350 if ((IVAL(pdata,36) != 0)&&
3351 ((quotas.hardlim != 0xFFFFFFFF)||
3352 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3353 /* more than 32 bits? */
3356 NT_STATUS_INVALID_PARAMETER);
3359 #endif /* LARGE_SMB_OFF_T */
3361 /* quota_flags 2 bytes **/
3362 quotas.qflags = SVAL(pdata,40);
3364 /* unknown_2 6 NULL bytes follow*/
3366 /* now set the quotas */
3367 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3368 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3369 reply_doserror(req, ERRSRV, ERRerror);
3376 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3378 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3384 * sending this reply works fine,
3385 * but I'm not sure it's the same
3386 * like windows do...
3389 reply_outbuf(req, 10, 0);
3392 #if defined(HAVE_POSIX_ACLS)
3393 /****************************************************************************
3394 Utility function to count the number of entries in a POSIX acl.
3395 ****************************************************************************/
3397 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3399 unsigned int ace_count = 0;
3400 int entry_id = SMB_ACL_FIRST_ENTRY;
3401 SMB_ACL_ENTRY_T entry;
3403 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3405 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3406 entry_id = SMB_ACL_NEXT_ENTRY;
3413 /****************************************************************************
3414 Utility function to marshall a POSIX acl into wire format.
3415 ****************************************************************************/
3417 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3419 int entry_id = SMB_ACL_FIRST_ENTRY;
3420 SMB_ACL_ENTRY_T entry;
3422 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3423 SMB_ACL_TAG_T tagtype;
3424 SMB_ACL_PERMSET_T permset;
3425 unsigned char perms = 0;
3426 unsigned int own_grp;
3429 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3430 entry_id = SMB_ACL_NEXT_ENTRY;
3433 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3434 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3438 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3439 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3443 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3444 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3445 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3447 SCVAL(pdata,1,perms);
3450 case SMB_ACL_USER_OBJ:
3451 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3452 own_grp = (unsigned int)pst->st_uid;
3453 SIVAL(pdata,2,own_grp);
3458 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3460 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3463 own_grp = (unsigned int)*puid;
3464 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3465 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3466 SIVAL(pdata,2,own_grp);
3470 case SMB_ACL_GROUP_OBJ:
3471 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3472 own_grp = (unsigned int)pst->st_gid;
3473 SIVAL(pdata,2,own_grp);
3478 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3480 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3483 own_grp = (unsigned int)*pgid;
3484 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3485 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3486 SIVAL(pdata,2,own_grp);
3491 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3492 SIVAL(pdata,2,0xFFFFFFFF);
3493 SIVAL(pdata,6,0xFFFFFFFF);
3496 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3497 SIVAL(pdata,2,0xFFFFFFFF);
3498 SIVAL(pdata,6,0xFFFFFFFF);
3501 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3504 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3511 /****************************************************************************
3512 Store the FILE_UNIX_BASIC info.
3513 ****************************************************************************/
3515 static char *store_file_unix_basic(connection_struct *conn,
3518 const SMB_STRUCT_STAT *psbuf)
3520 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3521 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3523 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3526 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3529 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3530 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3531 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3534 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3538 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3542 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3545 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3549 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3553 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3556 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3560 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3567 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3568 * the chflags(2) (or equivalent) flags.
3570 * XXX: this really should be behind the VFS interface. To do this, we would
3571 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3572 * Each VFS module could then implement its own mapping as appropriate for the
3573 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3575 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3579 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3583 { UF_IMMUTABLE, EXT_IMMUTABLE },
3587 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3591 { UF_HIDDEN, EXT_HIDDEN },
3594 /* Do not remove. We need to guarantee that this array has at least one
3595 * entry to build on HP-UX.
3601 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3602 uint32 *smb_fflags, uint32 *smb_fmask)
3604 #ifdef HAVE_STAT_ST_FLAGS
3607 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3608 *smb_fmask |= info2_flags_map[i].smb_fflag;
3609 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3610 *smb_fflags |= info2_flags_map[i].smb_fflag;
3613 #endif /* HAVE_STAT_ST_FLAGS */
3616 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3617 const uint32 smb_fflags,
3618 const uint32 smb_fmask,
3621 #ifdef HAVE_STAT_ST_FLAGS
3622 uint32 max_fmask = 0;
3625 *stat_fflags = psbuf->st_flags;
3627 /* For each flags requested in smb_fmask, check the state of the
3628 * corresponding flag in smb_fflags and set or clear the matching
3632 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3633 max_fmask |= info2_flags_map[i].smb_fflag;
3634 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3635 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3636 *stat_fflags |= info2_flags_map[i].stat_fflag;
3638 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3643 /* If smb_fmask is asking to set any bits that are not supported by
3644 * our flag mappings, we should fail.
3646 if ((smb_fmask & max_fmask) != smb_fmask) {
3653 #endif /* HAVE_STAT_ST_FLAGS */
3657 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3658 * of file flags and birth (create) time.
3660 static char *store_file_unix_basic_info2(connection_struct *conn,
3663 const SMB_STRUCT_STAT *psbuf)
3665 uint32 file_flags = 0;
3666 uint32 flags_mask = 0;
3668 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3670 /* Create (birth) time 64 bit */
3671 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3674 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3675 SIVAL(pdata, 0, file_flags); /* flags */
3676 SIVAL(pdata, 4, flags_mask); /* mask */
3682 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3683 const struct stream_struct *streams,
3685 unsigned int max_data_bytes,
3686 unsigned int *data_size)
3689 unsigned int ofs = 0;
3691 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3692 unsigned int next_offset;
3694 smb_ucs2_t *namebuf;
3696 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3697 streams[i].name, &namelen) ||
3700 return NT_STATUS_INVALID_PARAMETER;
3704 * name_buf is now null-terminated, we need to marshall as not
3710 SIVAL(data, ofs+4, namelen);
3711 SOFF_T(data, ofs+8, streams[i].size);
3712 SOFF_T(data, ofs+16, streams[i].alloc_size);
3713 memcpy(data+ofs+24, namebuf, namelen);
3714 TALLOC_FREE(namebuf);
3716 next_offset = ofs + 24 + namelen;
3718 if (i == num_streams-1) {
3719 SIVAL(data, ofs, 0);
3722 unsigned int align = ndr_align_size(next_offset, 8);
3724 memset(data+next_offset, 0, align);
3725 next_offset += align;
3727 SIVAL(data, ofs, next_offset - ofs);
3736 return NT_STATUS_OK;
3739 /****************************************************************************
3740 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3741 ****************************************************************************/
3743 static void call_trans2qpipeinfo(connection_struct *conn,
3744 struct smb_request *req,
3745 unsigned int tran_call,
3746 char **pparams, int total_params,
3747 char **ppdata, int total_data,
3748 unsigned int max_data_bytes)
3750 char *params = *pparams;
3751 char *pdata = *ppdata;
3752 unsigned int data_size = 0;
3753 unsigned int param_size = 2;
3758 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3762 if (total_params < 4) {
3763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3767 fsp = file_fsp(req, SVAL(params,0));
3768 if (!fsp_is_np(fsp)) {
3769 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3773 info_level = SVAL(params,2);
3775 *pparams = (char *)SMB_REALLOC(*pparams,2);
3776 if (*pparams == NULL) {
3777 reply_nterror(req, NT_STATUS_NO_MEMORY);
3782 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3783 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3784 if (*ppdata == NULL ) {
3785 reply_nterror(req, NT_STATUS_NO_MEMORY);
3790 switch (info_level) {
3791 case SMB_FILE_STANDARD_INFORMATION:
3793 SOFF_T(pdata,0,4096LL);
3800 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3804 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3810 /****************************************************************************
3811 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3812 file name or file id).
3813 ****************************************************************************/
3815 static void call_trans2qfilepathinfo(connection_struct *conn,
3816 struct smb_request *req,
3817 unsigned int tran_call,
3818 char **pparams, int total_params,
3819 char **ppdata, int total_data,
3820 unsigned int max_data_bytes)
3822 char *params = *pparams;
3823 char *pdata = *ppdata;
3824 char *dstart, *dend;
3828 SMB_OFF_T file_size=0;
3829 uint64_t allocation_size=0;
3830 unsigned int data_size = 0;
3831 unsigned int param_size = 2;
3832 SMB_STRUCT_STAT sbuf;
3833 char *dos_fname = NULL;
3839 bool delete_pending = False;
3841 time_t create_time, mtime, atime;
3842 struct timespec create_time_ts, mtime_ts, atime_ts;
3843 struct timespec write_time_ts;
3844 files_struct *fsp = NULL;
3845 struct file_id fileid;
3846 struct ea_list *ea_list = NULL;
3847 char *lock_data = NULL;
3848 bool ms_dfs_link = false;
3849 TALLOC_CTX *ctx = talloc_tos();
3852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3857 ZERO_STRUCT(write_time_ts);
3859 if (tran_call == TRANSACT2_QFILEINFO) {
3860 if (total_params < 4) {
3861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3866 call_trans2qpipeinfo(conn, req, tran_call,
3867 pparams, total_params,
3873 fsp = file_fsp(req, SVAL(params,0));
3874 info_level = SVAL(params,2);
3876 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3878 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3879 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3883 /* Initial check for valid fsp ptr. */
3884 if (!check_fsp_open(conn, req, fsp)) {
3888 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3890 reply_nterror(req, NT_STATUS_NO_MEMORY);
3894 if(fsp->fake_file_handle) {
3896 * This is actually for the QUOTA_FAKE_FILE --metze
3899 /* We know this name is ok, it's already passed the checks. */
3901 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3903 * This is actually a QFILEINFO on a directory
3904 * handle (returned from an NT SMB). NT5.0 seems
3905 * to do this call. JRA.
3908 if (INFO_LEVEL_IS_UNIX(info_level)) {
3909 /* Always do lstat for UNIX calls. */
3910 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3911 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3912 reply_unixerror(req,ERRDOS,ERRbadpath);
3915 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3916 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3917 reply_unixerror(req, ERRDOS, ERRbadpath);
3921 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3922 get_file_infos(fileid, &delete_pending, &write_time_ts);
3925 * Original code - this is an open file.
3927 if (!check_fsp(conn, req, fsp)) {
3931 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3932 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3933 reply_unixerror(req, ERRDOS, ERRbadfid);
3936 pos = fsp->fh->position_information;
3937 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3938 get_file_infos(fileid, &delete_pending, &write_time_ts);
3942 NTSTATUS status = NT_STATUS_OK;
3945 if (total_params < 7) {
3946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3950 info_level = SVAL(params,0);
3952 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3954 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3955 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3959 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3961 STR_TERMINATE, &status);
3962 if (!NT_STATUS_IS_OK(status)) {
3963 reply_nterror(req, status);
3967 status = resolve_dfspath(ctx,
3969 req->flags2 & FLAGS2_DFS_PATHNAMES,
3972 if (!NT_STATUS_IS_OK(status)) {
3973 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3974 reply_botherror(req,
3975 NT_STATUS_PATH_NOT_COVERED,
3976 ERRSRV, ERRbadpath);
3978 reply_nterror(req, status);
3982 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3983 if (!NT_STATUS_IS_OK(status)) {
3984 reply_nterror(req, status);
3987 status = check_name(conn, fname);
3988 if (!NT_STATUS_IS_OK(status)) {
3989 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3990 reply_nterror(req, status);
3994 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3995 && is_ntfs_stream_name(fname)) {
3997 SMB_STRUCT_STAT bsbuf;
3999 status = split_ntfs_stream_name(talloc_tos(), fname,
4001 if (!NT_STATUS_IS_OK(status)) {
4002 DEBUG(10, ("create_file_unixpath: "
4003 "split_ntfs_stream_name failed: %s\n",
4004 nt_errstr(status)));
4005 reply_nterror(req, status);
4009 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4011 if (INFO_LEVEL_IS_UNIX(info_level)) {
4012 /* Always do lstat for UNIX calls. */
4013 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4014 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4015 reply_unixerror(req,ERRDOS,ERRbadpath);
4019 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4020 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4021 reply_unixerror(req,ERRDOS,ERRbadpath);
4026 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4027 get_file_infos(fileid, &delete_pending, NULL);
4028 if (delete_pending) {
4029 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4034 if (INFO_LEVEL_IS_UNIX(info_level)) {
4035 /* Always do lstat for UNIX calls. */
4036 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4037 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4038 reply_unixerror(req, ERRDOS, ERRbadpath);
4042 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4043 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4046 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4047 reply_unixerror(req, ERRDOS, ERRbadpath);
4052 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4053 get_file_infos(fileid, &delete_pending, &write_time_ts);
4054 if (delete_pending) {
4055 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4060 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4061 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4065 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4066 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4068 p = strrchr_m(fname,'/');
4075 mode = dos_mode_msdfs(conn,fname,&sbuf);
4077 mode = dos_mode(conn,fname,&sbuf);
4080 mode = FILE_ATTRIBUTE_NORMAL;
4082 nlink = sbuf.st_nlink;
4084 if (nlink && (mode&aDIR)) {
4088 if ((nlink > 0) && delete_pending) {
4092 fullpathname = fname;
4094 file_size = get_file_size_stat(&sbuf);
4096 /* Pull out any data sent here before we realloc. */
4097 switch (info_level) {
4098 case SMB_INFO_QUERY_EAS_FROM_LIST:
4100 /* Pull any EA list from the data portion. */
4103 if (total_data < 4) {
4105 req, NT_STATUS_INVALID_PARAMETER);
4108 ea_size = IVAL(pdata,0);
4110 if (total_data > 0 && ea_size != total_data) {
4111 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4112 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4114 req, NT_STATUS_INVALID_PARAMETER);
4118 if (!lp_ea_support(SNUM(conn))) {
4119 reply_doserror(req, ERRDOS,
4120 ERReasnotsupported);
4124 /* Pull out the list of names. */
4125 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4128 req, NT_STATUS_INVALID_PARAMETER);
4134 case SMB_QUERY_POSIX_LOCK:
4136 if (fsp == NULL || fsp->fh->fd == -1) {
4137 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4141 if (total_data != POSIX_LOCK_DATA_SIZE) {
4143 req, NT_STATUS_INVALID_PARAMETER);
4147 /* Copy the lock range data. */
4148 lock_data = (char *)TALLOC_MEMDUP(
4149 ctx, pdata, total_data);
4151 reply_nterror(req, NT_STATUS_NO_MEMORY);
4159 *pparams = (char *)SMB_REALLOC(*pparams,2);
4160 if (*pparams == NULL) {
4161 reply_nterror(req, NT_STATUS_NO_MEMORY);
4166 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4167 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4168 if (*ppdata == NULL ) {
4169 reply_nterror(req, NT_STATUS_NO_MEMORY);
4174 dend = dstart + data_size - 1;
4176 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4177 mtime_ts = get_mtimespec(&sbuf);
4178 atime_ts = get_atimespec(&sbuf);
4180 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4183 /* Do we have this path open ? */
4185 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4186 fsp1 = file_find_di_first(fileid);
4187 if (fsp1 && fsp1->initial_allocation_size) {
4188 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4192 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4193 mtime_ts = write_time_ts;
4196 if (lp_dos_filetime_resolution(SNUM(conn))) {
4197 dos_filetime_timespec(&create_time_ts);
4198 dos_filetime_timespec(&mtime_ts);
4199 dos_filetime_timespec(&atime_ts);
4202 create_time = convert_timespec_to_time_t(create_time_ts);
4203 mtime = convert_timespec_to_time_t(mtime_ts);
4204 atime = convert_timespec_to_time_t(atime_ts);
4206 /* NT expects the name to be in an exact form of the *full*
4207 filename. See the trans2 torture test */
4208 if (ISDOT(base_name)) {
4209 dos_fname = talloc_strdup(ctx, "\\");
4211 reply_nterror(req, NT_STATUS_NO_MEMORY);
4215 dos_fname = talloc_asprintf(ctx,
4219 reply_nterror(req, NT_STATUS_NO_MEMORY);
4222 string_replace(dos_fname, '/', '\\');
4225 switch (info_level) {
4226 case SMB_INFO_STANDARD:
4227 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4229 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4230 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4231 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4232 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4233 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4234 SSVAL(pdata,l1_attrFile,mode);
4237 case SMB_INFO_QUERY_EA_SIZE:
4239 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4240 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4242 srv_put_dos_date2(pdata,0,create_time);
4243 srv_put_dos_date2(pdata,4,atime);
4244 srv_put_dos_date2(pdata,8,mtime); /* write time */
4245 SIVAL(pdata,12,(uint32)file_size);
4246 SIVAL(pdata,16,(uint32)allocation_size);
4247 SSVAL(pdata,20,mode);
4248 SIVAL(pdata,22,ea_size);
4252 case SMB_INFO_IS_NAME_VALID:
4253 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4254 if (tran_call == TRANSACT2_QFILEINFO) {
4255 /* os/2 needs this ? really ?*/
4256 reply_doserror(req, ERRDOS, ERRbadfunc);
4263 case SMB_INFO_QUERY_EAS_FROM_LIST:
4265 size_t total_ea_len = 0;
4266 struct ea_list *ea_file_list = NULL;
4268 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4270 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4271 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4273 if (!ea_list || (total_ea_len > data_size)) {
4275 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4279 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4283 case SMB_INFO_QUERY_ALL_EAS:
4285 /* We have data_size bytes to put EA's into. */
4286 size_t total_ea_len = 0;
4288 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4290 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4291 if (!ea_list || (total_ea_len > data_size)) {
4293 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4297 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4301 case SMB_FILE_BASIC_INFORMATION:
4302 case SMB_QUERY_FILE_BASIC_INFO:
4304 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4305 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4306 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4308 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4312 put_long_date_timespec(pdata,create_time_ts);
4313 put_long_date_timespec(pdata+8,atime_ts);
4314 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4315 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4316 SIVAL(pdata,32,mode);
4318 DEBUG(5,("SMB_QFBI - "));
4319 DEBUG(5,("create: %s ", ctime(&create_time)));
4320 DEBUG(5,("access: %s ", ctime(&atime)));
4321 DEBUG(5,("write: %s ", ctime(&mtime)));
4322 DEBUG(5,("change: %s ", ctime(&mtime)));
4323 DEBUG(5,("mode: %x\n", mode));
4326 case SMB_FILE_STANDARD_INFORMATION:
4327 case SMB_QUERY_FILE_STANDARD_INFO:
4329 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4331 SOFF_T(pdata,0,allocation_size);
4332 SOFF_T(pdata,8,file_size);
4333 SIVAL(pdata,16,nlink);
4334 SCVAL(pdata,20,delete_pending?1:0);
4335 SCVAL(pdata,21,(mode&aDIR)?1:0);
4336 SSVAL(pdata,22,0); /* Padding. */
4339 case SMB_FILE_EA_INFORMATION:
4340 case SMB_QUERY_FILE_EA_INFO:
4342 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4343 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4345 SIVAL(pdata,0,ea_size);
4349 /* Get the 8.3 name - used if NT SMB was negotiated. */
4350 case SMB_QUERY_FILE_ALT_NAME_INFO:
4351 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4353 char mangled_name[13];
4354 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4355 if (!name_to_8_3(base_name,mangled_name,
4356 True,conn->params)) {
4359 NT_STATUS_NO_MEMORY);
4361 len = srvstr_push(dstart, req->flags2,
4362 pdata+4, mangled_name,
4363 PTR_DIFF(dend, pdata+4),
4365 data_size = 4 + len;
4370 case SMB_QUERY_FILE_NAME_INFO:
4372 this must be *exactly* right for ACLs on mapped drives to work
4374 len = srvstr_push(dstart, req->flags2,
4376 PTR_DIFF(dend, pdata+4),
4378 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4379 data_size = 4 + len;
4383 case SMB_FILE_ALLOCATION_INFORMATION:
4384 case SMB_QUERY_FILE_ALLOCATION_INFO:
4385 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4387 SOFF_T(pdata,0,allocation_size);
4390 case SMB_FILE_END_OF_FILE_INFORMATION:
4391 case SMB_QUERY_FILE_END_OF_FILEINFO:
4392 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4394 SOFF_T(pdata,0,file_size);
4397 case SMB_QUERY_FILE_ALL_INFO:
4398 case SMB_FILE_ALL_INFORMATION:
4400 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4401 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4402 put_long_date_timespec(pdata,create_time_ts);
4403 put_long_date_timespec(pdata+8,atime_ts);
4404 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4405 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4406 SIVAL(pdata,32,mode);
4407 SIVAL(pdata,36,0); /* padding. */
4409 SOFF_T(pdata,0,allocation_size);
4410 SOFF_T(pdata,8,file_size);
4411 SIVAL(pdata,16,nlink);
4412 SCVAL(pdata,20,delete_pending);
4413 SCVAL(pdata,21,(mode&aDIR)?1:0);
4416 SIVAL(pdata,0,ea_size);
4417 pdata += 4; /* EA info */
4418 len = srvstr_push(dstart, req->flags2,
4420 PTR_DIFF(dend, pdata+4),
4424 data_size = PTR_DIFF(pdata,(*ppdata));
4427 case SMB_FILE_INTERNAL_INFORMATION:
4428 /* This should be an index number - looks like
4431 I think this causes us to fail the IFSKIT
4432 BasicFileInformationTest. -tpot */
4434 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4435 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4436 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4440 case SMB_FILE_ACCESS_INFORMATION:
4441 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4443 SIVAL(pdata,0,fsp->access_mask);
4445 /* GENERIC_EXECUTE mapping from Windows */
4446 SIVAL(pdata,0,0x12019F);
4451 case SMB_FILE_NAME_INFORMATION:
4452 /* Pathname with leading '\'. */
4455 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4456 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4457 SIVAL(pdata,0,byte_len);
4458 data_size = 4 + byte_len;
4462 case SMB_FILE_DISPOSITION_INFORMATION:
4463 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4465 SCVAL(pdata,0,delete_pending);
4468 case SMB_FILE_POSITION_INFORMATION:
4469 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4471 SOFF_T(pdata,0,pos);
4474 case SMB_FILE_MODE_INFORMATION:
4475 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4476 SIVAL(pdata,0,mode);
4480 case SMB_FILE_ALIGNMENT_INFORMATION:
4481 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4482 SIVAL(pdata,0,0); /* No alignment needed. */
4487 * NT4 server just returns "invalid query" to this - if we try
4488 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4491 /* The first statement above is false - verified using Thursby
4492 * client against NT4 -- gcolley.
4494 case SMB_QUERY_FILE_STREAM_INFO:
4495 case SMB_FILE_STREAM_INFORMATION: {
4496 unsigned int num_streams;
4497 struct stream_struct *streams;
4500 DEBUG(10,("call_trans2qfilepathinfo: "
4501 "SMB_FILE_STREAM_INFORMATION\n"));
4503 status = SMB_VFS_STREAMINFO(
4504 conn, fsp, fname, talloc_tos(),
4505 &num_streams, &streams);
4507 if (!NT_STATUS_IS_OK(status)) {
4508 DEBUG(10, ("could not get stream info: %s\n",
4509 nt_errstr(status)));
4510 reply_nterror(req, status);
4514 status = marshall_stream_info(num_streams, streams,
4515 pdata, max_data_bytes,
4518 if (!NT_STATUS_IS_OK(status)) {
4519 DEBUG(10, ("marshall_stream_info failed: %s\n",
4520 nt_errstr(status)));
4521 reply_nterror(req, status);
4525 TALLOC_FREE(streams);
4529 case SMB_QUERY_COMPRESSION_INFO:
4530 case SMB_FILE_COMPRESSION_INFORMATION:
4531 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4532 SOFF_T(pdata,0,file_size);
4533 SIVAL(pdata,8,0); /* ??? */
4534 SIVAL(pdata,12,0); /* ??? */
4538 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4539 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4540 put_long_date_timespec(pdata,create_time_ts);
4541 put_long_date_timespec(pdata+8,atime_ts);
4542 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4543 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4544 SOFF_T(pdata,32,allocation_size);
4545 SOFF_T(pdata,40,file_size);
4546 SIVAL(pdata,48,mode);
4547 SIVAL(pdata,52,0); /* ??? */
4551 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4552 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4553 SIVAL(pdata,0,mode);
4559 * CIFS UNIX Extensions.
4562 case SMB_QUERY_FILE_UNIX_BASIC:
4564 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4565 data_size = PTR_DIFF(pdata,(*ppdata));
4569 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4571 for (i=0; i<100; i++)
4572 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4578 case SMB_QUERY_FILE_UNIX_INFO2:
4580 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4581 data_size = PTR_DIFF(pdata,(*ppdata));
4585 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4587 for (i=0; i<100; i++)
4588 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4594 case SMB_QUERY_FILE_UNIX_LINK:
4596 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4599 reply_nterror(req, NT_STATUS_NO_MEMORY);
4603 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4605 if(!S_ISLNK(sbuf.st_mode)) {
4606 reply_unixerror(req, ERRSRV,
4611 reply_unixerror(req, ERRDOS, ERRbadlink);
4614 len = SMB_VFS_READLINK(conn,fullpathname,
4617 reply_unixerror(req, ERRDOS,
4622 len = srvstr_push(dstart, req->flags2,
4624 PTR_DIFF(dend, pdata),
4627 data_size = PTR_DIFF(pdata,(*ppdata));
4632 #if defined(HAVE_POSIX_ACLS)
4633 case SMB_QUERY_POSIX_ACL:
4635 SMB_ACL_T file_acl = NULL;
4636 SMB_ACL_T def_acl = NULL;
4637 uint16 num_file_acls = 0;
4638 uint16 num_def_acls = 0;
4640 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4641 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4643 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4646 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4647 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4651 NT_STATUS_NOT_IMPLEMENTED);
4655 if (S_ISDIR(sbuf.st_mode)) {
4656 if (fsp && fsp->is_directory) {
4657 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4659 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4661 def_acl = free_empty_sys_acl(conn, def_acl);
4664 num_file_acls = count_acl_entries(conn, file_acl);
4665 num_def_acls = count_acl_entries(conn, def_acl);
4667 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4668 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4670 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4671 SMB_POSIX_ACL_HEADER_SIZE) ));
4673 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4676 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4680 NT_STATUS_BUFFER_TOO_SMALL);
4684 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4685 SSVAL(pdata,2,num_file_acls);
4686 SSVAL(pdata,4,num_def_acls);
4687 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4689 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4692 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4695 req, NT_STATUS_INTERNAL_ERROR);
4698 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4700 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4703 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4707 NT_STATUS_INTERNAL_ERROR);
4712 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4715 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4717 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4723 case SMB_QUERY_POSIX_LOCK:
4725 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4729 enum brl_type lock_type;
4731 if (total_data != POSIX_LOCK_DATA_SIZE) {
4733 req, NT_STATUS_INVALID_PARAMETER);
4737 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4738 case POSIX_LOCK_TYPE_READ:
4739 lock_type = READ_LOCK;
4741 case POSIX_LOCK_TYPE_WRITE:
4742 lock_type = WRITE_LOCK;
4744 case POSIX_LOCK_TYPE_UNLOCK:
4746 /* There's no point in asking for an unlock... */
4749 NT_STATUS_INVALID_PARAMETER);
4753 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4754 #if defined(HAVE_LONGLONG)
4755 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4756 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4757 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4758 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4759 #else /* HAVE_LONGLONG */
4760 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4761 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4762 #endif /* HAVE_LONGLONG */
4764 status = query_lock(fsp,
4771 if (ERROR_WAS_LOCK_DENIED(status)) {
4772 /* Here we need to report who has it locked... */
4773 data_size = POSIX_LOCK_DATA_SIZE;
4775 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4776 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4777 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4778 #if defined(HAVE_LONGLONG)
4779 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4780 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4781 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4782 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4783 #else /* HAVE_LONGLONG */
4784 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4785 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4786 #endif /* HAVE_LONGLONG */
4788 } else if (NT_STATUS_IS_OK(status)) {
4789 /* For success we just return a copy of what we sent
4790 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4791 data_size = POSIX_LOCK_DATA_SIZE;
4792 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4793 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4795 reply_nterror(req, status);
4802 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4806 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4812 /****************************************************************************
4813 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4815 ****************************************************************************/
4817 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4818 connection_struct *conn,
4819 const char *oldname_in,
4820 const char *newname_in)
4822 SMB_STRUCT_STAT sbuf1, sbuf2;
4823 char *last_component_oldname = NULL;
4824 char *last_component_newname = NULL;
4825 char *oldname = NULL;
4826 char *newname = NULL;
4827 NTSTATUS status = NT_STATUS_OK;
4832 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4833 &last_component_oldname, &sbuf1);
4834 if (!NT_STATUS_IS_OK(status)) {
4838 status = check_name(conn, oldname);
4839 if (!NT_STATUS_IS_OK(status)) {
4843 /* source must already exist. */
4844 if (!VALID_STAT(sbuf1)) {
4845 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4848 status = unix_convert(ctx, conn, newname_in, False, &newname,
4849 &last_component_newname, &sbuf2);
4850 if (!NT_STATUS_IS_OK(status)) {
4854 status = check_name(conn, newname);
4855 if (!NT_STATUS_IS_OK(status)) {
4859 /* Disallow if newname already exists. */
4860 if (VALID_STAT(sbuf2)) {
4861 return NT_STATUS_OBJECT_NAME_COLLISION;
4864 /* No links from a directory. */
4865 if (S_ISDIR(sbuf1.st_mode)) {
4866 return NT_STATUS_FILE_IS_A_DIRECTORY;
4869 /* Ensure this is within the share. */
4870 status = check_reduced_name(conn, oldname);
4871 if (!NT_STATUS_IS_OK(status)) {
4875 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4877 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4878 status = map_nt_error_from_unix(errno);
4879 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4880 nt_errstr(status), newname, oldname));
4886 /****************************************************************************
4887 Deal with setting the time from any of the setfilepathinfo functions.
4888 ****************************************************************************/
4890 NTSTATUS smb_set_file_time(connection_struct *conn,
4893 const SMB_STRUCT_STAT *psbuf,
4894 struct smb_file_time *ft,
4895 bool setting_write_time)
4898 FILE_NOTIFY_CHANGE_LAST_ACCESS
4899 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4901 if (!VALID_STAT(*psbuf)) {
4902 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4905 /* get some defaults (no modifications) if any info is zero or -1. */
4906 if (null_timespec(ft->atime)) {
4907 ft->atime= get_atimespec(psbuf);
4908 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4911 if (null_timespec(ft->mtime)) {
4912 ft->mtime = get_mtimespec(psbuf);
4913 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4916 if (!setting_write_time) {
4917 /* ft->mtime comes from change time, not write time. */
4918 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4921 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4922 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4923 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4924 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4925 if (!null_timespec(ft->create_time)) {
4926 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4927 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4931 * Try and set the times of this file if
4932 * they are different from the current values.
4936 struct timespec mts = get_mtimespec(psbuf);
4937 struct timespec ats = get_atimespec(psbuf);
4938 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4939 (timespec_compare(&ft->mtime, &mts) == 0)) {
4940 return NT_STATUS_OK;
4944 if (setting_write_time) {
4946 * This was a setfileinfo on an open file.
4947 * NT does this a lot. We also need to
4948 * set the time here, as it can be read by
4949 * FindFirst/FindNext and with the patch for bug #2045
4950 * in smbd/fileio.c it ensures that this timestamp is
4951 * kept sticky even after a write. We save the request
4952 * away and will set it on file close and after a write. JRA.
4955 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4956 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4959 if (fsp->base_fsp) {
4960 set_sticky_write_time_fsp(fsp->base_fsp,
4963 set_sticky_write_time_fsp(fsp, ft->mtime);
4966 set_sticky_write_time_path(conn, fname,
4967 vfs_file_id_from_sbuf(conn, psbuf),
4972 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4974 if (fsp && fsp->base_fsp) {
4975 fname = fsp->base_fsp->fsp_name;
4978 if(file_ntimes(conn, fname, ft)!=0) {
4979 return map_nt_error_from_unix(errno);
4981 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4983 return NT_STATUS_OK;
4986 /****************************************************************************
4987 Deal with setting the dosmode from any of the setfilepathinfo functions.
4988 ****************************************************************************/
4990 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4993 SMB_STRUCT_STAT *psbuf,
4996 if (!VALID_STAT(*psbuf)) {
4997 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5001 if (fsp->base_fsp) {
5002 fname = fsp->base_fsp->fsp_name;
5004 fname = fsp->fsp_name;
5009 if (S_ISDIR(psbuf->st_mode)) {
5016 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5018 /* check the mode isn't different, before changing it */
5019 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5021 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5022 fname, (unsigned int)dosmode ));
5024 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5025 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5026 fname, strerror(errno)));
5027 return map_nt_error_from_unix(errno);
5030 return NT_STATUS_OK;
5033 /****************************************************************************
5034 Deal with setting the size from any of the setfilepathinfo functions.
5035 ****************************************************************************/
5037 static NTSTATUS smb_set_file_size(connection_struct *conn,
5038 struct smb_request *req,
5041 SMB_STRUCT_STAT *psbuf,
5044 NTSTATUS status = NT_STATUS_OK;
5045 files_struct *new_fsp = NULL;
5047 if (!VALID_STAT(*psbuf)) {
5048 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5051 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5053 if (size == get_file_size_stat(psbuf)) {
5054 return NT_STATUS_OK;
5057 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5058 fname, (double)size ));
5060 if (fsp && fsp->fh->fd != -1) {
5061 /* Handle based call. */
5062 if (vfs_set_filelen(fsp, size) == -1) {
5063 return map_nt_error_from_unix(errno);
5065 trigger_write_time_update_immediate(fsp);
5066 return NT_STATUS_OK;
5069 status = SMB_VFS_CREATE_FILE(
5072 0, /* root_dir_fid */
5074 0, /* create_file_flags */
5075 FILE_WRITE_ATTRIBUTES, /* access_mask */
5076 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5078 FILE_OPEN, /* create_disposition*/
5079 0, /* create_options */
5080 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5081 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5082 0, /* allocation_size */
5085 &new_fsp, /* result */
5089 if (!NT_STATUS_IS_OK(status)) {
5090 /* NB. We check for open_was_deferred in the caller. */
5094 if (vfs_set_filelen(new_fsp, size) == -1) {
5095 status = map_nt_error_from_unix(errno);
5096 close_file(req, new_fsp,NORMAL_CLOSE);
5100 trigger_write_time_update_immediate(new_fsp);
5101 close_file(req, new_fsp,NORMAL_CLOSE);
5102 return NT_STATUS_OK;
5105 /****************************************************************************
5106 Deal with SMB_INFO_SET_EA.
5107 ****************************************************************************/
5109 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5115 struct ea_list *ea_list = NULL;
5116 TALLOC_CTX *ctx = NULL;
5117 NTSTATUS status = NT_STATUS_OK;
5119 if (total_data < 10) {
5121 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5122 length. They seem to have no effect. Bug #3212. JRA */
5124 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5125 /* We're done. We only get EA info in this call. */
5126 return NT_STATUS_OK;
5129 return NT_STATUS_INVALID_PARAMETER;
5132 if (IVAL(pdata,0) > total_data) {
5133 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5134 IVAL(pdata,0), (unsigned int)total_data));
5135 return NT_STATUS_INVALID_PARAMETER;
5139 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5141 return NT_STATUS_INVALID_PARAMETER;
5143 status = set_ea(conn, fsp, fname, ea_list);
5148 /****************************************************************************
5149 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5150 ****************************************************************************/
5152 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5157 SMB_STRUCT_STAT *psbuf)
5159 NTSTATUS status = NT_STATUS_OK;
5160 bool delete_on_close;
5163 if (total_data < 1) {
5164 return NT_STATUS_INVALID_PARAMETER;
5168 return NT_STATUS_INVALID_HANDLE;
5171 delete_on_close = (CVAL(pdata,0) ? True : False);
5172 dosmode = dos_mode(conn, fname, psbuf);
5174 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5175 "delete_on_close = %u\n",
5177 (unsigned int)dosmode,
5178 (unsigned int)delete_on_close ));
5180 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5182 if (!NT_STATUS_IS_OK(status)) {
5186 /* The set is across all open files on this dev/inode pair. */
5187 if (!set_delete_on_close(fsp, delete_on_close,
5188 &conn->server_info->utok)) {
5189 return NT_STATUS_ACCESS_DENIED;
5191 return NT_STATUS_OK;
5194 /****************************************************************************
5195 Deal with SMB_FILE_POSITION_INFORMATION.
5196 ****************************************************************************/
5198 static NTSTATUS smb_file_position_information(connection_struct *conn,
5203 uint64_t position_information;
5205 if (total_data < 8) {
5206 return NT_STATUS_INVALID_PARAMETER;
5210 /* Ignore on pathname based set. */
5211 return NT_STATUS_OK;
5214 position_information = (uint64_t)IVAL(pdata,0);
5215 #ifdef LARGE_SMB_OFF_T
5216 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5217 #else /* LARGE_SMB_OFF_T */
5218 if (IVAL(pdata,4) != 0) {
5219 /* more than 32 bits? */
5220 return NT_STATUS_INVALID_PARAMETER;
5222 #endif /* LARGE_SMB_OFF_T */
5224 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5225 fsp->fsp_name, (double)position_information ));
5226 fsp->fh->position_information = position_information;
5227 return NT_STATUS_OK;
5230 /****************************************************************************
5231 Deal with SMB_FILE_MODE_INFORMATION.
5232 ****************************************************************************/
5234 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5240 if (total_data < 4) {
5241 return NT_STATUS_INVALID_PARAMETER;
5243 mode = IVAL(pdata,0);
5244 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5245 return NT_STATUS_INVALID_PARAMETER;
5247 return NT_STATUS_OK;
5250 /****************************************************************************
5251 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5252 ****************************************************************************/
5254 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5255 struct smb_request *req,
5260 char *link_target = NULL;
5261 const char *newname = fname;
5262 NTSTATUS status = NT_STATUS_OK;
5263 TALLOC_CTX *ctx = talloc_tos();
5265 /* Set a symbolic link. */
5266 /* Don't allow this if follow links is false. */
5268 if (total_data == 0) {
5269 return NT_STATUS_INVALID_PARAMETER;
5272 if (!lp_symlinks(SNUM(conn))) {
5273 return NT_STATUS_ACCESS_DENIED;
5276 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5277 total_data, STR_TERMINATE);
5280 return NT_STATUS_INVALID_PARAMETER;
5283 /* !widelinks forces the target path to be within the share. */
5284 /* This means we can interpret the target as a pathname. */
5285 if (!lp_widelinks(SNUM(conn))) {
5286 char *rel_name = NULL;
5287 char *last_dirp = NULL;
5289 if (*link_target == '/') {
5290 /* No absolute paths allowed. */
5291 return NT_STATUS_ACCESS_DENIED;
5293 rel_name = talloc_strdup(ctx,newname);
5295 return NT_STATUS_NO_MEMORY;
5297 last_dirp = strrchr_m(rel_name, '/');
5299 last_dirp[1] = '\0';
5301 rel_name = talloc_strdup(ctx,"./");
5303 return NT_STATUS_NO_MEMORY;
5306 rel_name = talloc_asprintf_append(rel_name,
5310 return NT_STATUS_NO_MEMORY;
5313 status = check_name(conn, rel_name);
5314 if (!NT_STATUS_IS_OK(status)) {
5319 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5320 newname, link_target ));
5322 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5323 return map_nt_error_from_unix(errno);
5326 return NT_STATUS_OK;
5329 /****************************************************************************
5330 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5331 ****************************************************************************/
5333 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5334 struct smb_request *req,
5335 const char *pdata, int total_data,
5338 char *oldname = NULL;
5339 TALLOC_CTX *ctx = talloc_tos();
5340 NTSTATUS status = NT_STATUS_OK;
5342 /* Set a hard link. */
5343 if (total_data == 0) {
5344 return NT_STATUS_INVALID_PARAMETER;
5347 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5348 total_data, STR_TERMINATE, &status);
5349 if (!NT_STATUS_IS_OK(status)) {
5353 status = resolve_dfspath(ctx, conn,
5354 req->flags2 & FLAGS2_DFS_PATHNAMES,
5357 if (!NT_STATUS_IS_OK(status)) {
5361 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5364 return hardlink_internals(ctx, conn, oldname, fname);
5367 /****************************************************************************
5368 Deal with SMB_FILE_RENAME_INFORMATION.
5369 ****************************************************************************/
5371 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5372 struct smb_request *req,
5381 char *newname = NULL;
5382 char *base_name = NULL;
5383 bool dest_has_wcard = False;
5384 SMB_STRUCT_STAT sbuf;
5385 char *newname_last_component = NULL;
5386 NTSTATUS status = NT_STATUS_OK;
5388 TALLOC_CTX *ctx = talloc_tos();
5390 if (total_data < 13) {
5391 return NT_STATUS_INVALID_PARAMETER;
5396 overwrite = (CVAL(pdata,0) ? True : False);
5397 root_fid = IVAL(pdata,4);
5398 len = IVAL(pdata,8);
5400 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5401 return NT_STATUS_INVALID_PARAMETER;
5404 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5407 if (!NT_STATUS_IS_OK(status)) {
5411 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5414 status = resolve_dfspath_wcard(ctx, conn,
5415 req->flags2 & FLAGS2_DFS_PATHNAMES,
5419 if (!NT_STATUS_IS_OK(status)) {
5423 /* Check the new name has no '/' characters. */
5424 if (strchr_m(newname, '/')) {
5425 return NT_STATUS_NOT_SUPPORTED;
5428 if (fsp && fsp->base_fsp) {
5429 /* newname must be a stream name. */
5430 if (newname[0] != ':') {
5431 return NT_STATUS_NOT_SUPPORTED;
5433 base_name = talloc_asprintf(ctx, "%s%s",
5434 fsp->base_fsp->fsp_name,
5437 return NT_STATUS_NO_MEMORY;
5440 /* newname must *not* be a stream name. */
5441 if (is_ntfs_stream_name(newname)) {
5442 return NT_STATUS_NOT_SUPPORTED;
5445 /* Create the base directory. */
5446 base_name = talloc_strdup(ctx, fname);
5448 return NT_STATUS_NO_MEMORY;
5450 p = strrchr_m(base_name, '/');
5454 base_name = talloc_strdup(ctx, "./");
5456 return NT_STATUS_NO_MEMORY;
5459 /* Append the new name. */
5460 base_name = talloc_asprintf_append(base_name,
5464 return NT_STATUS_NO_MEMORY;
5467 status = unix_convert(ctx, conn, newname, False,
5469 &newname_last_component,
5472 /* If an error we expect this to be
5473 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5475 if (!NT_STATUS_IS_OK(status)
5476 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5483 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5484 fsp->fnum, fsp->fsp_name, base_name ));
5485 status = rename_internals_fsp(conn, fsp, base_name,
5486 newname_last_component, 0,
5489 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5490 fname, base_name ));
5491 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5492 overwrite, False, dest_has_wcard,
5493 FILE_WRITE_ATTRIBUTES);
5499 /****************************************************************************
5500 Deal with SMB_SET_POSIX_ACL.
5501 ****************************************************************************/
5503 #if defined(HAVE_POSIX_ACLS)
5504 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5509 SMB_STRUCT_STAT *psbuf)
5511 uint16 posix_acl_version;
5512 uint16 num_file_acls;
5513 uint16 num_def_acls;
5514 bool valid_file_acls = True;
5515 bool valid_def_acls = True;
5517 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5518 return NT_STATUS_INVALID_PARAMETER;
5520 posix_acl_version = SVAL(pdata,0);
5521 num_file_acls = SVAL(pdata,2);
5522 num_def_acls = SVAL(pdata,4);
5524 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5525 valid_file_acls = False;
5529 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5530 valid_def_acls = False;
5534 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5535 return NT_STATUS_INVALID_PARAMETER;
5538 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5539 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5540 return NT_STATUS_INVALID_PARAMETER;
5543 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5544 fname ? fname : fsp->fsp_name,
5545 (unsigned int)num_file_acls,
5546 (unsigned int)num_def_acls));
5548 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5549 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5550 return map_nt_error_from_unix(errno);
5553 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5554 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5555 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5556 return map_nt_error_from_unix(errno);
5558 return NT_STATUS_OK;
5562 /****************************************************************************
5563 Deal with SMB_SET_POSIX_LOCK.
5564 ****************************************************************************/
5566 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5567 struct smb_request *req,
5575 bool blocking_lock = False;
5576 enum brl_type lock_type;
5578 NTSTATUS status = NT_STATUS_OK;
5580 if (fsp == NULL || fsp->fh->fd == -1) {
5581 return NT_STATUS_INVALID_HANDLE;
5584 if (total_data != POSIX_LOCK_DATA_SIZE) {
5585 return NT_STATUS_INVALID_PARAMETER;
5588 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5589 case POSIX_LOCK_TYPE_READ:
5590 lock_type = READ_LOCK;
5592 case POSIX_LOCK_TYPE_WRITE:
5593 /* Return the right POSIX-mappable error code for files opened read-only. */
5594 if (!fsp->can_write) {
5595 return NT_STATUS_INVALID_HANDLE;
5597 lock_type = WRITE_LOCK;
5599 case POSIX_LOCK_TYPE_UNLOCK:
5600 lock_type = UNLOCK_LOCK;
5603 return NT_STATUS_INVALID_PARAMETER;
5606 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5607 blocking_lock = False;
5608 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5609 blocking_lock = True;
5611 return NT_STATUS_INVALID_PARAMETER;
5614 if (!lp_blocking_locks(SNUM(conn))) {
5615 blocking_lock = False;
5618 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5619 #if defined(HAVE_LONGLONG)
5620 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5621 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5622 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5623 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5624 #else /* HAVE_LONGLONG */
5625 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5626 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5627 #endif /* HAVE_LONGLONG */
5629 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5630 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5632 (unsigned int)lock_type,
5633 (unsigned int)lock_pid,
5637 if (lock_type == UNLOCK_LOCK) {
5638 status = do_unlock(smbd_messaging_context(),
5645 uint32 block_smbpid;
5647 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5659 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5661 * A blocking lock was requested. Package up
5662 * this smb into a queued request and push it
5663 * onto the blocking lock queue.
5665 if(push_blocking_lock_request(br_lck,
5668 -1, /* infinite timeout. */
5676 TALLOC_FREE(br_lck);
5680 TALLOC_FREE(br_lck);
5686 /****************************************************************************
5687 Deal with SMB_INFO_STANDARD.
5688 ****************************************************************************/
5690 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5695 const SMB_STRUCT_STAT *psbuf)
5697 struct smb_file_time ft;
5700 if (total_data < 12) {
5701 return NT_STATUS_INVALID_PARAMETER;
5705 ft.create_time = interpret_long_date(pdata);
5708 ft.atime = interpret_long_date(pdata + 8);
5711 ft.mtime = interpret_long_date(pdata + 16);
5713 DEBUG(10,("smb_set_info_standard: file %s\n",
5714 fname ? fname : fsp->fsp_name ));
5716 return smb_set_file_time(conn,
5724 /****************************************************************************
5725 Deal with SMB_SET_FILE_BASIC_INFO.
5726 ****************************************************************************/
5728 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5733 SMB_STRUCT_STAT *psbuf)
5735 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5736 struct timespec write_time;
5737 struct timespec changed_time;
5738 struct smb_file_time ft;
5740 NTSTATUS status = NT_STATUS_OK;
5741 bool setting_write_time = true;
5745 if (total_data < 36) {
5746 return NT_STATUS_INVALID_PARAMETER;
5749 /* Set the attributes */
5750 dosmode = IVAL(pdata,32);
5751 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5752 if (!NT_STATUS_IS_OK(status)) {
5757 ft.atime = interpret_long_date(pdata+8);
5759 write_time = interpret_long_date(pdata+16);
5760 changed_time = interpret_long_date(pdata+24);
5763 ft.mtime = timespec_min(&write_time, &changed_time);
5766 ft.create_time = interpret_long_date(pdata);
5768 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5769 !null_timespec(write_time)) {
5770 ft.mtime = write_time;
5773 /* Prefer a defined time to an undefined one. */
5774 if (null_timespec(ft.mtime)) {
5775 if (null_timespec(write_time)) {
5776 ft.mtime = changed_time;
5777 setting_write_time = false;
5779 ft.mtime = write_time;
5783 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5784 fname ? fname : fsp->fsp_name ));
5786 return smb_set_file_time(conn,
5791 setting_write_time);
5794 /****************************************************************************
5795 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5796 ****************************************************************************/
5798 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5799 struct smb_request *req,
5804 SMB_STRUCT_STAT *psbuf)
5806 uint64_t allocation_size = 0;
5807 NTSTATUS status = NT_STATUS_OK;
5808 files_struct *new_fsp = NULL;
5810 if (!VALID_STAT(*psbuf)) {
5811 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5814 if (total_data < 8) {
5815 return NT_STATUS_INVALID_PARAMETER;
5818 allocation_size = (uint64_t)IVAL(pdata,0);
5819 #ifdef LARGE_SMB_OFF_T
5820 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5821 #else /* LARGE_SMB_OFF_T */
5822 if (IVAL(pdata,4) != 0) {
5823 /* more than 32 bits? */
5824 return NT_STATUS_INVALID_PARAMETER;
5826 #endif /* LARGE_SMB_OFF_T */
5828 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5829 fname, (double)allocation_size ));
5831 if (allocation_size) {
5832 allocation_size = smb_roundup(conn, allocation_size);
5835 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5836 fname, (double)allocation_size ));
5838 if (fsp && fsp->fh->fd != -1) {
5839 /* Open file handle. */
5840 /* Only change if needed. */
5841 if (allocation_size != get_file_size_stat(psbuf)) {
5842 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5843 return map_nt_error_from_unix(errno);
5846 /* But always update the time. */
5848 * This is equivalent to a write. Ensure it's seen immediately
5849 * if there are no pending writes.
5851 trigger_write_time_update_immediate(fsp);
5852 return NT_STATUS_OK;
5855 /* Pathname or stat or directory file. */
5857 status = SMB_VFS_CREATE_FILE(
5860 0, /* root_dir_fid */
5862 0, /* create_file_flags */
5863 FILE_WRITE_DATA, /* access_mask */
5864 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5866 FILE_OPEN, /* create_disposition*/
5867 0, /* create_options */
5868 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5869 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5870 0, /* allocation_size */
5873 &new_fsp, /* result */
5877 if (!NT_STATUS_IS_OK(status)) {
5878 /* NB. We check for open_was_deferred in the caller. */
5882 /* Only change if needed. */
5883 if (allocation_size != get_file_size_stat(psbuf)) {
5884 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5885 status = map_nt_error_from_unix(errno);
5886 close_file(req, new_fsp, NORMAL_CLOSE);
5891 /* Changing the allocation size should set the last mod time. */
5893 * This is equivalent to a write. Ensure it's seen immediately
5894 * if there are no pending writes.
5896 trigger_write_time_update_immediate(new_fsp);
5898 close_file(req, new_fsp, NORMAL_CLOSE);
5899 return NT_STATUS_OK;
5902 /****************************************************************************
5903 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5904 ****************************************************************************/
5906 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5907 struct smb_request *req,
5912 SMB_STRUCT_STAT *psbuf)
5916 if (total_data < 8) {
5917 return NT_STATUS_INVALID_PARAMETER;
5920 size = IVAL(pdata,0);
5921 #ifdef LARGE_SMB_OFF_T
5922 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5923 #else /* LARGE_SMB_OFF_T */
5924 if (IVAL(pdata,4) != 0) {
5925 /* more than 32 bits? */
5926 return NT_STATUS_INVALID_PARAMETER;
5928 #endif /* LARGE_SMB_OFF_T */
5929 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5930 "file %s to %.0f\n", fname, (double)size ));
5932 return smb_set_file_size(conn, req,
5939 /****************************************************************************
5940 Allow a UNIX info mknod.
5941 ****************************************************************************/
5943 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5947 SMB_STRUCT_STAT *psbuf)
5949 uint32 file_type = IVAL(pdata,56);
5950 #if defined(HAVE_MAKEDEV)
5951 uint32 dev_major = IVAL(pdata,60);
5952 uint32 dev_minor = IVAL(pdata,68);
5954 SMB_DEV_T dev = (SMB_DEV_T)0;
5955 uint32 raw_unixmode = IVAL(pdata,84);
5959 if (total_data < 100) {
5960 return NT_STATUS_INVALID_PARAMETER;
5963 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5964 if (!NT_STATUS_IS_OK(status)) {
5968 #if defined(HAVE_MAKEDEV)
5969 dev = makedev(dev_major, dev_minor);
5972 switch (file_type) {
5973 #if defined(S_IFIFO)
5974 case UNIX_TYPE_FIFO:
5975 unixmode |= S_IFIFO;
5978 #if defined(S_IFSOCK)
5979 case UNIX_TYPE_SOCKET:
5980 unixmode |= S_IFSOCK;
5983 #if defined(S_IFCHR)
5984 case UNIX_TYPE_CHARDEV:
5985 unixmode |= S_IFCHR;
5988 #if defined(S_IFBLK)
5989 case UNIX_TYPE_BLKDEV:
5990 unixmode |= S_IFBLK;
5994 return NT_STATUS_INVALID_PARAMETER;
5997 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5998 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6000 /* Ok - do the mknod. */
6001 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6002 return map_nt_error_from_unix(errno);
6005 /* If any of the other "set" calls fail we
6006 * don't want to end up with a half-constructed mknod.
6009 if (lp_inherit_perms(SNUM(conn))) {
6011 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6012 return NT_STATUS_NO_MEMORY;
6014 inherit_access_posix_acl(conn, parent, fname, unixmode);
6015 TALLOC_FREE(parent);
6018 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6019 status = map_nt_error_from_unix(errno);
6020 SMB_VFS_UNLINK(conn,fname);
6023 return NT_STATUS_OK;
6026 /****************************************************************************
6027 Deal with SMB_SET_FILE_UNIX_BASIC.
6028 ****************************************************************************/
6030 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6031 struct smb_request *req,
6036 SMB_STRUCT_STAT *psbuf)
6038 struct smb_file_time ft;
6039 uint32 raw_unixmode;
6042 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6043 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6044 NTSTATUS status = NT_STATUS_OK;
6045 bool delete_on_fail = False;
6046 enum perm_type ptype;
6050 if (total_data < 100) {
6051 return NT_STATUS_INVALID_PARAMETER;
6054 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6055 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6056 size=IVAL(pdata,0); /* first 8 Bytes are size */
6057 #ifdef LARGE_SMB_OFF_T
6058 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6059 #else /* LARGE_SMB_OFF_T */
6060 if (IVAL(pdata,4) != 0) {
6061 /* more than 32 bits? */
6062 return NT_STATUS_INVALID_PARAMETER;
6064 #endif /* LARGE_SMB_OFF_T */
6067 ft.atime = interpret_long_date(pdata+24); /* access_time */
6068 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6069 set_owner = (uid_t)IVAL(pdata,40);
6070 set_grp = (gid_t)IVAL(pdata,48);
6071 raw_unixmode = IVAL(pdata,84);
6073 if (VALID_STAT(*psbuf)) {
6074 if (S_ISDIR(psbuf->st_mode)) {
6075 ptype = PERM_EXISTING_DIR;
6077 ptype = PERM_EXISTING_FILE;
6080 ptype = PERM_NEW_FILE;
6083 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6084 if (!NT_STATUS_IS_OK(status)) {
6088 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6089 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6090 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6092 if (!VALID_STAT(*psbuf)) {
6094 * The only valid use of this is to create character and block
6095 * devices, and named pipes. This is deprecated (IMHO) and
6096 * a new info level should be used for mknod. JRA.
6099 status = smb_unix_mknod(conn,
6104 if (!NT_STATUS_IS_OK(status)) {
6108 /* Ensure we don't try and change anything else. */
6109 raw_unixmode = SMB_MODE_NO_CHANGE;
6110 size = get_file_size_stat(psbuf);
6111 ft.atime = get_atimespec(psbuf);
6112 ft.mtime = get_mtimespec(psbuf);
6114 * We continue here as we might want to change the
6117 delete_on_fail = True;
6121 /* Horrible backwards compatibility hack as an old server bug
6122 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6126 size = get_file_size_stat(psbuf);
6131 * Deal with the UNIX specific mode set.
6134 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6135 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6136 (unsigned int)unixmode, fname ));
6137 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6138 return map_nt_error_from_unix(errno);
6143 * Deal with the UNIX specific uid set.
6146 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6149 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6150 (unsigned int)set_owner, fname ));
6152 if (S_ISLNK(psbuf->st_mode)) {
6153 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6155 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6159 status = map_nt_error_from_unix(errno);
6160 if (delete_on_fail) {
6161 SMB_VFS_UNLINK(conn,fname);
6168 * Deal with the UNIX specific gid set.
6171 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6172 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6173 (unsigned int)set_owner, fname ));
6174 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6175 status = map_nt_error_from_unix(errno);
6176 if (delete_on_fail) {
6177 SMB_VFS_UNLINK(conn,fname);
6183 /* Deal with any size changes. */
6185 status = smb_set_file_size(conn, req,
6190 if (!NT_STATUS_IS_OK(status)) {
6194 /* Deal with any time changes. */
6196 return smb_set_file_time(conn,
6204 /****************************************************************************
6205 Deal with SMB_SET_FILE_UNIX_INFO2.
6206 ****************************************************************************/
6208 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6209 struct smb_request *req,
6214 SMB_STRUCT_STAT *psbuf)
6220 if (total_data < 116) {
6221 return NT_STATUS_INVALID_PARAMETER;
6224 /* Start by setting all the fields that are common between UNIX_BASIC
6227 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6229 if (!NT_STATUS_IS_OK(status)) {
6233 smb_fflags = IVAL(pdata, 108);
6234 smb_fmask = IVAL(pdata, 112);
6236 /* NB: We should only attempt to alter the file flags if the client
6237 * sends a non-zero mask.
6239 if (smb_fmask != 0) {
6240 int stat_fflags = 0;
6242 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6244 /* Client asked to alter a flag we don't understand. */
6245 return NT_STATUS_INVALID_PARAMETER;
6248 if (fsp && fsp->fh->fd != -1) {
6249 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6250 return NT_STATUS_NOT_SUPPORTED;
6252 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6253 return map_nt_error_from_unix(errno);
6258 /* XXX: need to add support for changing the create_time here. You
6259 * can do this for paths on Darwin with setattrlist(2). The right way
6260 * to hook this up is probably by extending the VFS utimes interface.
6263 return NT_STATUS_OK;
6266 /****************************************************************************
6267 Create a directory with POSIX semantics.
6268 ****************************************************************************/
6270 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6271 struct smb_request *req,
6275 SMB_STRUCT_STAT *psbuf,
6276 int *pdata_return_size)
6278 NTSTATUS status = NT_STATUS_OK;
6279 uint32 raw_unixmode = 0;
6280 uint32 mod_unixmode = 0;
6281 mode_t unixmode = (mode_t)0;
6282 files_struct *fsp = NULL;
6283 uint16 info_level_return = 0;
6285 char *pdata = *ppdata;
6287 if (total_data < 18) {
6288 return NT_STATUS_INVALID_PARAMETER;
6291 raw_unixmode = IVAL(pdata,8);
6292 /* Next 4 bytes are not yet defined. */
6294 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6295 if (!NT_STATUS_IS_OK(status)) {
6299 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6301 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6302 fname, (unsigned int)unixmode ));
6304 status = SMB_VFS_CREATE_FILE(
6307 0, /* root_dir_fid */
6309 0, /* create_file_flags */
6310 FILE_READ_ATTRIBUTES, /* access_mask */
6311 FILE_SHARE_NONE, /* share_access */
6312 FILE_CREATE, /* create_disposition*/
6313 FILE_DIRECTORY_FILE, /* create_options */
6314 mod_unixmode, /* file_attributes */
6315 0, /* oplock_request */
6316 0, /* allocation_size */
6323 if (NT_STATUS_IS_OK(status)) {
6324 close_file(req, fsp, NORMAL_CLOSE);
6327 info_level_return = SVAL(pdata,16);
6329 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6330 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6331 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6332 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6334 *pdata_return_size = 12;
6337 /* Realloc the data size */
6338 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6339 if (*ppdata == NULL) {
6340 *pdata_return_size = 0;
6341 return NT_STATUS_NO_MEMORY;
6345 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6346 SSVAL(pdata,2,0); /* No fnum. */
6347 SIVAL(pdata,4,info); /* Was directory created. */
6349 switch (info_level_return) {
6350 case SMB_QUERY_FILE_UNIX_BASIC:
6351 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6352 SSVAL(pdata,10,0); /* Padding. */
6353 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6355 case SMB_QUERY_FILE_UNIX_INFO2:
6356 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6357 SSVAL(pdata,10,0); /* Padding. */
6358 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6361 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6362 SSVAL(pdata,10,0); /* Padding. */
6369 /****************************************************************************
6370 Open/Create a file with POSIX semantics.
6371 ****************************************************************************/
6373 static NTSTATUS smb_posix_open(connection_struct *conn,
6374 struct smb_request *req,
6378 SMB_STRUCT_STAT *psbuf,
6379 int *pdata_return_size)
6381 bool extended_oplock_granted = False;
6382 char *pdata = *ppdata;
6384 uint32 wire_open_mode = 0;
6385 uint32 raw_unixmode = 0;
6386 uint32 mod_unixmode = 0;
6387 uint32 create_disp = 0;
6388 uint32 access_mask = 0;
6389 uint32 create_options = 0;
6390 NTSTATUS status = NT_STATUS_OK;
6391 mode_t unixmode = (mode_t)0;
6392 files_struct *fsp = NULL;
6393 int oplock_request = 0;
6395 uint16 info_level_return = 0;
6397 if (total_data < 18) {
6398 return NT_STATUS_INVALID_PARAMETER;
6401 flags = IVAL(pdata,0);
6402 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6403 if (oplock_request) {
6404 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6407 wire_open_mode = IVAL(pdata,4);
6409 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6410 return smb_posix_mkdir(conn, req,
6418 switch (wire_open_mode & SMB_ACCMODE) {
6420 access_mask = FILE_READ_DATA;
6423 access_mask = FILE_WRITE_DATA;
6426 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6429 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6430 (unsigned int)wire_open_mode ));
6431 return NT_STATUS_INVALID_PARAMETER;
6434 wire_open_mode &= ~SMB_ACCMODE;
6436 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6437 create_disp = FILE_CREATE;
6438 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6439 create_disp = FILE_OVERWRITE_IF;
6440 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6441 create_disp = FILE_OPEN_IF;
6442 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6443 create_disp = FILE_OPEN;
6445 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6446 (unsigned int)wire_open_mode ));
6447 return NT_STATUS_INVALID_PARAMETER;
6450 raw_unixmode = IVAL(pdata,8);
6451 /* Next 4 bytes are not yet defined. */
6453 status = unix_perms_from_wire(conn,
6456 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6459 if (!NT_STATUS_IS_OK(status)) {
6463 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6465 if (wire_open_mode & SMB_O_SYNC) {
6466 create_options |= FILE_WRITE_THROUGH;
6468 if (wire_open_mode & SMB_O_APPEND) {
6469 access_mask |= FILE_APPEND_DATA;
6471 if (wire_open_mode & SMB_O_DIRECT) {
6472 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6475 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6477 (unsigned int)wire_open_mode,
6478 (unsigned int)unixmode ));
6480 status = SMB_VFS_CREATE_FILE(
6483 0, /* root_dir_fid */
6485 0, /* create_file_flags */
6486 access_mask, /* access_mask */
6487 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6489 create_disp, /* create_disposition*/
6490 FILE_NON_DIRECTORY_FILE, /* create_options */
6491 mod_unixmode, /* file_attributes */
6492 oplock_request, /* oplock_request */
6493 0, /* allocation_size */
6500 if (!NT_STATUS_IS_OK(status)) {
6504 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6505 extended_oplock_granted = True;
6508 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6509 extended_oplock_granted = True;
6512 info_level_return = SVAL(pdata,16);
6514 /* Allocate the correct return size. */
6516 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6517 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6518 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6519 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6521 *pdata_return_size = 12;
6524 /* Realloc the data size */
6525 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6526 if (*ppdata == NULL) {
6527 close_file(req, fsp, ERROR_CLOSE);
6528 *pdata_return_size = 0;
6529 return NT_STATUS_NO_MEMORY;
6533 if (extended_oplock_granted) {
6534 if (flags & REQUEST_BATCH_OPLOCK) {
6535 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6537 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6539 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6540 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6542 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6545 SSVAL(pdata,2,fsp->fnum);
6546 SIVAL(pdata,4,info); /* Was file created etc. */
6548 switch (info_level_return) {
6549 case SMB_QUERY_FILE_UNIX_BASIC:
6550 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6551 SSVAL(pdata,10,0); /* padding. */
6552 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6554 case SMB_QUERY_FILE_UNIX_INFO2:
6555 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6556 SSVAL(pdata,10,0); /* padding. */
6557 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6560 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6561 SSVAL(pdata,10,0); /* padding. */
6564 return NT_STATUS_OK;
6567 /****************************************************************************
6568 Delete a file with POSIX semantics.
6569 ****************************************************************************/
6571 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6572 struct smb_request *req,
6576 SMB_STRUCT_STAT *psbuf)
6578 NTSTATUS status = NT_STATUS_OK;
6579 files_struct *fsp = NULL;
6583 int create_options = 0;
6585 struct share_mode_lock *lck = NULL;
6587 if (total_data < 2) {
6588 return NT_STATUS_INVALID_PARAMETER;
6591 flags = SVAL(pdata,0);
6593 if (!VALID_STAT(*psbuf)) {
6594 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6597 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6598 !VALID_STAT_OF_DIR(*psbuf)) {
6599 return NT_STATUS_NOT_A_DIRECTORY;
6602 DEBUG(10,("smb_posix_unlink: %s %s\n",
6603 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6606 if (VALID_STAT_OF_DIR(*psbuf)) {
6607 create_options |= FILE_DIRECTORY_FILE;
6610 status = SMB_VFS_CREATE_FILE(
6613 0, /* root_dir_fid */
6615 0, /* create_file_flags */
6616 DELETE_ACCESS, /* access_mask */
6617 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6619 FILE_OPEN, /* create_disposition*/
6620 create_options, /* create_options */
6621 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6622 0, /* oplock_request */
6623 0, /* allocation_size */
6630 if (!NT_STATUS_IS_OK(status)) {
6635 * Don't lie to client. If we can't really delete due to
6636 * non-POSIX opens return SHARING_VIOLATION.
6639 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6642 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6643 "lock for file %s\n", fsp->fsp_name));
6644 close_file(req, fsp, NORMAL_CLOSE);
6645 return NT_STATUS_INVALID_PARAMETER;
6649 * See if others still have the file open. If this is the case, then
6650 * don't delete. If all opens are POSIX delete we can set the delete
6651 * on close disposition.
6653 for (i=0; i<lck->num_share_modes; i++) {
6654 struct share_mode_entry *e = &lck->share_modes[i];
6655 if (is_valid_share_mode_entry(e)) {
6656 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6659 /* Fail with sharing violation. */
6660 close_file(req, fsp, NORMAL_CLOSE);
6662 return NT_STATUS_SHARING_VIOLATION;
6667 * Set the delete on close.
6669 status = smb_set_file_disposition_info(conn,
6676 if (!NT_STATUS_IS_OK(status)) {
6677 close_file(req, fsp, NORMAL_CLOSE);
6682 return close_file(req, fsp, NORMAL_CLOSE);
6685 /****************************************************************************
6686 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6687 ****************************************************************************/
6689 static void call_trans2setfilepathinfo(connection_struct *conn,
6690 struct smb_request *req,
6691 unsigned int tran_call,
6692 char **pparams, int total_params,
6693 char **ppdata, int total_data,
6694 unsigned int max_data_bytes)
6696 char *params = *pparams;
6697 char *pdata = *ppdata;
6699 SMB_STRUCT_STAT sbuf;
6701 files_struct *fsp = NULL;
6702 NTSTATUS status = NT_STATUS_OK;
6703 int data_return_size = 0;
6704 TALLOC_CTX *ctx = talloc_tos();
6707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6713 if (tran_call == TRANSACT2_SETFILEINFO) {
6714 if (total_params < 4) {
6715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6719 fsp = file_fsp(req, SVAL(params,0));
6720 /* Basic check for non-null fsp. */
6721 if (!check_fsp_open(conn, req, fsp)) {
6724 info_level = SVAL(params,2);
6726 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6728 reply_nterror(req, NT_STATUS_NO_MEMORY);
6732 if(fsp->is_directory || fsp->fh->fd == -1) {
6734 * This is actually a SETFILEINFO on a directory
6735 * handle (returned from an NT SMB). NT5.0 seems
6736 * to do this call. JRA.
6738 if (INFO_LEVEL_IS_UNIX(info_level)) {
6739 /* Always do lstat for UNIX calls. */
6740 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6741 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6742 reply_unixerror(req,ERRDOS,ERRbadpath);
6746 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6747 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6748 reply_unixerror(req,ERRDOS,ERRbadpath);
6752 } else if (fsp->print_file) {
6754 * Doing a DELETE_ON_CLOSE should cancel a print job.
6756 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6757 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6759 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6762 send_trans2_replies(conn, req, params, 2,
6767 reply_unixerror(req, ERRDOS, ERRbadpath);
6772 * Original code - this is an open file.
6774 if (!check_fsp(conn, req, fsp)) {
6778 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6779 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6780 reply_unixerror(req, ERRDOS, ERRbadfid);
6786 if (total_params < 7) {
6787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6791 info_level = SVAL(params,0);
6792 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6793 total_params - 6, STR_TERMINATE,
6795 if (!NT_STATUS_IS_OK(status)) {
6796 reply_nterror(req, status);
6800 status = resolve_dfspath(ctx, conn,
6801 req->flags2 & FLAGS2_DFS_PATHNAMES,
6804 if (!NT_STATUS_IS_OK(status)) {
6805 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6806 reply_botherror(req,
6807 NT_STATUS_PATH_NOT_COVERED,
6808 ERRSRV, ERRbadpath);
6811 reply_nterror(req, status);
6815 status = unix_convert(ctx, conn, fname, False,
6816 &fname, NULL, &sbuf);
6817 if (!NT_STATUS_IS_OK(status)) {
6818 reply_nterror(req, status);
6822 status = check_name(conn, fname);
6823 if (!NT_STATUS_IS_OK(status)) {
6824 reply_nterror(req, status);
6828 if (INFO_LEVEL_IS_UNIX(info_level)) {
6830 * For CIFS UNIX extensions the target name may not exist.
6833 /* Always do lstat for UNIX calls. */
6834 SMB_VFS_LSTAT(conn,fname,&sbuf);
6836 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6837 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6838 reply_unixerror(req, ERRDOS, ERRbadpath);
6843 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6844 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6848 if (!CAN_WRITE(conn)) {
6849 /* Allow POSIX opens. The open path will deny
6850 * any non-readonly opens. */
6851 if (info_level != SMB_POSIX_PATH_OPEN) {
6852 reply_doserror(req, ERRSRV, ERRaccess);
6857 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6858 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6860 /* Realloc the parameter size */
6861 *pparams = (char *)SMB_REALLOC(*pparams,2);
6862 if (*pparams == NULL) {
6863 reply_nterror(req, NT_STATUS_NO_MEMORY);
6870 switch (info_level) {
6872 case SMB_INFO_STANDARD:
6874 status = smb_set_info_standard(conn,
6883 case SMB_INFO_SET_EA:
6885 status = smb_info_set_ea(conn,
6893 case SMB_SET_FILE_BASIC_INFO:
6894 case SMB_FILE_BASIC_INFORMATION:
6896 status = smb_set_file_basic_info(conn,
6905 case SMB_FILE_ALLOCATION_INFORMATION:
6906 case SMB_SET_FILE_ALLOCATION_INFO:
6908 status = smb_set_file_allocation_info(conn, req,
6917 case SMB_FILE_END_OF_FILE_INFORMATION:
6918 case SMB_SET_FILE_END_OF_FILE_INFO:
6920 status = smb_set_file_end_of_file_info(conn, req,
6929 case SMB_FILE_DISPOSITION_INFORMATION:
6930 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6933 /* JRA - We used to just ignore this on a path ?
6934 * Shouldn't this be invalid level on a pathname
6937 if (tran_call != TRANSACT2_SETFILEINFO) {
6938 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6941 status = smb_set_file_disposition_info(conn,
6950 case SMB_FILE_POSITION_INFORMATION:
6952 status = smb_file_position_information(conn,
6959 /* From tridge Samba4 :
6960 * MODE_INFORMATION in setfileinfo (I have no
6961 * idea what "mode information" on a file is - it takes a value of 0,
6962 * 2, 4 or 6. What could it be?).
6965 case SMB_FILE_MODE_INFORMATION:
6967 status = smb_file_mode_information(conn,
6974 * CIFS UNIX extensions.
6977 case SMB_SET_FILE_UNIX_BASIC:
6979 status = smb_set_file_unix_basic(conn, req,
6988 case SMB_SET_FILE_UNIX_INFO2:
6990 status = smb_set_file_unix_info2(conn, req,
6999 case SMB_SET_FILE_UNIX_LINK:
7001 if (tran_call != TRANSACT2_SETPATHINFO) {
7002 /* We must have a pathname for this. */
7003 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7006 status = smb_set_file_unix_link(conn, req, pdata,
7011 case SMB_SET_FILE_UNIX_HLINK:
7013 if (tran_call != TRANSACT2_SETPATHINFO) {
7014 /* We must have a pathname for this. */
7015 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7018 status = smb_set_file_unix_hlink(conn, req,
7024 case SMB_FILE_RENAME_INFORMATION:
7026 status = smb_file_rename_information(conn, req,
7032 #if defined(HAVE_POSIX_ACLS)
7033 case SMB_SET_POSIX_ACL:
7035 status = smb_set_posix_acl(conn,
7045 case SMB_SET_POSIX_LOCK:
7047 if (tran_call != TRANSACT2_SETFILEINFO) {
7048 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7051 status = smb_set_posix_lock(conn, req,
7052 pdata, total_data, fsp);
7056 case SMB_POSIX_PATH_OPEN:
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_open(conn, req,
7073 case SMB_POSIX_PATH_UNLINK:
7075 if (tran_call != TRANSACT2_SETPATHINFO) {
7076 /* We must have a pathname for this. */
7077 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7081 status = smb_posix_unlink(conn, req,
7090 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7095 if (!NT_STATUS_IS_OK(status)) {
7096 if (open_was_deferred(req->mid)) {
7097 /* We have re-scheduled this call. */
7100 if (blocking_lock_was_deferred(req->mid)) {
7101 /* We have re-scheduled this call. */
7104 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7105 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7106 ERRSRV, ERRbadpath);
7109 if (info_level == SMB_POSIX_PATH_OPEN) {
7110 reply_openerror(req, status);
7114 reply_nterror(req, status);
7119 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7125 /****************************************************************************
7126 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7127 ****************************************************************************/
7129 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7130 char **pparams, int total_params,
7131 char **ppdata, int total_data,
7132 unsigned int max_data_bytes)
7134 char *params = *pparams;
7135 char *pdata = *ppdata;
7136 char *directory = NULL;
7137 SMB_STRUCT_STAT sbuf;
7138 NTSTATUS status = NT_STATUS_OK;
7139 struct ea_list *ea_list = NULL;
7140 TALLOC_CTX *ctx = talloc_tos();
7142 if (!CAN_WRITE(conn)) {
7143 reply_doserror(req, ERRSRV, ERRaccess);
7147 if (total_params < 5) {
7148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7152 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7153 total_params - 4, STR_TERMINATE,
7155 if (!NT_STATUS_IS_OK(status)) {
7156 reply_nterror(req, status);
7160 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7162 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7163 if (!NT_STATUS_IS_OK(status)) {
7164 reply_nterror(req, status);
7168 status = check_name(conn, directory);
7169 if (!NT_STATUS_IS_OK(status)) {
7170 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7171 reply_nterror(req, status);
7175 /* Any data in this call is an EA list. */
7176 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7177 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7182 * OS/2 workplace shell seems to send SET_EA requests of "null"
7183 * length (4 bytes containing IVAL 4).
7184 * They seem to have no effect. Bug #3212. JRA.
7187 if (total_data != 4) {
7188 if (total_data < 10) {
7189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7193 if (IVAL(pdata,0) > total_data) {
7194 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7195 IVAL(pdata,0), (unsigned int)total_data));
7196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7200 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7207 /* If total_data == 4 Windows doesn't care what values
7208 * are placed in that field, it just ignores them.
7209 * The System i QNTC IBM SMB client puts bad values here,
7210 * so ignore them. */
7212 status = create_directory(conn, req, directory);
7214 if (!NT_STATUS_IS_OK(status)) {
7215 reply_nterror(req, status);
7219 /* Try and set any given EA. */
7221 status = set_ea(conn, NULL, directory, ea_list);
7222 if (!NT_STATUS_IS_OK(status)) {
7223 reply_nterror(req, status);
7228 /* Realloc the parameter and data sizes */
7229 *pparams = (char *)SMB_REALLOC(*pparams,2);
7230 if(*pparams == NULL) {
7231 reply_nterror(req, NT_STATUS_NO_MEMORY);
7238 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7243 /****************************************************************************
7244 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7245 We don't actually do this - we just send a null response.
7246 ****************************************************************************/
7248 static void call_trans2findnotifyfirst(connection_struct *conn,
7249 struct smb_request *req,
7250 char **pparams, int total_params,
7251 char **ppdata, int total_data,
7252 unsigned int max_data_bytes)
7254 char *params = *pparams;
7257 if (total_params < 6) {
7258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7262 info_level = SVAL(params,4);
7263 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7265 switch (info_level) {
7270 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7274 /* Realloc the parameter and data sizes */
7275 *pparams = (char *)SMB_REALLOC(*pparams,6);
7276 if (*pparams == NULL) {
7277 reply_nterror(req, NT_STATUS_NO_MEMORY);
7282 SSVAL(params,0,fnf_handle);
7283 SSVAL(params,2,0); /* No changes */
7284 SSVAL(params,4,0); /* No EA errors */
7291 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7296 /****************************************************************************
7297 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7298 changes). Currently this does nothing.
7299 ****************************************************************************/
7301 static void call_trans2findnotifynext(connection_struct *conn,
7302 struct smb_request *req,
7303 char **pparams, int total_params,
7304 char **ppdata, int total_data,
7305 unsigned int max_data_bytes)
7307 char *params = *pparams;
7309 DEBUG(3,("call_trans2findnotifynext\n"));
7311 /* Realloc the parameter and data sizes */
7312 *pparams = (char *)SMB_REALLOC(*pparams,4);
7313 if (*pparams == NULL) {
7314 reply_nterror(req, NT_STATUS_NO_MEMORY);
7319 SSVAL(params,0,0); /* No changes */
7320 SSVAL(params,2,0); /* No EA errors */
7322 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7327 /****************************************************************************
7328 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7329 ****************************************************************************/
7331 static void call_trans2getdfsreferral(connection_struct *conn,
7332 struct smb_request *req,
7333 char **pparams, int total_params,
7334 char **ppdata, int total_data,
7335 unsigned int max_data_bytes)
7337 char *params = *pparams;
7338 char *pathname = NULL;
7340 int max_referral_level;
7341 NTSTATUS status = NT_STATUS_OK;
7342 TALLOC_CTX *ctx = talloc_tos();
7344 DEBUG(10,("call_trans2getdfsreferral\n"));
7346 if (total_params < 3) {
7347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7351 max_referral_level = SVAL(params,0);
7353 if(!lp_host_msdfs()) {
7354 reply_doserror(req, ERRDOS, ERRbadfunc);
7358 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7359 total_params - 2, STR_TERMINATE);
7361 reply_nterror(req, NT_STATUS_NOT_FOUND);
7364 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7365 ppdata,&status)) < 0) {
7366 reply_nterror(req, status);
7370 SSVAL(req->inbuf, smb_flg2,
7371 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7372 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7377 #define LMCAT_SPL 0x53
7378 #define LMFUNC_GETJOBID 0x60
7380 /****************************************************************************
7381 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7382 ****************************************************************************/
7384 static void call_trans2ioctl(connection_struct *conn,
7385 struct smb_request *req,
7386 char **pparams, int total_params,
7387 char **ppdata, int total_data,
7388 unsigned int max_data_bytes)
7390 char *pdata = *ppdata;
7391 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7393 /* check for an invalid fid before proceeding */
7396 reply_doserror(req, ERRDOS, ERRbadfid);
7400 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7401 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7402 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7403 if (*ppdata == NULL) {
7404 reply_nterror(req, NT_STATUS_NO_MEMORY);
7409 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7410 CAN ACCEPT THIS IN UNICODE. JRA. */
7412 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7413 srvstr_push(pdata, req->flags2, pdata + 2,
7414 global_myname(), 15,
7415 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7416 srvstr_push(pdata, req->flags2, pdata+18,
7417 lp_servicename(SNUM(conn)), 13,
7418 STR_ASCII|STR_TERMINATE); /* Service name */
7419 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7424 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7425 reply_doserror(req, ERRSRV, ERRerror);
7428 /****************************************************************************
7429 Reply to a SMBfindclose (stop trans2 directory search).
7430 ****************************************************************************/
7432 void reply_findclose(struct smb_request *req)
7436 START_PROFILE(SMBfindclose);
7439 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7440 END_PROFILE(SMBfindclose);
7444 dptr_num = SVALS(req->vwv+0, 0);
7446 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7448 dptr_close(&dptr_num);
7450 reply_outbuf(req, 0, 0);
7452 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7454 END_PROFILE(SMBfindclose);
7458 /****************************************************************************
7459 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7460 ****************************************************************************/
7462 void reply_findnclose(struct smb_request *req)
7466 START_PROFILE(SMBfindnclose);
7469 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7470 END_PROFILE(SMBfindnclose);
7474 dptr_num = SVAL(req->vwv+0, 0);
7476 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7478 /* We never give out valid handles for a
7479 findnotifyfirst - so any dptr_num is ok here.
7482 reply_outbuf(req, 0, 0);
7484 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7486 END_PROFILE(SMBfindnclose);
7490 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7491 struct trans_state *state)
7493 if (Protocol >= PROTOCOL_NT1) {
7494 req->flags2 |= 0x40; /* IS_LONG_NAME */
7495 SSVAL(req->inbuf,smb_flg2,req->flags2);
7498 if (conn->encrypt_level == Required && !req->encrypted) {
7499 if (state->call != TRANSACT2_QFSINFO &&
7500 state->call != TRANSACT2_SETFSINFO) {
7501 DEBUG(0,("handle_trans2: encryption required "
7503 (unsigned int)state->call));
7504 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7509 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7511 /* Now we must call the relevant TRANS2 function */
7512 switch(state->call) {
7513 case TRANSACT2_OPEN:
7515 START_PROFILE(Trans2_open);
7516 call_trans2open(conn, req,
7517 &state->param, state->total_param,
7518 &state->data, state->total_data,
7519 state->max_data_return);
7520 END_PROFILE(Trans2_open);
7524 case TRANSACT2_FINDFIRST:
7526 START_PROFILE(Trans2_findfirst);
7527 call_trans2findfirst(conn, req,
7528 &state->param, state->total_param,
7529 &state->data, state->total_data,
7530 state->max_data_return);
7531 END_PROFILE(Trans2_findfirst);
7535 case TRANSACT2_FINDNEXT:
7537 START_PROFILE(Trans2_findnext);
7538 call_trans2findnext(conn, req,
7539 &state->param, state->total_param,
7540 &state->data, state->total_data,
7541 state->max_data_return);
7542 END_PROFILE(Trans2_findnext);
7546 case TRANSACT2_QFSINFO:
7548 START_PROFILE(Trans2_qfsinfo);
7549 call_trans2qfsinfo(conn, req,
7550 &state->param, state->total_param,
7551 &state->data, state->total_data,
7552 state->max_data_return);
7553 END_PROFILE(Trans2_qfsinfo);
7557 case TRANSACT2_SETFSINFO:
7559 START_PROFILE(Trans2_setfsinfo);
7560 call_trans2setfsinfo(conn, req,
7561 &state->param, state->total_param,
7562 &state->data, state->total_data,
7563 state->max_data_return);
7564 END_PROFILE(Trans2_setfsinfo);
7568 case TRANSACT2_QPATHINFO:
7569 case TRANSACT2_QFILEINFO:
7571 START_PROFILE(Trans2_qpathinfo);
7572 call_trans2qfilepathinfo(conn, req, state->call,
7573 &state->param, state->total_param,
7574 &state->data, state->total_data,
7575 state->max_data_return);
7576 END_PROFILE(Trans2_qpathinfo);
7580 case TRANSACT2_SETPATHINFO:
7581 case TRANSACT2_SETFILEINFO:
7583 START_PROFILE(Trans2_setpathinfo);
7584 call_trans2setfilepathinfo(conn, req, state->call,
7585 &state->param, state->total_param,
7586 &state->data, state->total_data,
7587 state->max_data_return);
7588 END_PROFILE(Trans2_setpathinfo);
7592 case TRANSACT2_FINDNOTIFYFIRST:
7594 START_PROFILE(Trans2_findnotifyfirst);
7595 call_trans2findnotifyfirst(conn, req,
7596 &state->param, state->total_param,
7597 &state->data, state->total_data,
7598 state->max_data_return);
7599 END_PROFILE(Trans2_findnotifyfirst);
7603 case TRANSACT2_FINDNOTIFYNEXT:
7605 START_PROFILE(Trans2_findnotifynext);
7606 call_trans2findnotifynext(conn, req,
7607 &state->param, state->total_param,
7608 &state->data, state->total_data,
7609 state->max_data_return);
7610 END_PROFILE(Trans2_findnotifynext);
7614 case TRANSACT2_MKDIR:
7616 START_PROFILE(Trans2_mkdir);
7617 call_trans2mkdir(conn, req,
7618 &state->param, state->total_param,
7619 &state->data, state->total_data,
7620 state->max_data_return);
7621 END_PROFILE(Trans2_mkdir);
7625 case TRANSACT2_GET_DFS_REFERRAL:
7627 START_PROFILE(Trans2_get_dfs_referral);
7628 call_trans2getdfsreferral(conn, req,
7629 &state->param, state->total_param,
7630 &state->data, state->total_data,
7631 state->max_data_return);
7632 END_PROFILE(Trans2_get_dfs_referral);
7636 case TRANSACT2_IOCTL:
7638 START_PROFILE(Trans2_ioctl);
7639 call_trans2ioctl(conn, req,
7640 &state->param, state->total_param,
7641 &state->data, state->total_data,
7642 state->max_data_return);
7643 END_PROFILE(Trans2_ioctl);
7648 /* Error in request */
7649 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7650 reply_doserror(req, ERRSRV,ERRerror);
7654 /****************************************************************************
7655 Reply to a SMBtrans2.
7656 ****************************************************************************/
7658 void reply_trans2(struct smb_request *req)
7660 connection_struct *conn = req->conn;
7665 unsigned int tran_call;
7666 struct trans_state *state;
7669 START_PROFILE(SMBtrans2);
7671 if (req->wct < 14) {
7672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7673 END_PROFILE(SMBtrans2);
7677 dsoff = SVAL(req->vwv+12, 0);
7678 dscnt = SVAL(req->vwv+11, 0);
7679 psoff = SVAL(req->vwv+10, 0);
7680 pscnt = SVAL(req->vwv+9, 0);
7681 tran_call = SVAL(req->vwv+14, 0);
7683 result = allow_new_trans(conn->pending_trans, req->mid);
7684 if (!NT_STATUS_IS_OK(result)) {
7685 DEBUG(2, ("Got invalid trans2 request: %s\n",
7686 nt_errstr(result)));
7687 reply_nterror(req, result);
7688 END_PROFILE(SMBtrans2);
7693 switch (tran_call) {
7694 /* List the allowed trans2 calls on IPC$ */
7695 case TRANSACT2_OPEN:
7696 case TRANSACT2_GET_DFS_REFERRAL:
7697 case TRANSACT2_QFILEINFO:
7698 case TRANSACT2_QFSINFO:
7699 case TRANSACT2_SETFSINFO:
7702 reply_doserror(req, ERRSRV, ERRaccess);
7703 END_PROFILE(SMBtrans2);
7708 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7709 DEBUG(0, ("talloc failed\n"));
7710 reply_nterror(req, NT_STATUS_NO_MEMORY);
7711 END_PROFILE(SMBtrans2);
7715 state->cmd = SMBtrans2;
7717 state->mid = req->mid;
7718 state->vuid = req->vuid;
7719 state->setup_count = SVAL(req->vwv+13, 0);
7720 state->setup = NULL;
7721 state->total_param = SVAL(req->vwv+0, 0);
7722 state->param = NULL;
7723 state->total_data = SVAL(req->vwv+1, 0);
7725 state->max_param_return = SVAL(req->vwv+2, 0);
7726 state->max_data_return = SVAL(req->vwv+3, 0);
7727 state->max_setup_return = SVAL(req->vwv+4, 0);
7728 state->close_on_completion = BITSETW(req->vwv+5, 0);
7729 state->one_way = BITSETW(req->vwv+5, 1);
7731 state->call = tran_call;
7733 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7734 is so as a sanity check */
7735 if (state->setup_count != 1) {
7737 * Need to have rc=0 for ioctl to get job id for OS/2.
7738 * Network printing will fail if function is not successful.
7739 * Similar function in reply.c will be used if protocol
7740 * is LANMAN1.0 instead of LM1.2X002.
7741 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7742 * outbuf doesn't have to be set(only job id is used).
7744 if ( (state->setup_count == 4)
7745 && (tran_call == TRANSACT2_IOCTL)
7746 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7747 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7748 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7750 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7751 DEBUG(2,("Transaction is %d\n",tran_call));
7753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7754 END_PROFILE(SMBtrans2);
7759 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7762 if (state->total_data) {
7764 if (trans_oob(state->total_data, 0, dscnt)
7765 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7769 /* Can't use talloc here, the core routines do realloc on the
7770 * params and data. */
7771 state->data = (char *)SMB_MALLOC(state->total_data);
7772 if (state->data == NULL) {
7773 DEBUG(0,("reply_trans2: data malloc fail for %u "
7774 "bytes !\n", (unsigned int)state->total_data));
7776 reply_nterror(req, NT_STATUS_NO_MEMORY);
7777 END_PROFILE(SMBtrans2);
7781 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7784 if (state->total_param) {
7786 if (trans_oob(state->total_param, 0, pscnt)
7787 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7791 /* Can't use talloc here, the core routines do realloc on the
7792 * params and data. */
7793 state->param = (char *)SMB_MALLOC(state->total_param);
7794 if (state->param == NULL) {
7795 DEBUG(0,("reply_trans: param malloc fail for %u "
7796 "bytes !\n", (unsigned int)state->total_param));
7797 SAFE_FREE(state->data);
7799 reply_nterror(req, NT_STATUS_NO_MEMORY);
7800 END_PROFILE(SMBtrans2);
7804 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7807 state->received_data = dscnt;
7808 state->received_param = pscnt;
7810 if ((state->received_param == state->total_param) &&
7811 (state->received_data == state->total_data)) {
7813 handle_trans2(conn, req, state);
7815 SAFE_FREE(state->data);
7816 SAFE_FREE(state->param);
7818 END_PROFILE(SMBtrans2);
7822 DLIST_ADD(conn->pending_trans, state);
7824 /* We need to send an interim response then receive the rest
7825 of the parameter/data bytes */
7826 reply_outbuf(req, 0, 0);
7827 show_msg((char *)req->outbuf);
7828 END_PROFILE(SMBtrans2);
7833 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7834 SAFE_FREE(state->data);
7835 SAFE_FREE(state->param);
7837 END_PROFILE(SMBtrans2);
7838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7842 /****************************************************************************
7843 Reply to a SMBtranss2
7844 ****************************************************************************/
7846 void reply_transs2(struct smb_request *req)
7848 connection_struct *conn = req->conn;
7849 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7850 struct trans_state *state;
7852 START_PROFILE(SMBtranss2);
7854 show_msg((char *)req->inbuf);
7857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7858 END_PROFILE(SMBtranss2);
7862 for (state = conn->pending_trans; state != NULL;
7863 state = state->next) {
7864 if (state->mid == req->mid) {
7869 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7871 END_PROFILE(SMBtranss2);
7875 /* Revise state->total_param and state->total_data in case they have
7876 changed downwards */
7878 if (SVAL(req->vwv+0, 0) < state->total_param)
7879 state->total_param = SVAL(req->vwv+0, 0);
7880 if (SVAL(req->vwv+1, 0) < state->total_data)
7881 state->total_data = SVAL(req->vwv+1, 0);
7883 pcnt = SVAL(req->vwv+2, 0);
7884 poff = SVAL(req->vwv+3, 0);
7885 pdisp = SVAL(req->vwv+4, 0);
7887 dcnt = SVAL(req->vwv+5, 0);
7888 doff = SVAL(req->vwv+6, 0);
7889 ddisp = SVAL(req->vwv+7, 0);
7891 state->received_param += pcnt;
7892 state->received_data += dcnt;
7894 if ((state->received_data > state->total_data) ||
7895 (state->received_param > state->total_param))
7899 if (trans_oob(state->total_param, pdisp, pcnt)
7900 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7903 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7907 if (trans_oob(state->total_data, ddisp, dcnt)
7908 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7911 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7914 if ((state->received_param < state->total_param) ||
7915 (state->received_data < state->total_data)) {
7916 END_PROFILE(SMBtranss2);
7920 handle_trans2(conn, req, state);
7922 DLIST_REMOVE(conn->pending_trans, state);
7923 SAFE_FREE(state->data);
7924 SAFE_FREE(state->param);
7927 END_PROFILE(SMBtranss2);
7932 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7933 DLIST_REMOVE(conn->pending_trans, state);
7934 SAFE_FREE(state->data);
7935 SAFE_FREE(state->param);
7937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7938 END_PROFILE(SMBtranss2);