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"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
247 *pnum_names = num_names;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list *ea_list_head = NULL;
266 if (!lp_ea_support(SNUM(conn))) {
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
285 listp = TALLOC_P(mem_ctx, struct ea_list);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
346 if (ea_list->ea.value.length > 65535) {
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
372 size_t total_ea_len = 0;
373 TALLOC_CTX *mem_ctx = NULL;
375 if (!lp_ea_support(SNUM(conn))) {
378 mem_ctx = talloc_tos();
379 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
383 /****************************************************************************
384 Ensure the EA name is case insensitive by matching any existing EA name.
385 ****************************************************************************/
387 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
390 TALLOC_CTX *mem_ctx = talloc_tos();
391 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
393 for (; ea_list; ea_list = ea_list->next) {
394 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
395 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
396 &unix_ea_name[5], ea_list->ea.name));
397 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
403 /****************************************************************************
404 Set or delete an extended attribute.
405 ****************************************************************************/
407 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
409 if (!lp_ea_support(SNUM(conn))) {
410 return NT_STATUS_EAS_NOT_SUPPORTED;
413 for (;ea_list; ea_list = ea_list->next) {
415 fstring unix_ea_name;
417 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
418 fstrcat(unix_ea_name, ea_list->ea.name);
420 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
422 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
424 if (samba_private_attr_name(unix_ea_name)) {
425 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
426 return NT_STATUS_ACCESS_DENIED;
429 if (ea_list->ea.value.length == 0) {
430 /* Remove the attribute. */
431 if (fsp && (fsp->fh->fd != -1)) {
432 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
433 unix_ea_name, fsp->fsp_name));
434 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
436 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
437 unix_ea_name, fname));
438 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
441 /* Removing a non existent attribute always succeeds. */
442 if (ret == -1 && errno == ENOATTR) {
443 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
449 if (fsp && (fsp->fh->fd != -1)) {
450 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
451 unix_ea_name, fsp->fsp_name));
452 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
453 ea_list->ea.value.data, ea_list->ea.value.length, 0);
455 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
456 unix_ea_name, fname));
457 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
458 ea_list->ea.value.data, ea_list->ea.value.length, 0);
464 if (errno == ENOTSUP) {
465 return NT_STATUS_EAS_NOT_SUPPORTED;
468 return map_nt_error_from_unix(errno);
474 /****************************************************************************
475 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
476 ****************************************************************************/
478 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
480 struct ea_list *ea_list_head = NULL;
481 size_t converted_size, offset = 0;
483 while (offset + 2 < data_size) {
484 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
485 unsigned int namelen = CVAL(pdata,offset);
487 offset++; /* Go past the namelen byte. */
489 /* integer wrap paranioa. */
490 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
491 (offset > data_size) || (namelen > data_size) ||
492 (offset + namelen >= data_size)) {
495 /* Ensure the name is null terminated. */
496 if (pdata[offset + namelen] != '\0') {
499 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
501 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
502 "failed: %s", strerror(errno)));
508 offset += (namelen + 1); /* Go past the name + terminating zero. */
509 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
510 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
516 /****************************************************************************
517 Read one EA list entry from the buffer.
518 ****************************************************************************/
520 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
522 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
524 unsigned int namelen;
525 size_t converted_size;
535 eal->ea.flags = CVAL(pdata,0);
536 namelen = CVAL(pdata,1);
537 val_len = SVAL(pdata,2);
539 if (4 + namelen + 1 + val_len > data_size) {
543 /* Ensure the name is null terminated. */
544 if (pdata[namelen + 4] != '\0') {
547 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
548 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
555 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
556 if (!eal->ea.value.data) {
560 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
562 /* Ensure we're null terminated just in case we print the value. */
563 eal->ea.value.data[val_len] = '\0';
564 /* But don't count the null. */
565 eal->ea.value.length--;
568 *pbytes_used = 4 + namelen + 1 + val_len;
571 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
572 dump_data(10, eal->ea.value.data, eal->ea.value.length);
577 /****************************************************************************
578 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
579 ****************************************************************************/
581 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
583 struct ea_list *ea_list_head = NULL;
585 size_t bytes_used = 0;
587 while (offset < data_size) {
588 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
594 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
595 offset += bytes_used;
601 /****************************************************************************
602 Count the total EA size needed.
603 ****************************************************************************/
605 static size_t ea_list_size(struct ea_list *ealist)
608 struct ea_list *listp;
611 for (listp = ealist; listp; listp = listp->next) {
612 push_ascii_fstring(dos_ea_name, listp->ea.name);
613 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
615 /* Add on 4 for total length. */
623 /****************************************************************************
624 Return a union of EA's from a file list and a list of names.
625 The TALLOC context for the two lists *MUST* be identical as we steal
626 memory from one list to add to another. JRA.
627 ****************************************************************************/
629 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
631 struct ea_list *nlistp, *flistp;
633 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
634 for (flistp = file_list; flistp; flistp = flistp->next) {
635 if (strequal(nlistp->ea.name, flistp->ea.name)) {
641 /* Copy the data from this entry. */
642 nlistp->ea.flags = flistp->ea.flags;
643 nlistp->ea.value = flistp->ea.value;
646 nlistp->ea.flags = 0;
647 ZERO_STRUCT(nlistp->ea.value);
651 *total_ea_len = ea_list_size(name_list);
655 /****************************************************************************
656 Send the required number of replies back.
657 We assume all fields other than the data fields are
658 set correctly for the type of call.
659 HACK ! Always assumes smb_setup field is zero.
660 ****************************************************************************/
662 void send_trans2_replies(connection_struct *conn,
663 struct smb_request *req,
670 /* As we are using a protocol > LANMAN1 then the max_send
671 variable must have been set in the sessetupX call.
672 This takes precedence over the max_xmit field in the
673 global struct. These different max_xmit variables should
674 be merged as this is now too confusing */
676 int data_to_send = datasize;
677 int params_to_send = paramsize;
679 const char *pp = params;
680 const char *pd = pdata;
681 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
682 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
683 int data_alignment_offset = 0;
684 bool overflow = False;
686 /* Modify the data_to_send and datasize and set the error if
687 we're trying to send more than max_data_bytes. We still send
688 the part of the packet(s) that fit. Strange, but needed
691 if (max_data_bytes > 0 && datasize > max_data_bytes) {
692 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
693 max_data_bytes, datasize ));
694 datasize = data_to_send = max_data_bytes;
698 /* If there genuinely are no parameters or data to send just send the empty packet */
700 if(params_to_send == 0 && data_to_send == 0) {
701 reply_outbuf(req, 10, 0);
702 show_msg((char *)req->outbuf);
706 /* When sending params and data ensure that both are nicely aligned */
707 /* Only do this alignment when there is also data to send - else
708 can cause NT redirector problems. */
710 if (((params_to_send % 4) != 0) && (data_to_send != 0))
711 data_alignment_offset = 4 - (params_to_send % 4);
713 /* Space is bufsize minus Netbios over TCP header minus SMB header */
714 /* The alignment_offset is to align the param bytes on an even byte
715 boundary. NT 4.0 Beta needs this to work correctly. */
717 useable_space = max_send - (smb_size
720 + data_alignment_offset);
722 if (useable_space < 0) {
723 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
724 "= %d!!!", useable_space));
725 exit_server_cleanly("send_trans2_replies: Not enough space");
728 while (params_to_send || data_to_send) {
729 /* Calculate whether we will totally or partially fill this packet */
731 total_sent_thistime = params_to_send + data_to_send;
733 /* We can never send more than useable_space */
735 * Note that 'useable_space' does not include the alignment offsets,
736 * but we must include the alignment offsets in the calculation of
737 * the length of the data we send over the wire, as the alignment offsets
738 * are sent here. Fix from Marc_Jacobsen@hp.com.
741 total_sent_thistime = MIN(total_sent_thistime, useable_space);
743 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
744 + data_alignment_offset);
747 * We might have SMBtrans2s in req which was transferred to
748 * the outbuf, fix that.
750 SCVAL(req->outbuf, smb_com, SMBtrans2);
752 /* Set total params and data to be sent */
753 SSVAL(req->outbuf,smb_tprcnt,paramsize);
754 SSVAL(req->outbuf,smb_tdrcnt,datasize);
756 /* Calculate how many parameters and data we can fit into
757 * this packet. Parameters get precedence
760 params_sent_thistime = MIN(params_to_send,useable_space);
761 data_sent_thistime = useable_space - params_sent_thistime;
762 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
764 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
766 /* smb_proff is the offset from the start of the SMB header to the
767 parameter bytes, however the first 4 bytes of outbuf are
768 the Netbios over TCP header. Thus use smb_base() to subtract
769 them from the calculation */
771 SSVAL(req->outbuf,smb_proff,
772 ((smb_buf(req->outbuf)+alignment_offset)
773 - smb_base(req->outbuf)));
775 if(params_sent_thistime == 0)
776 SSVAL(req->outbuf,smb_prdisp,0);
778 /* Absolute displacement of param bytes sent in this packet */
779 SSVAL(req->outbuf,smb_prdisp,pp - params);
781 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
782 if(data_sent_thistime == 0) {
783 SSVAL(req->outbuf,smb_droff,0);
784 SSVAL(req->outbuf,smb_drdisp, 0);
786 /* The offset of the data bytes is the offset of the
787 parameter bytes plus the number of parameters being sent this time */
788 SSVAL(req->outbuf, smb_droff,
789 ((smb_buf(req->outbuf)+alignment_offset)
790 - smb_base(req->outbuf))
791 + params_sent_thistime + data_alignment_offset);
792 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
795 /* Initialize the padding for alignment */
797 if (alignment_offset != 0) {
798 memset(smb_buf(req->outbuf), 0, alignment_offset);
801 /* Copy the param bytes into the packet */
803 if(params_sent_thistime) {
804 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
805 params_sent_thistime);
808 /* Copy in the data bytes */
809 if(data_sent_thistime) {
810 if (data_alignment_offset != 0) {
811 memset((smb_buf(req->outbuf)+alignment_offset+
812 params_sent_thistime), 0,
813 data_alignment_offset);
815 memcpy(smb_buf(req->outbuf)+alignment_offset
816 +params_sent_thistime+data_alignment_offset,
817 pd,data_sent_thistime);
820 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
821 params_sent_thistime, data_sent_thistime, useable_space));
822 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
823 params_to_send, data_to_send, paramsize, datasize));
826 error_packet_set((char *)req->outbuf,
827 ERRDOS,ERRbufferoverflow,
828 STATUS_BUFFER_OVERFLOW,
832 /* Send the packet */
833 show_msg((char *)req->outbuf);
834 if (!srv_send_smb(smbd_server_fd(),
837 IS_CONN_ENCRYPTED(conn),
839 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
841 TALLOC_FREE(req->outbuf);
843 pp += params_sent_thistime;
844 pd += data_sent_thistime;
846 params_to_send -= params_sent_thistime;
847 data_to_send -= data_sent_thistime;
850 if(params_to_send < 0 || data_to_send < 0) {
851 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
852 params_to_send, data_to_send));
860 /****************************************************************************
861 Reply to a TRANSACT2_OPEN.
862 ****************************************************************************/
864 static void call_trans2open(connection_struct *conn,
865 struct smb_request *req,
866 char **pparams, int total_params,
867 char **ppdata, int total_data,
868 unsigned int max_data_bytes)
870 char *params = *pparams;
871 char *pdata = *ppdata;
876 bool return_additional_info;
887 SMB_STRUCT_STAT sbuf;
890 struct ea_list *ea_list = NULL;
895 uint32 create_disposition;
896 uint32 create_options = 0;
897 TALLOC_CTX *ctx = talloc_tos();
899 SET_STAT_INVALID(sbuf);
902 * Ensure we have enough parameters to perform the operation.
905 if (total_params < 29) {
906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
910 flags = SVAL(params, 0);
911 deny_mode = SVAL(params, 2);
912 open_attr = SVAL(params,6);
913 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
914 if (oplock_request) {
915 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
919 return_additional_info = BITSETW(params,0);
920 open_sattr = SVAL(params, 4);
921 open_time = make_unix_date3(params+8);
923 open_ofun = SVAL(params,12);
924 open_size = IVAL(params,14);
928 reply_doserror(req, ERRSRV, ERRaccess);
932 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
933 total_params - 28, STR_TERMINATE,
935 if (!NT_STATUS_IS_OK(status)) {
936 reply_nterror(req, status);
940 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
941 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
942 (unsigned int)open_ofun, open_size));
944 if (open_ofun == 0) {
945 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
949 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
954 reply_doserror(req, ERRDOS, ERRbadaccess);
958 /* Any data in this call is an EA list. */
959 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
960 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
964 if (total_data != 4) {
965 if (total_data < 10) {
966 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
970 if (IVAL(pdata,0) > total_data) {
971 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
972 IVAL(pdata,0), (unsigned int)total_data));
973 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
977 ea_list = read_ea_list(talloc_tos(), pdata + 4,
980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
983 } else if (IVAL(pdata,0) != 4) {
984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
988 status = SMB_VFS_CREATE_FILE(
991 0, /* root_dir_fid */
993 CFF_DOS_PATH, /* create_file_flags */
994 access_mask, /* access_mask */
995 share_mode, /* share_access */
996 create_disposition, /* create_disposition*/
997 create_options, /* create_options */
998 open_attr, /* file_attributes */
999 oplock_request, /* oplock_request */
1000 open_size, /* allocation_size */
1002 ea_list, /* ea_list */
1004 &smb_action, /* pinfo */
1007 if (!NT_STATUS_IS_OK(status)) {
1008 if (open_was_deferred(req->mid)) {
1009 /* We have re-scheduled this call. */
1012 reply_openerror(req, status);
1016 size = get_file_size_stat(&sbuf);
1017 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1018 mtime = sbuf.st_mtime;
1019 inode = sbuf.st_ino;
1021 close_file(req, fsp, ERROR_CLOSE);
1022 reply_doserror(req, ERRDOS,ERRnoaccess);
1026 /* Realloc the size of parameters and data we will return */
1027 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1028 if(*pparams == NULL ) {
1029 reply_nterror(req, NT_STATUS_NO_MEMORY);
1034 SSVAL(params,0,fsp->fnum);
1035 SSVAL(params,2,fattr);
1036 srv_put_dos_date2(params,4, mtime);
1037 SIVAL(params,8, (uint32)size);
1038 SSVAL(params,12,deny_mode);
1039 SSVAL(params,14,0); /* open_type - file or directory. */
1040 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1042 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1043 smb_action |= EXTENDED_OPLOCK_GRANTED;
1046 SSVAL(params,18,smb_action);
1049 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1051 SIVAL(params,20,inode);
1052 SSVAL(params,24,0); /* Padding. */
1054 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1055 SIVAL(params, 26, ea_size);
1057 SIVAL(params, 26, 0);
1060 /* Send the required number of replies */
1061 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1064 /*********************************************************
1065 Routine to check if a given string matches exactly.
1066 as a special case a mask of "." does NOT match. That
1067 is required for correct wildcard semantics
1068 Case can be significant or not.
1069 **********************************************************/
1071 static bool exact_match(connection_struct *conn,
1075 if (mask[0] == '.' && mask[1] == 0)
1077 if (dptr_has_wild(conn->dirptr)) {
1080 if (conn->case_sensitive)
1081 return strcmp(str,mask)==0;
1083 return StrCaseCmp(str,mask) == 0;
1086 /****************************************************************************
1087 Return the filetype for UNIX extensions.
1088 ****************************************************************************/
1090 static uint32 unix_filetype(mode_t mode)
1093 return UNIX_TYPE_FILE;
1094 else if(S_ISDIR(mode))
1095 return UNIX_TYPE_DIR;
1097 else if(S_ISLNK(mode))
1098 return UNIX_TYPE_SYMLINK;
1101 else if(S_ISCHR(mode))
1102 return UNIX_TYPE_CHARDEV;
1105 else if(S_ISBLK(mode))
1106 return UNIX_TYPE_BLKDEV;
1109 else if(S_ISFIFO(mode))
1110 return UNIX_TYPE_FIFO;
1113 else if(S_ISSOCK(mode))
1114 return UNIX_TYPE_SOCKET;
1117 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1118 return UNIX_TYPE_UNKNOWN;
1121 /****************************************************************************
1122 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1123 ****************************************************************************/
1125 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1127 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1128 SMB_STRUCT_STAT *psbuf,
1130 enum perm_type ptype,
1135 if (perms == SMB_MODE_NO_CHANGE) {
1136 if (!VALID_STAT(*psbuf)) {
1137 return NT_STATUS_INVALID_PARAMETER;
1139 *ret_perms = psbuf->st_mode;
1140 return NT_STATUS_OK;
1144 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1145 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1146 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1147 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1148 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1149 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1150 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1151 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1152 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1154 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1157 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1160 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1165 /* Apply mode mask */
1166 ret &= lp_create_mask(SNUM(conn));
1167 /* Add in force bits */
1168 ret |= lp_force_create_mode(SNUM(conn));
1171 ret &= lp_dir_mask(SNUM(conn));
1172 /* Add in force bits */
1173 ret |= lp_force_dir_mode(SNUM(conn));
1175 case PERM_EXISTING_FILE:
1176 /* Apply mode mask */
1177 ret &= lp_security_mask(SNUM(conn));
1178 /* Add in force bits */
1179 ret |= lp_force_security_mode(SNUM(conn));
1181 case PERM_EXISTING_DIR:
1182 /* Apply mode mask */
1183 ret &= lp_dir_security_mask(SNUM(conn));
1184 /* Add in force bits */
1185 ret |= lp_force_dir_security_mode(SNUM(conn));
1190 return NT_STATUS_OK;
1193 /****************************************************************************
1194 Needed to show the msdfs symlinks as directories. Modifies psbuf
1195 to be a directory if it's a msdfs link.
1196 ****************************************************************************/
1198 static bool check_msdfs_link(connection_struct *conn,
1199 const char *pathname,
1200 SMB_STRUCT_STAT *psbuf)
1202 int saved_errno = errno;
1203 if(lp_host_msdfs() &&
1204 lp_msdfs_root(SNUM(conn)) &&
1205 is_msdfs_link(conn, pathname, psbuf)) {
1207 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1210 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1211 errno = saved_errno;
1214 errno = saved_errno;
1219 /****************************************************************************
1220 Get a level dependent lanman2 dir entry.
1221 ****************************************************************************/
1223 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1224 connection_struct *conn,
1226 const char *path_mask,
1229 int requires_resume_key,
1235 int space_remaining,
1237 bool *got_exact_match,
1238 int *last_entry_off,
1239 struct ea_list *name_list)
1243 SMB_STRUCT_STAT sbuf;
1244 const char *mask = NULL;
1245 char *pathreal = NULL;
1246 const char *fname = NULL;
1247 char *p, *q, *pdata = *ppdata;
1251 SMB_OFF_T file_size = 0;
1252 uint64_t allocation_size = 0;
1254 struct timespec mdate_ts, adate_ts, create_date_ts;
1255 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1257 char *last_entry_ptr;
1259 uint32 nt_extmode; /* Used for NT connections instead of mode */
1260 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1261 bool check_mangled_names = lp_manglednames(conn->params);
1262 char mangled_name[13]; /* mangled 8.3 name. */
1264 *out_of_space = False;
1265 *got_exact_match = False;
1267 ZERO_STRUCT(mdate_ts);
1268 ZERO_STRUCT(adate_ts);
1269 ZERO_STRUCT(create_date_ts);
1271 if (!conn->dirptr) {
1275 p = strrchr_m(path_mask,'/');
1278 mask = talloc_strdup(ctx,"*.*");
1288 bool ms_dfs_link = False;
1290 /* Needed if we run out of space */
1291 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1292 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1295 * Due to bugs in NT client redirectors we are not using
1296 * resume keys any more - set them to zero.
1297 * Check out the related comments in findfirst/findnext.
1303 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1304 (long)conn->dirptr,curr_dirpos));
1311 * fname may get mangled, dname is never mangled.
1312 * Whenever we're accessing the filesystem we use
1313 * pathreal which is composed from dname.
1319 /* Mangle fname if it's an illegal name. */
1320 if (mangle_must_mangle(dname,conn->params)) {
1321 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1322 continue; /* Error - couldn't mangle. */
1324 fname = mangled_name;
1327 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1328 got_match = mask_match(fname, mask, conn->case_sensitive);
1331 if(!got_match && check_mangled_names &&
1332 !mangle_is_8_3(fname, False, conn->params)) {
1334 * It turns out that NT matches wildcards against
1335 * both long *and* short names. This may explain some
1336 * of the wildcard wierdness from old DOS clients
1337 * that some people have been seeing.... JRA.
1339 /* Force the mangling into 8.3. */
1340 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1341 continue; /* Error - couldn't mangle. */
1344 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1345 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1350 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1352 if (dont_descend && !isdots) {
1358 pathreal = talloc_asprintf(ctx,
1363 pathreal = talloc_asprintf(ctx,
1373 if (INFO_LEVEL_IS_UNIX(info_level)) {
1374 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1375 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1376 pathreal,strerror(errno)));
1377 TALLOC_FREE(pathreal);
1380 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1381 /* Needed to show the msdfs symlinks as
1384 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1386 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1387 pathreal,strerror(errno)));
1388 TALLOC_FREE(pathreal);
1394 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1396 mode = dos_mode(conn,pathreal,&sbuf);
1399 if (!dir_check_ftype(conn,mode,dirtype)) {
1400 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1401 TALLOC_FREE(pathreal);
1405 if (!(mode & aDIR)) {
1406 file_size = get_file_size_stat(&sbuf);
1408 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1410 mdate_ts = get_mtimespec(&sbuf);
1411 adate_ts = get_atimespec(&sbuf);
1412 create_date_ts = get_create_timespec(&sbuf,
1413 lp_fake_dir_create_times(SNUM(conn)));
1415 if (ask_sharemode) {
1416 struct timespec write_time_ts;
1417 struct file_id fileid;
1419 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1420 get_file_infos(fileid, NULL, &write_time_ts);
1421 if (!null_timespec(write_time_ts)) {
1422 mdate_ts = write_time_ts;
1426 if (lp_dos_filetime_resolution(SNUM(conn))) {
1427 dos_filetime_timespec(&create_date_ts);
1428 dos_filetime_timespec(&mdate_ts);
1429 dos_filetime_timespec(&adate_ts);
1432 create_date = convert_timespec_to_time_t(create_date_ts);
1433 mdate = convert_timespec_to_time_t(mdate_ts);
1434 adate = convert_timespec_to_time_t(adate_ts);
1436 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1441 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1448 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1450 switch (info_level) {
1451 case SMB_FIND_INFO_STANDARD:
1452 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1453 if(requires_resume_key) {
1457 srv_put_dos_date2(p,0,create_date);
1458 srv_put_dos_date2(p,4,adate);
1459 srv_put_dos_date2(p,8,mdate);
1460 SIVAL(p,12,(uint32)file_size);
1461 SIVAL(p,16,(uint32)allocation_size);
1465 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1466 p += ucs2_align(base_data, p, 0);
1468 len = srvstr_push(base_data, flags2, p,
1469 fname, PTR_DIFF(end_data, p),
1471 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1473 SCVAL(nameptr, -1, len - 2);
1475 SCVAL(nameptr, -1, 0);
1479 SCVAL(nameptr, -1, len - 1);
1481 SCVAL(nameptr, -1, 0);
1487 case SMB_FIND_EA_SIZE:
1488 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1489 if(requires_resume_key) {
1493 srv_put_dos_date2(p,0,create_date);
1494 srv_put_dos_date2(p,4,adate);
1495 srv_put_dos_date2(p,8,mdate);
1496 SIVAL(p,12,(uint32)file_size);
1497 SIVAL(p,16,(uint32)allocation_size);
1500 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1501 SIVAL(p,22,ea_size); /* Extended attributes */
1505 len = srvstr_push(base_data, flags2,
1506 p, fname, PTR_DIFF(end_data, p),
1507 STR_TERMINATE | STR_NOALIGN);
1508 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1521 SCVAL(nameptr,0,len);
1523 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1526 case SMB_FIND_EA_LIST:
1528 struct ea_list *file_list = NULL;
1531 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1535 if(requires_resume_key) {
1539 srv_put_dos_date2(p,0,create_date);
1540 srv_put_dos_date2(p,4,adate);
1541 srv_put_dos_date2(p,8,mdate);
1542 SIVAL(p,12,(uint32)file_size);
1543 SIVAL(p,16,(uint32)allocation_size);
1545 p += 22; /* p now points to the EA area. */
1547 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1548 name_list = ea_list_union(name_list, file_list, &ea_len);
1550 /* We need to determine if this entry will fit in the space available. */
1551 /* Max string size is 255 bytes. */
1552 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1553 /* Move the dirptr back to prev_dirpos */
1554 dptr_SeekDir(conn->dirptr, prev_dirpos);
1555 *out_of_space = True;
1556 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1557 return False; /* Not finished - just out of space */
1560 /* Push the ea_data followed by the name. */
1561 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1563 len = srvstr_push(base_data, flags2,
1564 p + 1, fname, PTR_DIFF(end_data, p+1),
1565 STR_TERMINATE | STR_NOALIGN);
1566 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1579 SCVAL(nameptr,0,len);
1581 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1585 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1586 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1587 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1589 SIVAL(p,0,reskey); p += 4;
1590 put_long_date_timespec(p,create_date_ts); p += 8;
1591 put_long_date_timespec(p,adate_ts); p += 8;
1592 put_long_date_timespec(p,mdate_ts); p += 8;
1593 put_long_date_timespec(p,mdate_ts); p += 8;
1594 SOFF_T(p,0,file_size); p += 8;
1595 SOFF_T(p,0,allocation_size); p += 8;
1596 SIVAL(p,0,nt_extmode); p += 4;
1597 q = p; p += 4; /* q is placeholder for name length. */
1599 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1600 SIVAL(p,0,ea_size); /* Extended attributes */
1603 /* Clear the short name buffer. This is
1604 * IMPORTANT as not doing so will trigger
1605 * a Win2k client bug. JRA.
1607 if (!was_8_3 && check_mangled_names) {
1608 if (!name_to_8_3(fname,mangled_name,True,
1610 /* Error - mangle failed ! */
1611 memset(mangled_name,'\0',12);
1613 mangled_name[12] = 0;
1614 len = srvstr_push(base_data, flags2,
1615 p+2, mangled_name, 24,
1616 STR_UPPER|STR_UNICODE);
1618 memset(p + 2 + len,'\0',24 - len);
1625 len = srvstr_push(base_data, flags2, p,
1626 fname, PTR_DIFF(end_data, p),
1627 STR_TERMINATE_ASCII);
1630 SIVAL(p,0,0); /* Ensure any padding is null. */
1631 len = PTR_DIFF(p, pdata);
1632 len = (len + 3) & ~3;
1637 case SMB_FIND_FILE_DIRECTORY_INFO:
1638 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1640 SIVAL(p,0,reskey); p += 4;
1641 put_long_date_timespec(p,create_date_ts); p += 8;
1642 put_long_date_timespec(p,adate_ts); p += 8;
1643 put_long_date_timespec(p,mdate_ts); p += 8;
1644 put_long_date_timespec(p,mdate_ts); p += 8;
1645 SOFF_T(p,0,file_size); p += 8;
1646 SOFF_T(p,0,allocation_size); p += 8;
1647 SIVAL(p,0,nt_extmode); p += 4;
1648 len = srvstr_push(base_data, flags2,
1649 p + 4, fname, PTR_DIFF(end_data, p+4),
1650 STR_TERMINATE_ASCII);
1653 SIVAL(p,0,0); /* Ensure any padding is null. */
1654 len = PTR_DIFF(p, pdata);
1655 len = (len + 3) & ~3;
1660 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1661 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1663 SIVAL(p,0,reskey); p += 4;
1664 put_long_date_timespec(p,create_date_ts); p += 8;
1665 put_long_date_timespec(p,adate_ts); p += 8;
1666 put_long_date_timespec(p,mdate_ts); p += 8;
1667 put_long_date_timespec(p,mdate_ts); p += 8;
1668 SOFF_T(p,0,file_size); p += 8;
1669 SOFF_T(p,0,allocation_size); p += 8;
1670 SIVAL(p,0,nt_extmode); p += 4;
1671 q = p; p += 4; /* q is placeholder for name length. */
1673 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1674 SIVAL(p,0,ea_size); /* Extended attributes */
1677 len = srvstr_push(base_data, flags2, p,
1678 fname, PTR_DIFF(end_data, p),
1679 STR_TERMINATE_ASCII);
1683 SIVAL(p,0,0); /* Ensure any padding is null. */
1684 len = PTR_DIFF(p, pdata);
1685 len = (len + 3) & ~3;
1690 case SMB_FIND_FILE_NAMES_INFO:
1691 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1693 SIVAL(p,0,reskey); p += 4;
1695 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1696 acl on a dir (tridge) */
1697 len = srvstr_push(base_data, flags2, p,
1698 fname, PTR_DIFF(end_data, p),
1699 STR_TERMINATE_ASCII);
1702 SIVAL(p,0,0); /* Ensure any padding is null. */
1703 len = PTR_DIFF(p, pdata);
1704 len = (len + 3) & ~3;
1709 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1710 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1712 SIVAL(p,0,reskey); p += 4;
1713 put_long_date_timespec(p,create_date_ts); p += 8;
1714 put_long_date_timespec(p,adate_ts); p += 8;
1715 put_long_date_timespec(p,mdate_ts); p += 8;
1716 put_long_date_timespec(p,mdate_ts); p += 8;
1717 SOFF_T(p,0,file_size); p += 8;
1718 SOFF_T(p,0,allocation_size); p += 8;
1719 SIVAL(p,0,nt_extmode); p += 4;
1720 q = p; p += 4; /* q is placeholder for name length. */
1722 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1723 SIVAL(p,0,ea_size); /* Extended attributes */
1726 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1727 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1728 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1729 len = srvstr_push(base_data, flags2, p,
1730 fname, PTR_DIFF(end_data, p),
1731 STR_TERMINATE_ASCII);
1734 SIVAL(p,0,0); /* Ensure any padding is null. */
1735 len = PTR_DIFF(p, pdata);
1736 len = (len + 3) & ~3;
1741 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1742 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1743 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1745 SIVAL(p,0,reskey); p += 4;
1746 put_long_date_timespec(p,create_date_ts); p += 8;
1747 put_long_date_timespec(p,adate_ts); p += 8;
1748 put_long_date_timespec(p,mdate_ts); p += 8;
1749 put_long_date_timespec(p,mdate_ts); p += 8;
1750 SOFF_T(p,0,file_size); p += 8;
1751 SOFF_T(p,0,allocation_size); p += 8;
1752 SIVAL(p,0,nt_extmode); p += 4;
1753 q = p; p += 4; /* q is placeholder for name length */
1755 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1756 SIVAL(p,0,ea_size); /* Extended attributes */
1759 /* Clear the short name buffer. This is
1760 * IMPORTANT as not doing so will trigger
1761 * a Win2k client bug. JRA.
1763 if (!was_8_3 && check_mangled_names) {
1764 if (!name_to_8_3(fname,mangled_name,True,
1766 /* Error - mangle failed ! */
1767 memset(mangled_name,'\0',12);
1769 mangled_name[12] = 0;
1770 len = srvstr_push(base_data, flags2,
1771 p+2, mangled_name, 24,
1772 STR_UPPER|STR_UNICODE);
1775 memset(p + 2 + len,'\0',24 - len);
1782 SSVAL(p,0,0); p += 2; /* Reserved ? */
1783 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1784 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1785 len = srvstr_push(base_data, flags2, p,
1786 fname, PTR_DIFF(end_data, p),
1787 STR_TERMINATE_ASCII);
1790 SIVAL(p,0,0); /* Ensure any padding is null. */
1791 len = PTR_DIFF(p, pdata);
1792 len = (len + 3) & ~3;
1797 /* CIFS UNIX Extension. */
1799 case SMB_FIND_FILE_UNIX:
1800 case SMB_FIND_FILE_UNIX_INFO2:
1802 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1804 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1806 if (info_level == SMB_FIND_FILE_UNIX) {
1807 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1808 p = store_file_unix_basic(conn, p,
1810 len = srvstr_push(base_data, flags2, p,
1811 fname, PTR_DIFF(end_data, p),
1814 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1815 p = store_file_unix_basic_info2(conn, p,
1819 len = srvstr_push(base_data, flags2, p, fname,
1820 PTR_DIFF(end_data, p), 0);
1821 SIVAL(nameptr, 0, len);
1825 SIVAL(p,0,0); /* Ensure any padding is null. */
1827 len = PTR_DIFF(p, pdata);
1828 len = (len + 3) & ~3;
1829 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1831 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1840 if (PTR_DIFF(p,pdata) > space_remaining) {
1841 /* Move the dirptr back to prev_dirpos */
1842 dptr_SeekDir(conn->dirptr, prev_dirpos);
1843 *out_of_space = True;
1844 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1845 return False; /* Not finished - just out of space */
1848 /* Setup the last entry pointer, as an offset from base_data */
1849 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1850 /* Advance the data pointer to the next slot */
1856 /****************************************************************************
1857 Reply to a TRANS2_FINDFIRST.
1858 ****************************************************************************/
1860 static void call_trans2findfirst(connection_struct *conn,
1861 struct smb_request *req,
1862 char **pparams, int total_params,
1863 char **ppdata, int total_data,
1864 unsigned int max_data_bytes)
1866 /* We must be careful here that we don't return more than the
1867 allowed number of data bytes. If this means returning fewer than
1868 maxentries then so be it. We assume that the redirector has
1869 enough room for the fixed number of parameter bytes it has
1871 char *params = *pparams;
1872 char *pdata = *ppdata;
1876 uint16 findfirst_flags;
1877 bool close_after_first;
1879 bool requires_resume_key;
1881 char *directory = NULL;
1884 int last_entry_off=0;
1888 bool finished = False;
1889 bool dont_descend = False;
1890 bool out_of_space = False;
1891 int space_remaining;
1892 bool mask_contains_wcard = False;
1893 SMB_STRUCT_STAT sbuf;
1894 struct ea_list *ea_list = NULL;
1895 NTSTATUS ntstatus = NT_STATUS_OK;
1896 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1897 TALLOC_CTX *ctx = talloc_tos();
1899 if (total_params < 13) {
1900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1904 dirtype = SVAL(params,0);
1905 maxentries = SVAL(params,2);
1906 findfirst_flags = SVAL(params,4);
1907 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1908 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1909 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1910 info_level = SVAL(params,6);
1912 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1913 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1914 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1915 info_level, max_data_bytes));
1918 /* W2K3 seems to treat zero as 1. */
1922 switch (info_level) {
1923 case SMB_FIND_INFO_STANDARD:
1924 case SMB_FIND_EA_SIZE:
1925 case SMB_FIND_EA_LIST:
1926 case SMB_FIND_FILE_DIRECTORY_INFO:
1927 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1928 case SMB_FIND_FILE_NAMES_INFO:
1929 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1930 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1931 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1933 case SMB_FIND_FILE_UNIX:
1934 case SMB_FIND_FILE_UNIX_INFO2:
1935 /* Always use filesystem for UNIX mtime query. */
1936 ask_sharemode = false;
1937 if (!lp_unix_extensions()) {
1938 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1943 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1947 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1948 params+12, total_params - 12,
1949 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1950 if (!NT_STATUS_IS_OK(ntstatus)) {
1951 reply_nterror(req, ntstatus);
1955 ntstatus = resolve_dfspath_wcard(ctx, conn,
1956 req->flags2 & FLAGS2_DFS_PATHNAMES,
1959 &mask_contains_wcard);
1960 if (!NT_STATUS_IS_OK(ntstatus)) {
1961 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1962 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1963 ERRSRV, ERRbadpath);
1966 reply_nterror(req, ntstatus);
1970 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1971 if (!NT_STATUS_IS_OK(ntstatus)) {
1972 reply_nterror(req, ntstatus);
1976 ntstatus = check_name(conn, directory);
1977 if (!NT_STATUS_IS_OK(ntstatus)) {
1978 reply_nterror(req, ntstatus);
1982 p = strrchr_m(directory,'/');
1984 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1985 if((directory[0] == '.') && (directory[1] == '\0')) {
1986 mask = talloc_strdup(ctx,"*");
1988 reply_nterror(req, NT_STATUS_NO_MEMORY);
1991 mask_contains_wcard = True;
1993 directory = talloc_strdup(talloc_tos(), "./");
1995 reply_nterror(req, NT_STATUS_NO_MEMORY);
2002 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2004 if (info_level == SMB_FIND_EA_LIST) {
2007 if (total_data < 4) {
2008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2012 ea_size = IVAL(pdata,0);
2013 if (ea_size != total_data) {
2014 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2015 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2020 if (!lp_ea_support(SNUM(conn))) {
2021 reply_doserror(req, ERRDOS, ERReasnotsupported);
2025 /* Pull out the list of names. */
2026 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2033 *ppdata = (char *)SMB_REALLOC(
2034 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2035 if(*ppdata == NULL ) {
2036 reply_nterror(req, NT_STATUS_NO_MEMORY);
2040 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2042 /* Realloc the params space */
2043 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2044 if (*pparams == NULL) {
2045 reply_nterror(req, NT_STATUS_NO_MEMORY);
2050 /* Save the wildcard match and attribs we are using on this directory -
2051 needed as lanman2 assumes these are being saved between calls */
2053 ntstatus = dptr_create(conn,
2059 mask_contains_wcard,
2063 if (!NT_STATUS_IS_OK(ntstatus)) {
2064 reply_nterror(req, ntstatus);
2068 dptr_num = dptr_dnum(conn->dirptr);
2069 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2071 /* Initialize per TRANS2_FIND_FIRST operation data */
2072 dptr_init_search_op(conn->dirptr);
2074 /* We don't need to check for VOL here as this is returned by
2075 a different TRANS2 call. */
2077 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2078 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2079 dont_descend = True;
2082 space_remaining = max_data_bytes;
2083 out_of_space = False;
2085 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2086 bool got_exact_match = False;
2088 /* this is a heuristic to avoid seeking the dirptr except when
2089 absolutely necessary. It allows for a filename of about 40 chars */
2090 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2091 out_of_space = True;
2094 finished = !get_lanman2_dir_entry(ctx,
2097 mask,dirtype,info_level,
2098 requires_resume_key,dont_descend,
2101 space_remaining, &out_of_space,
2103 &last_entry_off, ea_list);
2106 if (finished && out_of_space)
2109 if (!finished && !out_of_space)
2113 * As an optimisation if we know we aren't looking
2114 * for a wildcard name (ie. the name matches the wildcard exactly)
2115 * then we can finish on any (first) match.
2116 * This speeds up large directory searches. JRA.
2122 /* Ensure space_remaining never goes -ve. */
2123 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2124 space_remaining = 0;
2125 out_of_space = true;
2127 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2131 /* Check if we can close the dirptr */
2132 if(close_after_first || (finished && close_if_end)) {
2133 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2134 dptr_close(&dptr_num);
2138 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2139 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2140 * the protocol level is less than NT1. Tested with smbclient. JRA.
2141 * This should fix the OS/2 client bug #2335.
2144 if(numentries == 0) {
2145 dptr_close(&dptr_num);
2146 if (Protocol < PROTOCOL_NT1) {
2147 reply_doserror(req, ERRDOS, ERRnofiles);
2150 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2151 ERRDOS, ERRbadfile);
2156 /* At this point pdata points to numentries directory entries. */
2158 /* Set up the return parameter block */
2159 SSVAL(params,0,dptr_num);
2160 SSVAL(params,2,numentries);
2161 SSVAL(params,4,finished);
2162 SSVAL(params,6,0); /* Never an EA error */
2163 SSVAL(params,8,last_entry_off);
2165 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2168 if ((! *directory) && dptr_path(dptr_num)) {
2169 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2171 reply_nterror(req, NT_STATUS_NO_MEMORY);
2175 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2176 smb_fn_name(req->cmd),
2177 mask, directory, dirtype, numentries ) );
2180 * Force a name mangle here to ensure that the
2181 * mask as an 8.3 name is top of the mangled cache.
2182 * The reasons for this are subtle. Don't remove
2183 * this code unless you know what you are doing
2184 * (see PR#13758). JRA.
2187 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2188 char mangled_name[13];
2189 name_to_8_3(mask, mangled_name, True, conn->params);
2195 /****************************************************************************
2196 Reply to a TRANS2_FINDNEXT.
2197 ****************************************************************************/
2199 static void call_trans2findnext(connection_struct *conn,
2200 struct smb_request *req,
2201 char **pparams, int total_params,
2202 char **ppdata, int total_data,
2203 unsigned int max_data_bytes)
2205 /* We must be careful here that we don't return more than the
2206 allowed number of data bytes. If this means returning fewer than
2207 maxentries then so be it. We assume that the redirector has
2208 enough room for the fixed number of parameter bytes it has
2210 char *params = *pparams;
2211 char *pdata = *ppdata;
2217 uint16 findnext_flags;
2218 bool close_after_request;
2220 bool requires_resume_key;
2222 bool mask_contains_wcard = False;
2223 char *resume_name = NULL;
2224 const char *mask = NULL;
2225 const char *directory = NULL;
2229 int i, last_entry_off=0;
2230 bool finished = False;
2231 bool dont_descend = False;
2232 bool out_of_space = False;
2233 int space_remaining;
2234 struct ea_list *ea_list = NULL;
2235 NTSTATUS ntstatus = NT_STATUS_OK;
2236 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2237 TALLOC_CTX *ctx = talloc_tos();
2239 if (total_params < 13) {
2240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2244 dptr_num = SVAL(params,0);
2245 maxentries = SVAL(params,2);
2246 info_level = SVAL(params,4);
2247 resume_key = IVAL(params,6);
2248 findnext_flags = SVAL(params,10);
2249 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2250 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2251 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2252 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2254 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2256 total_params - 12, STR_TERMINATE, &ntstatus,
2257 &mask_contains_wcard);
2258 if (!NT_STATUS_IS_OK(ntstatus)) {
2259 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2260 complain (it thinks we're asking for the directory above the shared
2261 path or an invalid name). Catch this as the resume name is only compared, never used in
2262 a file access. JRA. */
2263 srvstr_pull_talloc(ctx, params, req->flags2,
2264 &resume_name, params+12,
2268 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2269 reply_nterror(req, ntstatus);
2274 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2275 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2276 resume_key = %d resume name = %s continue=%d level = %d\n",
2277 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2278 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2281 /* W2K3 seems to treat zero as 1. */
2285 switch (info_level) {
2286 case SMB_FIND_INFO_STANDARD:
2287 case SMB_FIND_EA_SIZE:
2288 case SMB_FIND_EA_LIST:
2289 case SMB_FIND_FILE_DIRECTORY_INFO:
2290 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2291 case SMB_FIND_FILE_NAMES_INFO:
2292 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2293 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2294 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2296 case SMB_FIND_FILE_UNIX:
2297 case SMB_FIND_FILE_UNIX_INFO2:
2298 /* Always use filesystem for UNIX mtime query. */
2299 ask_sharemode = false;
2300 if (!lp_unix_extensions()) {
2301 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2306 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2310 if (info_level == SMB_FIND_EA_LIST) {
2313 if (total_data < 4) {
2314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2318 ea_size = IVAL(pdata,0);
2319 if (ea_size != total_data) {
2320 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2321 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2326 if (!lp_ea_support(SNUM(conn))) {
2327 reply_doserror(req, ERRDOS, ERReasnotsupported);
2331 /* Pull out the list of names. */
2332 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2339 *ppdata = (char *)SMB_REALLOC(
2340 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2341 if(*ppdata == NULL) {
2342 reply_nterror(req, NT_STATUS_NO_MEMORY);
2347 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2349 /* Realloc the params space */
2350 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2351 if(*pparams == NULL ) {
2352 reply_nterror(req, NT_STATUS_NO_MEMORY);
2358 /* Check that the dptr is valid */
2359 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2360 reply_doserror(req, ERRDOS, ERRnofiles);
2364 string_set(&conn->dirpath,dptr_path(dptr_num));
2366 /* Get the wildcard mask from the dptr */
2367 if((p = dptr_wcard(dptr_num))== NULL) {
2368 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2369 reply_doserror(req, ERRDOS, ERRnofiles);
2374 directory = conn->dirpath;
2376 /* Get the attr mask from the dptr */
2377 dirtype = dptr_attr(dptr_num);
2379 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2380 dptr_num, mask, dirtype,
2382 dptr_TellDir(conn->dirptr)));
2384 /* Initialize per TRANS2_FIND_NEXT operation data */
2385 dptr_init_search_op(conn->dirptr);
2387 /* We don't need to check for VOL here as this is returned by
2388 a different TRANS2 call. */
2390 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2391 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2392 dont_descend = True;
2395 space_remaining = max_data_bytes;
2396 out_of_space = False;
2399 * Seek to the correct position. We no longer use the resume key but
2400 * depend on the last file name instead.
2403 if(*resume_name && !continue_bit) {
2406 long current_pos = 0;
2408 * Remember, name_to_8_3 is called by
2409 * get_lanman2_dir_entry(), so the resume name
2410 * could be mangled. Ensure we check the unmangled name.
2413 if (mangle_is_mangled(resume_name, conn->params)) {
2414 char *new_resume_name = NULL;
2415 mangle_lookup_name_from_8_3(ctx,
2419 if (new_resume_name) {
2420 resume_name = new_resume_name;
2425 * Fix for NT redirector problem triggered by resume key indexes
2426 * changing between directory scans. We now return a resume key of 0
2427 * and instead look for the filename to continue from (also given
2428 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2429 * findfirst/findnext (as is usual) then the directory pointer
2430 * should already be at the correct place.
2433 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2434 } /* end if resume_name && !continue_bit */
2436 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2437 bool got_exact_match = False;
2439 /* this is a heuristic to avoid seeking the dirptr except when
2440 absolutely necessary. It allows for a filename of about 40 chars */
2441 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2442 out_of_space = True;
2445 finished = !get_lanman2_dir_entry(ctx,
2448 mask,dirtype,info_level,
2449 requires_resume_key,dont_descend,
2452 space_remaining, &out_of_space,
2454 &last_entry_off, ea_list);
2457 if (finished && out_of_space)
2460 if (!finished && !out_of_space)
2464 * As an optimisation if we know we aren't looking
2465 * for a wildcard name (ie. the name matches the wildcard exactly)
2466 * then we can finish on any (first) match.
2467 * This speeds up large directory searches. JRA.
2473 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2476 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2477 smb_fn_name(req->cmd),
2478 mask, directory, dirtype, numentries ) );
2480 /* Check if we can close the dirptr */
2481 if(close_after_request || (finished && close_if_end)) {
2482 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2483 dptr_close(&dptr_num); /* This frees up the saved mask */
2486 /* Set up the return parameter block */
2487 SSVAL(params,0,numentries);
2488 SSVAL(params,2,finished);
2489 SSVAL(params,4,0); /* Never an EA error */
2490 SSVAL(params,6,last_entry_off);
2492 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2498 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2500 E_md4hash(lp_servicename(SNUM(conn)),objid);
2504 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2506 SMB_ASSERT(extended_info != NULL);
2508 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2509 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2510 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2511 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2512 #ifdef SAMBA_VERSION_REVISION
2513 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2515 extended_info->samba_subversion = 0;
2516 #ifdef SAMBA_VERSION_RC_RELEASE
2517 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2519 #ifdef SAMBA_VERSION_PRE_RELEASE
2520 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2523 #ifdef SAMBA_VERSION_VENDOR_PATCH
2524 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2526 extended_info->samba_gitcommitdate = 0;
2527 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2528 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2531 memset(extended_info->samba_version_string, 0,
2532 sizeof(extended_info->samba_version_string));
2534 snprintf (extended_info->samba_version_string,
2535 sizeof(extended_info->samba_version_string),
2536 "%s", samba_version_string());
2539 /****************************************************************************
2540 Reply to a TRANS2_QFSINFO (query filesystem info).
2541 ****************************************************************************/
2543 static void call_trans2qfsinfo(connection_struct *conn,
2544 struct smb_request *req,
2545 char **pparams, int total_params,
2546 char **ppdata, int total_data,
2547 unsigned int max_data_bytes)
2549 char *pdata, *end_data;
2550 char *params = *pparams;
2554 const char *vname = volume_label(SNUM(conn));
2555 int snum = SNUM(conn);
2556 char *fstype = lp_fstype(SNUM(conn));
2557 uint32 additional_flags = 0;
2559 if (total_params < 2) {
2560 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2564 info_level = SVAL(params,0);
2567 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2568 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2569 "info level (0x%x) on IPC$.\n",
2570 (unsigned int)info_level));
2571 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2576 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2577 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2578 DEBUG(0,("call_trans2qfsinfo: encryption required "
2579 "and info level 0x%x sent.\n",
2580 (unsigned int)info_level));
2581 exit_server_cleanly("encryption required "
2587 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2589 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2590 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2591 reply_doserror(req, ERRSRV, ERRinvdevice);
2595 *ppdata = (char *)SMB_REALLOC(
2596 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2597 if (*ppdata == NULL ) {
2598 reply_nterror(req, NT_STATUS_NO_MEMORY);
2603 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2604 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2606 switch (info_level) {
2607 case SMB_INFO_ALLOCATION:
2609 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2611 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2612 reply_unixerror(req, ERRHRD, ERRgeneral);
2616 block_size = lp_block_size(snum);
2617 if (bsize < block_size) {
2618 uint64_t factor = block_size/bsize;
2623 if (bsize > block_size) {
2624 uint64_t factor = bsize/block_size;
2629 bytes_per_sector = 512;
2630 sectors_per_unit = bsize/bytes_per_sector;
2632 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2633 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2634 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2636 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2637 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2638 SIVAL(pdata,l1_cUnit,dsize);
2639 SIVAL(pdata,l1_cUnitAvail,dfree);
2640 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2644 case SMB_INFO_VOLUME:
2645 /* Return volume name */
2647 * Add volume serial number - hash of a combination of
2648 * the called hostname and the service name.
2650 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2652 * Win2k3 and previous mess this up by sending a name length
2653 * one byte short. I believe only older clients (OS/2 Win9x) use
2654 * this call so try fixing this by adding a terminating null to
2655 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2659 pdata+l2_vol_szVolLabel, vname,
2660 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2661 STR_NOALIGN|STR_TERMINATE);
2662 SCVAL(pdata,l2_vol_cch,len);
2663 data_len = l2_vol_szVolLabel + len;
2664 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2665 (unsigned)st.st_ctime, len, vname));
2668 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2669 case SMB_FS_ATTRIBUTE_INFORMATION:
2671 additional_flags = 0;
2672 #if defined(HAVE_SYS_QUOTAS)
2673 additional_flags |= FILE_VOLUME_QUOTAS;
2676 if(lp_nt_acl_support(SNUM(conn))) {
2677 additional_flags |= FILE_PERSISTENT_ACLS;
2680 /* Capabilities are filled in at connection time through STATVFS call */
2681 additional_flags |= conn->fs_capabilities;
2683 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2684 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2685 additional_flags); /* FS ATTRIBUTES */
2687 SIVAL(pdata,4,255); /* Max filename component length */
2688 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2689 and will think we can't do long filenames */
2690 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2691 PTR_DIFF(end_data, pdata+12),
2694 data_len = 12 + len;
2697 case SMB_QUERY_FS_LABEL_INFO:
2698 case SMB_FS_LABEL_INFORMATION:
2699 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2700 PTR_DIFF(end_data, pdata+4), 0);
2705 case SMB_QUERY_FS_VOLUME_INFO:
2706 case SMB_FS_VOLUME_INFORMATION:
2709 * Add volume serial number - hash of a combination of
2710 * the called hostname and the service name.
2712 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2713 (str_checksum(get_local_machine_name())<<16));
2715 /* Max label len is 32 characters. */
2716 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2717 PTR_DIFF(end_data, pdata+18),
2719 SIVAL(pdata,12,len);
2722 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2723 (int)strlen(vname),vname, lp_servicename(snum)));
2726 case SMB_QUERY_FS_SIZE_INFO:
2727 case SMB_FS_SIZE_INFORMATION:
2729 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2731 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2732 reply_unixerror(req, ERRHRD, ERRgeneral);
2735 block_size = lp_block_size(snum);
2736 if (bsize < block_size) {
2737 uint64_t factor = block_size/bsize;
2742 if (bsize > block_size) {
2743 uint64_t factor = bsize/block_size;
2748 bytes_per_sector = 512;
2749 sectors_per_unit = bsize/bytes_per_sector;
2750 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2751 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2752 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2753 SBIG_UINT(pdata,0,dsize);
2754 SBIG_UINT(pdata,8,dfree);
2755 SIVAL(pdata,16,sectors_per_unit);
2756 SIVAL(pdata,20,bytes_per_sector);
2760 case SMB_FS_FULL_SIZE_INFORMATION:
2762 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2764 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2765 reply_unixerror(req, ERRHRD, ERRgeneral);
2768 block_size = lp_block_size(snum);
2769 if (bsize < block_size) {
2770 uint64_t factor = block_size/bsize;
2775 if (bsize > block_size) {
2776 uint64_t factor = bsize/block_size;
2781 bytes_per_sector = 512;
2782 sectors_per_unit = bsize/bytes_per_sector;
2783 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2784 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2785 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2786 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2787 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2788 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2789 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2790 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2794 case SMB_QUERY_FS_DEVICE_INFO:
2795 case SMB_FS_DEVICE_INFORMATION:
2797 SIVAL(pdata,0,0); /* dev type */
2798 SIVAL(pdata,4,0); /* characteristics */
2801 #ifdef HAVE_SYS_QUOTAS
2802 case SMB_FS_QUOTA_INFORMATION:
2804 * what we have to send --metze:
2806 * Unknown1: 24 NULL bytes
2807 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2808 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2809 * Quota Flags: 2 byte :
2810 * Unknown3: 6 NULL bytes
2814 * details for Quota Flags:
2816 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2817 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2818 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2819 * 0x0001 Enable Quotas: enable quota for this fs
2823 /* we need to fake up a fsp here,
2824 * because its not send in this call
2827 SMB_NTQUOTA_STRUCT quotas;
2830 ZERO_STRUCT(quotas);
2836 if (conn->server_info->utok.uid != 0) {
2837 DEBUG(0,("set_user_quota: access_denied "
2838 "service [%s] user [%s]\n",
2839 lp_servicename(SNUM(conn)),
2840 conn->server_info->unix_name));
2841 reply_doserror(req, ERRDOS, ERRnoaccess);
2845 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2846 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2847 reply_doserror(req, ERRSRV, ERRerror);
2853 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2855 /* Unknown1 24 NULL bytes*/
2856 SBIG_UINT(pdata,0,(uint64_t)0);
2857 SBIG_UINT(pdata,8,(uint64_t)0);
2858 SBIG_UINT(pdata,16,(uint64_t)0);
2860 /* Default Soft Quota 8 bytes */
2861 SBIG_UINT(pdata,24,quotas.softlim);
2863 /* Default Hard Quota 8 bytes */
2864 SBIG_UINT(pdata,32,quotas.hardlim);
2866 /* Quota flag 2 bytes */
2867 SSVAL(pdata,40,quotas.qflags);
2869 /* Unknown3 6 NULL bytes */
2875 #endif /* HAVE_SYS_QUOTAS */
2876 case SMB_FS_OBJECTID_INFORMATION:
2878 unsigned char objid[16];
2879 struct smb_extended_info extended_info;
2880 memcpy(pdata,create_volume_objectid(conn, objid),16);
2881 samba_extended_info_version (&extended_info);
2882 SIVAL(pdata,16,extended_info.samba_magic);
2883 SIVAL(pdata,20,extended_info.samba_version);
2884 SIVAL(pdata,24,extended_info.samba_subversion);
2885 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2886 memcpy(pdata+36,extended_info.samba_version_string,28);
2892 * Query the version and capabilities of the CIFS UNIX extensions
2896 case SMB_QUERY_CIFS_UNIX_INFO:
2898 bool large_write = lp_min_receive_file_size() &&
2899 !srv_is_signing_active(smbd_server_conn);
2900 bool large_read = !srv_is_signing_active(smbd_server_conn);
2901 int encrypt_caps = 0;
2903 if (!lp_unix_extensions()) {
2904 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2908 switch (conn->encrypt_level) {
2914 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2917 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2918 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2919 large_write = false;
2925 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2926 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2928 /* We have POSIX ACLs, pathname, encryption,
2929 * large read/write, and locking capability. */
2931 SBIG_UINT(pdata,4,((uint64_t)(
2932 CIFS_UNIX_POSIX_ACLS_CAP|
2933 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2934 CIFS_UNIX_FCNTL_LOCKS_CAP|
2935 CIFS_UNIX_EXTATTR_CAP|
2936 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2938 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2940 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2944 case SMB_QUERY_POSIX_FS_INFO:
2947 vfs_statvfs_struct svfs;
2949 if (!lp_unix_extensions()) {
2950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2954 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2958 SIVAL(pdata,0,svfs.OptimalTransferSize);
2959 SIVAL(pdata,4,svfs.BlockSize);
2960 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2961 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2962 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2963 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2964 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2965 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2966 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2968 } else if (rc == EOPNOTSUPP) {
2969 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2971 #endif /* EOPNOTSUPP */
2973 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2974 reply_doserror(req, ERRSRV, ERRerror);
2980 case SMB_QUERY_POSIX_WHOAMI:
2986 if (!lp_unix_extensions()) {
2987 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2991 if (max_data_bytes < 40) {
2992 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2996 /* We ARE guest if global_sid_Builtin_Guests is
2997 * in our list of SIDs.
2999 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3000 conn->server_info->ptok)) {
3001 flags |= SMB_WHOAMI_GUEST;
3004 /* We are NOT guest if global_sid_Authenticated_Users
3005 * is in our list of SIDs.
3007 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3008 conn->server_info->ptok)) {
3009 flags &= ~SMB_WHOAMI_GUEST;
3012 /* NOTE: 8 bytes for UID/GID, irrespective of native
3013 * platform size. This matches
3014 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3016 data_len = 4 /* flags */
3023 + 4 /* pad/reserved */
3024 + (conn->server_info->utok.ngroups * 8)
3026 + (conn->server_info->ptok->num_sids *
3030 SIVAL(pdata, 0, flags);
3031 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3033 (uint64_t)conn->server_info->utok.uid);
3034 SBIG_UINT(pdata, 16,
3035 (uint64_t)conn->server_info->utok.gid);
3038 if (data_len >= max_data_bytes) {
3039 /* Potential overflow, skip the GIDs and SIDs. */
3041 SIVAL(pdata, 24, 0); /* num_groups */
3042 SIVAL(pdata, 28, 0); /* num_sids */
3043 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3044 SIVAL(pdata, 36, 0); /* reserved */
3050 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3051 SIVAL(pdata, 28, conn->server_info->num_sids);
3053 /* We walk the SID list twice, but this call is fairly
3054 * infrequent, and I don't expect that it's performance
3055 * sensitive -- jpeach
3057 for (i = 0, sid_bytes = 0;
3058 i < conn->server_info->ptok->num_sids; ++i) {
3059 sid_bytes += ndr_size_dom_sid(
3060 &conn->server_info->ptok->user_sids[i],
3065 /* SID list byte count */
3066 SIVAL(pdata, 32, sid_bytes);
3068 /* 4 bytes pad/reserved - must be zero */
3069 SIVAL(pdata, 36, 0);
3073 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3074 SBIG_UINT(pdata, data_len,
3075 (uint64_t)conn->server_info->utok.groups[i]);
3081 i < conn->server_info->ptok->num_sids; ++i) {
3082 int sid_len = ndr_size_dom_sid(
3083 &conn->server_info->ptok->user_sids[i],
3087 sid_linearize(pdata + data_len, sid_len,
3088 &conn->server_info->ptok->user_sids[i]);
3089 data_len += sid_len;
3095 case SMB_MAC_QUERY_FS_INFO:
3097 * Thursby MAC extension... ONLY on NTFS filesystems
3098 * once we do streams then we don't need this
3100 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3102 SIVAL(pdata,84,0x100); /* Don't support mac... */
3107 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3112 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3115 DEBUG( 4, ( "%s info_level = %d\n",
3116 smb_fn_name(req->cmd), info_level) );
3121 /****************************************************************************
3122 Reply to a TRANS2_SETFSINFO (set filesystem info).
3123 ****************************************************************************/
3125 static void call_trans2setfsinfo(connection_struct *conn,
3126 struct smb_request *req,
3127 char **pparams, int total_params,
3128 char **ppdata, int total_data,
3129 unsigned int max_data_bytes)
3131 char *pdata = *ppdata;
3132 char *params = *pparams;
3135 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3138 if (total_params < 4) {
3139 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3145 info_level = SVAL(params,2);
3148 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3149 info_level != SMB_SET_CIFS_UNIX_INFO) {
3150 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3151 "info level (0x%x) on IPC$.\n",
3152 (unsigned int)info_level));
3153 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3158 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3159 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3160 DEBUG(0,("call_trans2setfsinfo: encryption required "
3161 "and info level 0x%x sent.\n",
3162 (unsigned int)info_level));
3163 exit_server_cleanly("encryption required "
3169 switch(info_level) {
3170 case SMB_SET_CIFS_UNIX_INFO:
3172 uint16 client_unix_major;
3173 uint16 client_unix_minor;
3174 uint32 client_unix_cap_low;
3175 uint32 client_unix_cap_high;
3177 if (!lp_unix_extensions()) {
3179 NT_STATUS_INVALID_LEVEL);
3183 /* There should be 12 bytes of capabilities set. */
3184 if (total_data < 8) {
3187 NT_STATUS_INVALID_PARAMETER);
3190 client_unix_major = SVAL(pdata,0);
3191 client_unix_minor = SVAL(pdata,2);
3192 client_unix_cap_low = IVAL(pdata,4);
3193 client_unix_cap_high = IVAL(pdata,8);
3194 /* Just print these values for now. */
3195 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3196 cap_low = 0x%x, cap_high = 0x%x\n",
3197 (unsigned int)client_unix_major,
3198 (unsigned int)client_unix_minor,
3199 (unsigned int)client_unix_cap_low,
3200 (unsigned int)client_unix_cap_high ));
3202 /* Here is where we must switch to posix pathname processing... */
3203 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3204 lp_set_posix_pathnames();
3205 mangle_change_to_posix();
3208 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3209 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3210 /* Client that knows how to do posix locks,
3211 * but not posix open/mkdir operations. Set a
3212 * default type for read/write checks. */
3214 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3220 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3223 size_t param_len = 0;
3224 size_t data_len = total_data;
3226 if (!lp_unix_extensions()) {
3229 NT_STATUS_INVALID_LEVEL);
3233 if (lp_smb_encrypt(SNUM(conn)) == false) {
3236 NT_STATUS_NOT_SUPPORTED);
3240 DEBUG( 4,("call_trans2setfsinfo: "
3241 "request transport encryption.\n"));
3243 status = srv_request_encryption_setup(conn,
3244 (unsigned char **)ppdata,
3246 (unsigned char **)pparams,
3249 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3250 !NT_STATUS_IS_OK(status)) {
3251 reply_nterror(req, status);
3255 send_trans2_replies(conn, req,
3262 if (NT_STATUS_IS_OK(status)) {
3263 /* Server-side transport
3264 * encryption is now *on*. */
3265 status = srv_encryption_start(conn);
3266 if (!NT_STATUS_IS_OK(status)) {
3267 exit_server_cleanly(
3268 "Failure in setting "
3269 "up encrypted transport");
3275 case SMB_FS_QUOTA_INFORMATION:
3277 files_struct *fsp = NULL;
3278 SMB_NTQUOTA_STRUCT quotas;
3280 ZERO_STRUCT(quotas);
3283 if ((conn->server_info->utok.uid != 0)
3284 ||!CAN_WRITE(conn)) {
3285 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3286 lp_servicename(SNUM(conn)),
3287 conn->server_info->unix_name));
3288 reply_doserror(req, ERRSRV, ERRaccess);
3292 /* note: normaly there're 48 bytes,
3293 * but we didn't use the last 6 bytes for now
3296 fsp = file_fsp(req, SVAL(params,0));
3298 if (!check_fsp_ntquota_handle(conn, req,
3300 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3302 req, NT_STATUS_INVALID_HANDLE);
3306 if (total_data < 42) {
3307 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3311 NT_STATUS_INVALID_PARAMETER);
3315 /* unknown_1 24 NULL bytes in pdata*/
3317 /* the soft quotas 8 bytes (uint64_t)*/
3318 quotas.softlim = (uint64_t)IVAL(pdata,24);
3319 #ifdef LARGE_SMB_OFF_T
3320 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3321 #else /* LARGE_SMB_OFF_T */
3322 if ((IVAL(pdata,28) != 0)&&
3323 ((quotas.softlim != 0xFFFFFFFF)||
3324 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3325 /* more than 32 bits? */
3328 NT_STATUS_INVALID_PARAMETER);
3331 #endif /* LARGE_SMB_OFF_T */
3333 /* the hard quotas 8 bytes (uint64_t)*/
3334 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3335 #ifdef LARGE_SMB_OFF_T
3336 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3337 #else /* LARGE_SMB_OFF_T */
3338 if ((IVAL(pdata,36) != 0)&&
3339 ((quotas.hardlim != 0xFFFFFFFF)||
3340 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3341 /* more than 32 bits? */
3344 NT_STATUS_INVALID_PARAMETER);
3347 #endif /* LARGE_SMB_OFF_T */
3349 /* quota_flags 2 bytes **/
3350 quotas.qflags = SVAL(pdata,40);
3352 /* unknown_2 6 NULL bytes follow*/
3354 /* now set the quotas */
3355 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3356 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3357 reply_doserror(req, ERRSRV, ERRerror);
3364 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3366 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3372 * sending this reply works fine,
3373 * but I'm not sure it's the same
3374 * like windows do...
3377 reply_outbuf(req, 10, 0);
3380 #if defined(HAVE_POSIX_ACLS)
3381 /****************************************************************************
3382 Utility function to count the number of entries in a POSIX acl.
3383 ****************************************************************************/
3385 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3387 unsigned int ace_count = 0;
3388 int entry_id = SMB_ACL_FIRST_ENTRY;
3389 SMB_ACL_ENTRY_T entry;
3391 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3393 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3394 entry_id = SMB_ACL_NEXT_ENTRY;
3401 /****************************************************************************
3402 Utility function to marshall a POSIX acl into wire format.
3403 ****************************************************************************/
3405 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3407 int entry_id = SMB_ACL_FIRST_ENTRY;
3408 SMB_ACL_ENTRY_T entry;
3410 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3411 SMB_ACL_TAG_T tagtype;
3412 SMB_ACL_PERMSET_T permset;
3413 unsigned char perms = 0;
3414 unsigned int own_grp;
3417 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3418 entry_id = SMB_ACL_NEXT_ENTRY;
3421 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3422 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3426 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3427 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3431 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3432 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3433 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3435 SCVAL(pdata,1,perms);
3438 case SMB_ACL_USER_OBJ:
3439 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3440 own_grp = (unsigned int)pst->st_uid;
3441 SIVAL(pdata,2,own_grp);
3446 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3448 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3451 own_grp = (unsigned int)*puid;
3452 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3453 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3454 SIVAL(pdata,2,own_grp);
3458 case SMB_ACL_GROUP_OBJ:
3459 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3460 own_grp = (unsigned int)pst->st_gid;
3461 SIVAL(pdata,2,own_grp);
3466 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3468 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3471 own_grp = (unsigned int)*pgid;
3472 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3473 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3474 SIVAL(pdata,2,own_grp);
3479 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3480 SIVAL(pdata,2,0xFFFFFFFF);
3481 SIVAL(pdata,6,0xFFFFFFFF);
3484 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3485 SIVAL(pdata,2,0xFFFFFFFF);
3486 SIVAL(pdata,6,0xFFFFFFFF);
3489 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3492 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3499 /****************************************************************************
3500 Store the FILE_UNIX_BASIC info.
3501 ****************************************************************************/
3503 static char *store_file_unix_basic(connection_struct *conn,
3506 const SMB_STRUCT_STAT *psbuf)
3508 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3509 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3511 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3514 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3517 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3518 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3519 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3522 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3526 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3530 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3533 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3537 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3541 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3544 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3548 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3555 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3556 * the chflags(2) (or equivalent) flags.
3558 * XXX: this really should be behind the VFS interface. To do this, we would
3559 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3560 * Each VFS module could then implement its own mapping as appropriate for the
3561 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3563 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3567 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3571 { UF_IMMUTABLE, EXT_IMMUTABLE },
3575 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3579 { UF_HIDDEN, EXT_HIDDEN },
3582 /* Do not remove. We need to guarantee that this array has at least one
3583 * entry to build on HP-UX.
3589 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3590 uint32 *smb_fflags, uint32 *smb_fmask)
3592 #ifdef HAVE_STAT_ST_FLAGS
3595 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3596 *smb_fmask |= info2_flags_map[i].smb_fflag;
3597 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3598 *smb_fflags |= info2_flags_map[i].smb_fflag;
3601 #endif /* HAVE_STAT_ST_FLAGS */
3604 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3605 const uint32 smb_fflags,
3606 const uint32 smb_fmask,
3609 #ifdef HAVE_STAT_ST_FLAGS
3610 uint32 max_fmask = 0;
3613 *stat_fflags = psbuf->st_flags;
3615 /* For each flags requested in smb_fmask, check the state of the
3616 * corresponding flag in smb_fflags and set or clear the matching
3620 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3621 max_fmask |= info2_flags_map[i].smb_fflag;
3622 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3623 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3624 *stat_fflags |= info2_flags_map[i].stat_fflag;
3626 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3631 /* If smb_fmask is asking to set any bits that are not supported by
3632 * our flag mappings, we should fail.
3634 if ((smb_fmask & max_fmask) != smb_fmask) {
3641 #endif /* HAVE_STAT_ST_FLAGS */
3645 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3646 * of file flags and birth (create) time.
3648 static char *store_file_unix_basic_info2(connection_struct *conn,
3651 const SMB_STRUCT_STAT *psbuf)
3653 uint32 file_flags = 0;
3654 uint32 flags_mask = 0;
3656 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3658 /* Create (birth) time 64 bit */
3659 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3662 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3663 SIVAL(pdata, 0, file_flags); /* flags */
3664 SIVAL(pdata, 4, flags_mask); /* mask */
3670 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3671 const struct stream_struct *streams,
3673 unsigned int max_data_bytes,
3674 unsigned int *data_size)
3677 unsigned int ofs = 0;
3679 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3680 unsigned int next_offset;
3682 smb_ucs2_t *namebuf;
3684 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3685 streams[i].name, &namelen) ||
3688 return NT_STATUS_INVALID_PARAMETER;
3692 * name_buf is now null-terminated, we need to marshall as not
3698 SIVAL(data, ofs+4, namelen);
3699 SOFF_T(data, ofs+8, streams[i].size);
3700 SOFF_T(data, ofs+16, streams[i].alloc_size);
3701 memcpy(data+ofs+24, namebuf, namelen);
3702 TALLOC_FREE(namebuf);
3704 next_offset = ofs + 24 + namelen;
3706 if (i == num_streams-1) {
3707 SIVAL(data, ofs, 0);
3710 unsigned int align = ndr_align_size(next_offset, 8);
3712 memset(data+next_offset, 0, align);
3713 next_offset += align;
3715 SIVAL(data, ofs, next_offset - ofs);
3724 return NT_STATUS_OK;
3727 /****************************************************************************
3728 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3729 ****************************************************************************/
3731 static void call_trans2qpipeinfo(connection_struct *conn,
3732 struct smb_request *req,
3733 unsigned int tran_call,
3734 char **pparams, int total_params,
3735 char **ppdata, int total_data,
3736 unsigned int max_data_bytes)
3738 char *params = *pparams;
3739 char *pdata = *ppdata;
3740 unsigned int data_size = 0;
3741 unsigned int param_size = 2;
3746 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3750 if (total_params < 4) {
3751 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3755 fsp = file_fsp(req, SVAL(params,0));
3756 if (!fsp_is_np(fsp)) {
3757 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3761 info_level = SVAL(params,2);
3763 *pparams = (char *)SMB_REALLOC(*pparams,2);
3764 if (*pparams == NULL) {
3765 reply_nterror(req, NT_STATUS_NO_MEMORY);
3770 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3771 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3772 if (*ppdata == NULL ) {
3773 reply_nterror(req, NT_STATUS_NO_MEMORY);
3778 switch (info_level) {
3779 case SMB_FILE_STANDARD_INFORMATION:
3781 SOFF_T(pdata,0,4096LL);
3788 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3792 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3798 /****************************************************************************
3799 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3800 file name or file id).
3801 ****************************************************************************/
3803 static void call_trans2qfilepathinfo(connection_struct *conn,
3804 struct smb_request *req,
3805 unsigned int tran_call,
3806 char **pparams, int total_params,
3807 char **ppdata, int total_data,
3808 unsigned int max_data_bytes)
3810 char *params = *pparams;
3811 char *pdata = *ppdata;
3812 char *dstart, *dend;
3816 SMB_OFF_T file_size=0;
3817 uint64_t allocation_size=0;
3818 unsigned int data_size = 0;
3819 unsigned int param_size = 2;
3820 SMB_STRUCT_STAT sbuf;
3821 char *dos_fname = NULL;
3827 bool delete_pending = False;
3829 time_t create_time, mtime, atime;
3830 struct timespec create_time_ts, mtime_ts, atime_ts;
3831 struct timespec write_time_ts;
3832 files_struct *fsp = NULL;
3833 struct file_id fileid;
3834 struct ea_list *ea_list = NULL;
3835 char *lock_data = NULL;
3836 bool ms_dfs_link = false;
3837 TALLOC_CTX *ctx = talloc_tos();
3840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3845 ZERO_STRUCT(write_time_ts);
3847 if (tran_call == TRANSACT2_QFILEINFO) {
3848 if (total_params < 4) {
3849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3854 call_trans2qpipeinfo(conn, req, tran_call,
3855 pparams, total_params,
3861 fsp = file_fsp(req, SVAL(params,0));
3862 info_level = SVAL(params,2);
3864 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3866 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3867 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3871 /* Initial check for valid fsp ptr. */
3872 if (!check_fsp_open(conn, req, fsp)) {
3876 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3878 reply_nterror(req, NT_STATUS_NO_MEMORY);
3882 if(fsp->fake_file_handle) {
3884 * This is actually for the QUOTA_FAKE_FILE --metze
3887 /* We know this name is ok, it's already passed the checks. */
3889 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3891 * This is actually a QFILEINFO on a directory
3892 * handle (returned from an NT SMB). NT5.0 seems
3893 * to do this call. JRA.
3896 if (INFO_LEVEL_IS_UNIX(info_level)) {
3897 /* Always do lstat for UNIX calls. */
3898 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3899 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3900 reply_unixerror(req,ERRDOS,ERRbadpath);
3903 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3904 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3905 reply_unixerror(req, ERRDOS, ERRbadpath);
3909 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3910 get_file_infos(fileid, &delete_pending, &write_time_ts);
3913 * Original code - this is an open file.
3915 if (!check_fsp(conn, req, fsp)) {
3919 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3920 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3921 reply_unixerror(req, ERRDOS, ERRbadfid);
3924 pos = fsp->fh->position_information;
3925 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3926 get_file_infos(fileid, &delete_pending, &write_time_ts);
3930 NTSTATUS status = NT_STATUS_OK;
3933 if (total_params < 7) {
3934 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3938 info_level = SVAL(params,0);
3940 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3942 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3943 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3947 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3949 STR_TERMINATE, &status);
3950 if (!NT_STATUS_IS_OK(status)) {
3951 reply_nterror(req, status);
3955 status = resolve_dfspath(ctx,
3957 req->flags2 & FLAGS2_DFS_PATHNAMES,
3960 if (!NT_STATUS_IS_OK(status)) {
3961 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3962 reply_botherror(req,
3963 NT_STATUS_PATH_NOT_COVERED,
3964 ERRSRV, ERRbadpath);
3966 reply_nterror(req, status);
3970 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 reply_nterror(req, status);
3975 status = check_name(conn, fname);
3976 if (!NT_STATUS_IS_OK(status)) {
3977 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3978 reply_nterror(req, status);
3982 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3983 && is_ntfs_stream_name(fname)) {
3985 SMB_STRUCT_STAT bsbuf;
3987 status = split_ntfs_stream_name(talloc_tos(), fname,
3989 if (!NT_STATUS_IS_OK(status)) {
3990 DEBUG(10, ("create_file_unixpath: "
3991 "split_ntfs_stream_name failed: %s\n",
3992 nt_errstr(status)));
3993 reply_nterror(req, status);
3997 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
3999 if (INFO_LEVEL_IS_UNIX(info_level)) {
4000 /* Always do lstat for UNIX calls. */
4001 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4002 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4003 reply_unixerror(req,ERRDOS,ERRbadpath);
4007 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4008 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4009 reply_unixerror(req,ERRDOS,ERRbadpath);
4014 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4015 get_file_infos(fileid, &delete_pending, NULL);
4016 if (delete_pending) {
4017 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4022 if (INFO_LEVEL_IS_UNIX(info_level)) {
4023 /* Always do lstat for UNIX calls. */
4024 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4025 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4026 reply_unixerror(req, ERRDOS, ERRbadpath);
4030 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4031 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4034 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4035 reply_unixerror(req, ERRDOS, ERRbadpath);
4040 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4041 get_file_infos(fileid, &delete_pending, &write_time_ts);
4042 if (delete_pending) {
4043 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4048 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4049 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4053 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4054 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4056 p = strrchr_m(fname,'/');
4063 mode = dos_mode_msdfs(conn,fname,&sbuf);
4065 mode = dos_mode(conn,fname,&sbuf);
4068 mode = FILE_ATTRIBUTE_NORMAL;
4070 nlink = sbuf.st_nlink;
4072 if (nlink && (mode&aDIR)) {
4076 if ((nlink > 0) && delete_pending) {
4080 fullpathname = fname;
4082 file_size = get_file_size_stat(&sbuf);
4084 /* Pull out any data sent here before we realloc. */
4085 switch (info_level) {
4086 case SMB_INFO_QUERY_EAS_FROM_LIST:
4088 /* Pull any EA list from the data portion. */
4091 if (total_data < 4) {
4093 req, NT_STATUS_INVALID_PARAMETER);
4096 ea_size = IVAL(pdata,0);
4098 if (total_data > 0 && ea_size != total_data) {
4099 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4100 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4102 req, NT_STATUS_INVALID_PARAMETER);
4106 if (!lp_ea_support(SNUM(conn))) {
4107 reply_doserror(req, ERRDOS,
4108 ERReasnotsupported);
4112 /* Pull out the list of names. */
4113 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4116 req, NT_STATUS_INVALID_PARAMETER);
4122 case SMB_QUERY_POSIX_LOCK:
4124 if (fsp == NULL || fsp->fh->fd == -1) {
4125 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4129 if (total_data != POSIX_LOCK_DATA_SIZE) {
4131 req, NT_STATUS_INVALID_PARAMETER);
4135 /* Copy the lock range data. */
4136 lock_data = (char *)TALLOC_MEMDUP(
4137 ctx, pdata, total_data);
4139 reply_nterror(req, NT_STATUS_NO_MEMORY);
4147 *pparams = (char *)SMB_REALLOC(*pparams,2);
4148 if (*pparams == NULL) {
4149 reply_nterror(req, NT_STATUS_NO_MEMORY);
4154 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4155 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4156 if (*ppdata == NULL ) {
4157 reply_nterror(req, NT_STATUS_NO_MEMORY);
4162 dend = dstart + data_size - 1;
4164 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4165 mtime_ts = get_mtimespec(&sbuf);
4166 atime_ts = get_atimespec(&sbuf);
4168 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4171 /* Do we have this path open ? */
4173 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4174 fsp1 = file_find_di_first(fileid);
4175 if (fsp1 && fsp1->initial_allocation_size) {
4176 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4180 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4181 mtime_ts = write_time_ts;
4184 if (lp_dos_filetime_resolution(SNUM(conn))) {
4185 dos_filetime_timespec(&create_time_ts);
4186 dos_filetime_timespec(&mtime_ts);
4187 dos_filetime_timespec(&atime_ts);
4190 create_time = convert_timespec_to_time_t(create_time_ts);
4191 mtime = convert_timespec_to_time_t(mtime_ts);
4192 atime = convert_timespec_to_time_t(atime_ts);
4194 /* NT expects the name to be in an exact form of the *full*
4195 filename. See the trans2 torture test */
4196 if (ISDOT(base_name)) {
4197 dos_fname = talloc_strdup(ctx, "\\");
4199 reply_nterror(req, NT_STATUS_NO_MEMORY);
4203 dos_fname = talloc_asprintf(ctx,
4207 reply_nterror(req, NT_STATUS_NO_MEMORY);
4210 string_replace(dos_fname, '/', '\\');
4213 switch (info_level) {
4214 case SMB_INFO_STANDARD:
4215 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4217 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4218 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4219 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4220 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4221 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4222 SSVAL(pdata,l1_attrFile,mode);
4225 case SMB_INFO_QUERY_EA_SIZE:
4227 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4228 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4230 srv_put_dos_date2(pdata,0,create_time);
4231 srv_put_dos_date2(pdata,4,atime);
4232 srv_put_dos_date2(pdata,8,mtime); /* write time */
4233 SIVAL(pdata,12,(uint32)file_size);
4234 SIVAL(pdata,16,(uint32)allocation_size);
4235 SSVAL(pdata,20,mode);
4236 SIVAL(pdata,22,ea_size);
4240 case SMB_INFO_IS_NAME_VALID:
4241 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4242 if (tran_call == TRANSACT2_QFILEINFO) {
4243 /* os/2 needs this ? really ?*/
4244 reply_doserror(req, ERRDOS, ERRbadfunc);
4251 case SMB_INFO_QUERY_EAS_FROM_LIST:
4253 size_t total_ea_len = 0;
4254 struct ea_list *ea_file_list = NULL;
4256 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4258 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4259 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4261 if (!ea_list || (total_ea_len > data_size)) {
4263 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4267 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4271 case SMB_INFO_QUERY_ALL_EAS:
4273 /* We have data_size bytes to put EA's into. */
4274 size_t total_ea_len = 0;
4276 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4278 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4279 if (!ea_list || (total_ea_len > data_size)) {
4281 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4285 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4289 case SMB_FILE_BASIC_INFORMATION:
4290 case SMB_QUERY_FILE_BASIC_INFO:
4292 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4293 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4294 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4296 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4300 put_long_date_timespec(pdata,create_time_ts);
4301 put_long_date_timespec(pdata+8,atime_ts);
4302 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4303 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4304 SIVAL(pdata,32,mode);
4306 DEBUG(5,("SMB_QFBI - "));
4307 DEBUG(5,("create: %s ", ctime(&create_time)));
4308 DEBUG(5,("access: %s ", ctime(&atime)));
4309 DEBUG(5,("write: %s ", ctime(&mtime)));
4310 DEBUG(5,("change: %s ", ctime(&mtime)));
4311 DEBUG(5,("mode: %x\n", mode));
4314 case SMB_FILE_STANDARD_INFORMATION:
4315 case SMB_QUERY_FILE_STANDARD_INFO:
4317 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4319 SOFF_T(pdata,0,allocation_size);
4320 SOFF_T(pdata,8,file_size);
4321 SIVAL(pdata,16,nlink);
4322 SCVAL(pdata,20,delete_pending?1:0);
4323 SCVAL(pdata,21,(mode&aDIR)?1:0);
4324 SSVAL(pdata,22,0); /* Padding. */
4327 case SMB_FILE_EA_INFORMATION:
4328 case SMB_QUERY_FILE_EA_INFO:
4330 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4331 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4333 SIVAL(pdata,0,ea_size);
4337 /* Get the 8.3 name - used if NT SMB was negotiated. */
4338 case SMB_QUERY_FILE_ALT_NAME_INFO:
4339 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4341 char mangled_name[13];
4342 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4343 if (!name_to_8_3(base_name,mangled_name,
4344 True,conn->params)) {
4347 NT_STATUS_NO_MEMORY);
4349 len = srvstr_push(dstart, req->flags2,
4350 pdata+4, mangled_name,
4351 PTR_DIFF(dend, pdata+4),
4353 data_size = 4 + len;
4358 case SMB_QUERY_FILE_NAME_INFO:
4360 this must be *exactly* right for ACLs on mapped drives to work
4362 len = srvstr_push(dstart, req->flags2,
4364 PTR_DIFF(dend, pdata+4),
4366 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4367 data_size = 4 + len;
4371 case SMB_FILE_ALLOCATION_INFORMATION:
4372 case SMB_QUERY_FILE_ALLOCATION_INFO:
4373 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4375 SOFF_T(pdata,0,allocation_size);
4378 case SMB_FILE_END_OF_FILE_INFORMATION:
4379 case SMB_QUERY_FILE_END_OF_FILEINFO:
4380 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4382 SOFF_T(pdata,0,file_size);
4385 case SMB_QUERY_FILE_ALL_INFO:
4386 case SMB_FILE_ALL_INFORMATION:
4388 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4389 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4390 put_long_date_timespec(pdata,create_time_ts);
4391 put_long_date_timespec(pdata+8,atime_ts);
4392 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4393 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4394 SIVAL(pdata,32,mode);
4395 SIVAL(pdata,36,0); /* padding. */
4397 SOFF_T(pdata,0,allocation_size);
4398 SOFF_T(pdata,8,file_size);
4399 SIVAL(pdata,16,nlink);
4400 SCVAL(pdata,20,delete_pending);
4401 SCVAL(pdata,21,(mode&aDIR)?1:0);
4404 SIVAL(pdata,0,ea_size);
4405 pdata += 4; /* EA info */
4406 len = srvstr_push(dstart, req->flags2,
4408 PTR_DIFF(dend, pdata+4),
4412 data_size = PTR_DIFF(pdata,(*ppdata));
4415 case SMB_FILE_INTERNAL_INFORMATION:
4416 /* This should be an index number - looks like
4419 I think this causes us to fail the IFSKIT
4420 BasicFileInformationTest. -tpot */
4422 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4423 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4424 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4428 case SMB_FILE_ACCESS_INFORMATION:
4429 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4431 SIVAL(pdata,0,fsp->access_mask);
4433 /* GENERIC_EXECUTE mapping from Windows */
4434 SIVAL(pdata,0,0x12019F);
4439 case SMB_FILE_NAME_INFORMATION:
4440 /* Pathname with leading '\'. */
4443 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4444 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4445 SIVAL(pdata,0,byte_len);
4446 data_size = 4 + byte_len;
4450 case SMB_FILE_DISPOSITION_INFORMATION:
4451 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4453 SCVAL(pdata,0,delete_pending);
4456 case SMB_FILE_POSITION_INFORMATION:
4457 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4459 SOFF_T(pdata,0,pos);
4462 case SMB_FILE_MODE_INFORMATION:
4463 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4464 SIVAL(pdata,0,mode);
4468 case SMB_FILE_ALIGNMENT_INFORMATION:
4469 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4470 SIVAL(pdata,0,0); /* No alignment needed. */
4475 * NT4 server just returns "invalid query" to this - if we try
4476 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4479 /* The first statement above is false - verified using Thursby
4480 * client against NT4 -- gcolley.
4482 case SMB_QUERY_FILE_STREAM_INFO:
4483 case SMB_FILE_STREAM_INFORMATION: {
4484 unsigned int num_streams;
4485 struct stream_struct *streams;
4488 DEBUG(10,("call_trans2qfilepathinfo: "
4489 "SMB_FILE_STREAM_INFORMATION\n"));
4491 status = SMB_VFS_STREAMINFO(
4492 conn, fsp, fname, talloc_tos(),
4493 &num_streams, &streams);
4495 if (!NT_STATUS_IS_OK(status)) {
4496 DEBUG(10, ("could not get stream info: %s\n",
4497 nt_errstr(status)));
4498 reply_nterror(req, status);
4502 status = marshall_stream_info(num_streams, streams,
4503 pdata, max_data_bytes,
4506 if (!NT_STATUS_IS_OK(status)) {
4507 DEBUG(10, ("marshall_stream_info failed: %s\n",
4508 nt_errstr(status)));
4509 reply_nterror(req, status);
4513 TALLOC_FREE(streams);
4517 case SMB_QUERY_COMPRESSION_INFO:
4518 case SMB_FILE_COMPRESSION_INFORMATION:
4519 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4520 SOFF_T(pdata,0,file_size);
4521 SIVAL(pdata,8,0); /* ??? */
4522 SIVAL(pdata,12,0); /* ??? */
4526 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4527 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4528 put_long_date_timespec(pdata,create_time_ts);
4529 put_long_date_timespec(pdata+8,atime_ts);
4530 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4531 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4532 SOFF_T(pdata,32,allocation_size);
4533 SOFF_T(pdata,40,file_size);
4534 SIVAL(pdata,48,mode);
4535 SIVAL(pdata,52,0); /* ??? */
4539 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4540 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4541 SIVAL(pdata,0,mode);
4547 * CIFS UNIX Extensions.
4550 case SMB_QUERY_FILE_UNIX_BASIC:
4552 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4553 data_size = PTR_DIFF(pdata,(*ppdata));
4557 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4559 for (i=0; i<100; i++)
4560 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4566 case SMB_QUERY_FILE_UNIX_INFO2:
4568 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4569 data_size = PTR_DIFF(pdata,(*ppdata));
4573 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4575 for (i=0; i<100; i++)
4576 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4582 case SMB_QUERY_FILE_UNIX_LINK:
4584 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4587 reply_nterror(req, NT_STATUS_NO_MEMORY);
4591 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4593 if(!S_ISLNK(sbuf.st_mode)) {
4594 reply_unixerror(req, ERRSRV,
4599 reply_unixerror(req, ERRDOS, ERRbadlink);
4602 len = SMB_VFS_READLINK(conn,fullpathname,
4605 reply_unixerror(req, ERRDOS,
4610 len = srvstr_push(dstart, req->flags2,
4612 PTR_DIFF(dend, pdata),
4615 data_size = PTR_DIFF(pdata,(*ppdata));
4620 #if defined(HAVE_POSIX_ACLS)
4621 case SMB_QUERY_POSIX_ACL:
4623 SMB_ACL_T file_acl = NULL;
4624 SMB_ACL_T def_acl = NULL;
4625 uint16 num_file_acls = 0;
4626 uint16 num_def_acls = 0;
4628 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4629 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4631 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4634 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4635 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4639 NT_STATUS_NOT_IMPLEMENTED);
4643 if (S_ISDIR(sbuf.st_mode)) {
4644 if (fsp && fsp->is_directory) {
4645 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4647 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4649 def_acl = free_empty_sys_acl(conn, def_acl);
4652 num_file_acls = count_acl_entries(conn, file_acl);
4653 num_def_acls = count_acl_entries(conn, def_acl);
4655 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4656 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4658 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4659 SMB_POSIX_ACL_HEADER_SIZE) ));
4661 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4664 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4668 NT_STATUS_BUFFER_TOO_SMALL);
4672 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4673 SSVAL(pdata,2,num_file_acls);
4674 SSVAL(pdata,4,num_def_acls);
4675 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4677 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4680 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4683 req, NT_STATUS_INTERNAL_ERROR);
4686 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4688 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4691 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4695 NT_STATUS_INTERNAL_ERROR);
4700 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4703 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4705 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4711 case SMB_QUERY_POSIX_LOCK:
4713 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4717 enum brl_type lock_type;
4719 if (total_data != POSIX_LOCK_DATA_SIZE) {
4721 req, NT_STATUS_INVALID_PARAMETER);
4725 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4726 case POSIX_LOCK_TYPE_READ:
4727 lock_type = READ_LOCK;
4729 case POSIX_LOCK_TYPE_WRITE:
4730 lock_type = WRITE_LOCK;
4732 case POSIX_LOCK_TYPE_UNLOCK:
4734 /* There's no point in asking for an unlock... */
4737 NT_STATUS_INVALID_PARAMETER);
4741 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4742 #if defined(HAVE_LONGLONG)
4743 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4744 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4745 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4746 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4747 #else /* HAVE_LONGLONG */
4748 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4749 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4750 #endif /* HAVE_LONGLONG */
4752 status = query_lock(fsp,
4759 if (ERROR_WAS_LOCK_DENIED(status)) {
4760 /* Here we need to report who has it locked... */
4761 data_size = POSIX_LOCK_DATA_SIZE;
4763 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4764 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4765 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4766 #if defined(HAVE_LONGLONG)
4767 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4768 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4769 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4770 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4771 #else /* HAVE_LONGLONG */
4772 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4773 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4774 #endif /* HAVE_LONGLONG */
4776 } else if (NT_STATUS_IS_OK(status)) {
4777 /* For success we just return a copy of what we sent
4778 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4779 data_size = POSIX_LOCK_DATA_SIZE;
4780 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4781 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4783 reply_nterror(req, status);
4790 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4794 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4800 /****************************************************************************
4801 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4803 ****************************************************************************/
4805 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4806 connection_struct *conn,
4807 const char *oldname_in,
4808 const char *newname_in)
4810 SMB_STRUCT_STAT sbuf1, sbuf2;
4811 char *last_component_oldname = NULL;
4812 char *last_component_newname = NULL;
4813 char *oldname = NULL;
4814 char *newname = NULL;
4815 NTSTATUS status = NT_STATUS_OK;
4820 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4821 &last_component_oldname, &sbuf1);
4822 if (!NT_STATUS_IS_OK(status)) {
4826 status = check_name(conn, oldname);
4827 if (!NT_STATUS_IS_OK(status)) {
4831 /* source must already exist. */
4832 if (!VALID_STAT(sbuf1)) {
4833 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4836 status = unix_convert(ctx, conn, newname_in, False, &newname,
4837 &last_component_newname, &sbuf2);
4838 if (!NT_STATUS_IS_OK(status)) {
4842 status = check_name(conn, newname);
4843 if (!NT_STATUS_IS_OK(status)) {
4847 /* Disallow if newname already exists. */
4848 if (VALID_STAT(sbuf2)) {
4849 return NT_STATUS_OBJECT_NAME_COLLISION;
4852 /* No links from a directory. */
4853 if (S_ISDIR(sbuf1.st_mode)) {
4854 return NT_STATUS_FILE_IS_A_DIRECTORY;
4857 /* Ensure this is within the share. */
4858 status = check_reduced_name(conn, oldname);
4859 if (!NT_STATUS_IS_OK(status)) {
4863 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4865 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4866 status = map_nt_error_from_unix(errno);
4867 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4868 nt_errstr(status), newname, oldname));
4874 /****************************************************************************
4875 Deal with setting the time from any of the setfilepathinfo functions.
4876 ****************************************************************************/
4878 NTSTATUS smb_set_file_time(connection_struct *conn,
4881 const SMB_STRUCT_STAT *psbuf,
4882 struct smb_file_time *ft,
4883 bool setting_write_time)
4886 FILE_NOTIFY_CHANGE_LAST_ACCESS
4887 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4889 if (!VALID_STAT(*psbuf)) {
4890 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4893 /* get some defaults (no modifications) if any info is zero or -1. */
4894 if (null_timespec(ft->atime)) {
4895 ft->atime= get_atimespec(psbuf);
4896 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4899 if (null_timespec(ft->mtime)) {
4900 ft->mtime = get_mtimespec(psbuf);
4901 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4904 if (!setting_write_time) {
4905 /* ft->mtime comes from change time, not write time. */
4906 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4909 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4910 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4911 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4912 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4913 if (!null_timespec(ft->create_time)) {
4914 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4915 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4919 * Try and set the times of this file if
4920 * they are different from the current values.
4924 struct timespec mts = get_mtimespec(psbuf);
4925 struct timespec ats = get_atimespec(psbuf);
4926 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4927 (timespec_compare(&ft->mtime, &mts) == 0)) {
4928 return NT_STATUS_OK;
4932 if (setting_write_time) {
4934 * This was a setfileinfo on an open file.
4935 * NT does this a lot. We also need to
4936 * set the time here, as it can be read by
4937 * FindFirst/FindNext and with the patch for bug #2045
4938 * in smbd/fileio.c it ensures that this timestamp is
4939 * kept sticky even after a write. We save the request
4940 * away and will set it on file close and after a write. JRA.
4943 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4944 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4947 if (fsp->base_fsp) {
4948 set_sticky_write_time_fsp(fsp->base_fsp,
4951 set_sticky_write_time_fsp(fsp, ft->mtime);
4954 set_sticky_write_time_path(conn, fname,
4955 vfs_file_id_from_sbuf(conn, psbuf),
4960 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4962 if (fsp && fsp->base_fsp) {
4963 fname = fsp->base_fsp->fsp_name;
4966 if(file_ntimes(conn, fname, ft)!=0) {
4967 return map_nt_error_from_unix(errno);
4969 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4971 return NT_STATUS_OK;
4974 /****************************************************************************
4975 Deal with setting the dosmode from any of the setfilepathinfo functions.
4976 ****************************************************************************/
4978 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4981 SMB_STRUCT_STAT *psbuf,
4984 if (!VALID_STAT(*psbuf)) {
4985 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4989 if (fsp->base_fsp) {
4990 fname = fsp->base_fsp->fsp_name;
4992 fname = fsp->fsp_name;
4997 if (S_ISDIR(psbuf->st_mode)) {
5004 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5006 /* check the mode isn't different, before changing it */
5007 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5009 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5010 fname, (unsigned int)dosmode ));
5012 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5013 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5014 fname, strerror(errno)));
5015 return map_nt_error_from_unix(errno);
5018 return NT_STATUS_OK;
5021 /****************************************************************************
5022 Deal with setting the size from any of the setfilepathinfo functions.
5023 ****************************************************************************/
5025 static NTSTATUS smb_set_file_size(connection_struct *conn,
5026 struct smb_request *req,
5029 SMB_STRUCT_STAT *psbuf,
5032 NTSTATUS status = NT_STATUS_OK;
5033 files_struct *new_fsp = NULL;
5035 if (!VALID_STAT(*psbuf)) {
5036 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5039 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5041 if (size == get_file_size_stat(psbuf)) {
5042 return NT_STATUS_OK;
5045 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5046 fname, (double)size ));
5048 if (fsp && fsp->fh->fd != -1) {
5049 /* Handle based call. */
5050 if (vfs_set_filelen(fsp, size) == -1) {
5051 return map_nt_error_from_unix(errno);
5053 trigger_write_time_update_immediate(fsp);
5054 return NT_STATUS_OK;
5057 status = SMB_VFS_CREATE_FILE(
5060 0, /* root_dir_fid */
5062 0, /* create_file_flags */
5063 FILE_WRITE_ATTRIBUTES, /* access_mask */
5064 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5066 FILE_OPEN, /* create_disposition*/
5067 0, /* create_options */
5068 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5069 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5070 0, /* allocation_size */
5073 &new_fsp, /* result */
5077 if (!NT_STATUS_IS_OK(status)) {
5078 /* NB. We check for open_was_deferred in the caller. */
5082 if (vfs_set_filelen(new_fsp, size) == -1) {
5083 status = map_nt_error_from_unix(errno);
5084 close_file(req, new_fsp,NORMAL_CLOSE);
5088 trigger_write_time_update_immediate(new_fsp);
5089 close_file(req, new_fsp,NORMAL_CLOSE);
5090 return NT_STATUS_OK;
5093 /****************************************************************************
5094 Deal with SMB_INFO_SET_EA.
5095 ****************************************************************************/
5097 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5103 struct ea_list *ea_list = NULL;
5104 TALLOC_CTX *ctx = NULL;
5105 NTSTATUS status = NT_STATUS_OK;
5107 if (total_data < 10) {
5109 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5110 length. They seem to have no effect. Bug #3212. JRA */
5112 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5113 /* We're done. We only get EA info in this call. */
5114 return NT_STATUS_OK;
5117 return NT_STATUS_INVALID_PARAMETER;
5120 if (IVAL(pdata,0) > total_data) {
5121 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5122 IVAL(pdata,0), (unsigned int)total_data));
5123 return NT_STATUS_INVALID_PARAMETER;
5127 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5129 return NT_STATUS_INVALID_PARAMETER;
5131 status = set_ea(conn, fsp, fname, ea_list);
5136 /****************************************************************************
5137 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5138 ****************************************************************************/
5140 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5145 SMB_STRUCT_STAT *psbuf)
5147 NTSTATUS status = NT_STATUS_OK;
5148 bool delete_on_close;
5151 if (total_data < 1) {
5152 return NT_STATUS_INVALID_PARAMETER;
5156 return NT_STATUS_INVALID_HANDLE;
5159 delete_on_close = (CVAL(pdata,0) ? True : False);
5160 dosmode = dos_mode(conn, fname, psbuf);
5162 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5163 "delete_on_close = %u\n",
5165 (unsigned int)dosmode,
5166 (unsigned int)delete_on_close ));
5168 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5170 if (!NT_STATUS_IS_OK(status)) {
5174 /* The set is across all open files on this dev/inode pair. */
5175 if (!set_delete_on_close(fsp, delete_on_close,
5176 &conn->server_info->utok)) {
5177 return NT_STATUS_ACCESS_DENIED;
5179 return NT_STATUS_OK;
5182 /****************************************************************************
5183 Deal with SMB_FILE_POSITION_INFORMATION.
5184 ****************************************************************************/
5186 static NTSTATUS smb_file_position_information(connection_struct *conn,
5191 uint64_t position_information;
5193 if (total_data < 8) {
5194 return NT_STATUS_INVALID_PARAMETER;
5198 /* Ignore on pathname based set. */
5199 return NT_STATUS_OK;
5202 position_information = (uint64_t)IVAL(pdata,0);
5203 #ifdef LARGE_SMB_OFF_T
5204 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5205 #else /* LARGE_SMB_OFF_T */
5206 if (IVAL(pdata,4) != 0) {
5207 /* more than 32 bits? */
5208 return NT_STATUS_INVALID_PARAMETER;
5210 #endif /* LARGE_SMB_OFF_T */
5212 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5213 fsp->fsp_name, (double)position_information ));
5214 fsp->fh->position_information = position_information;
5215 return NT_STATUS_OK;
5218 /****************************************************************************
5219 Deal with SMB_FILE_MODE_INFORMATION.
5220 ****************************************************************************/
5222 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5228 if (total_data < 4) {
5229 return NT_STATUS_INVALID_PARAMETER;
5231 mode = IVAL(pdata,0);
5232 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5233 return NT_STATUS_INVALID_PARAMETER;
5235 return NT_STATUS_OK;
5238 /****************************************************************************
5239 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5240 ****************************************************************************/
5242 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5243 struct smb_request *req,
5248 char *link_target = NULL;
5249 const char *newname = fname;
5250 NTSTATUS status = NT_STATUS_OK;
5251 TALLOC_CTX *ctx = talloc_tos();
5253 /* Set a symbolic link. */
5254 /* Don't allow this if follow links is false. */
5256 if (total_data == 0) {
5257 return NT_STATUS_INVALID_PARAMETER;
5260 if (!lp_symlinks(SNUM(conn))) {
5261 return NT_STATUS_ACCESS_DENIED;
5264 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5265 total_data, STR_TERMINATE);
5268 return NT_STATUS_INVALID_PARAMETER;
5271 /* !widelinks forces the target path to be within the share. */
5272 /* This means we can interpret the target as a pathname. */
5273 if (!lp_widelinks(SNUM(conn))) {
5274 char *rel_name = NULL;
5275 char *last_dirp = NULL;
5277 if (*link_target == '/') {
5278 /* No absolute paths allowed. */
5279 return NT_STATUS_ACCESS_DENIED;
5281 rel_name = talloc_strdup(ctx,newname);
5283 return NT_STATUS_NO_MEMORY;
5285 last_dirp = strrchr_m(rel_name, '/');
5287 last_dirp[1] = '\0';
5289 rel_name = talloc_strdup(ctx,"./");
5291 return NT_STATUS_NO_MEMORY;
5294 rel_name = talloc_asprintf_append(rel_name,
5298 return NT_STATUS_NO_MEMORY;
5301 status = check_name(conn, rel_name);
5302 if (!NT_STATUS_IS_OK(status)) {
5307 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5308 newname, link_target ));
5310 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5311 return map_nt_error_from_unix(errno);
5314 return NT_STATUS_OK;
5317 /****************************************************************************
5318 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5319 ****************************************************************************/
5321 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5322 struct smb_request *req,
5323 const char *pdata, int total_data,
5326 char *oldname = NULL;
5327 TALLOC_CTX *ctx = talloc_tos();
5328 NTSTATUS status = NT_STATUS_OK;
5330 /* Set a hard link. */
5331 if (total_data == 0) {
5332 return NT_STATUS_INVALID_PARAMETER;
5335 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5336 total_data, STR_TERMINATE, &status);
5337 if (!NT_STATUS_IS_OK(status)) {
5341 status = resolve_dfspath(ctx, conn,
5342 req->flags2 & FLAGS2_DFS_PATHNAMES,
5345 if (!NT_STATUS_IS_OK(status)) {
5349 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5352 return hardlink_internals(ctx, conn, oldname, fname);
5355 /****************************************************************************
5356 Deal with SMB_FILE_RENAME_INFORMATION.
5357 ****************************************************************************/
5359 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5360 struct smb_request *req,
5369 char *newname = NULL;
5370 char *base_name = NULL;
5371 bool dest_has_wcard = False;
5372 SMB_STRUCT_STAT sbuf;
5373 char *newname_last_component = NULL;
5374 NTSTATUS status = NT_STATUS_OK;
5376 TALLOC_CTX *ctx = talloc_tos();
5378 if (total_data < 13) {
5379 return NT_STATUS_INVALID_PARAMETER;
5384 overwrite = (CVAL(pdata,0) ? True : False);
5385 root_fid = IVAL(pdata,4);
5386 len = IVAL(pdata,8);
5388 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5389 return NT_STATUS_INVALID_PARAMETER;
5392 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5395 if (!NT_STATUS_IS_OK(status)) {
5399 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5402 status = resolve_dfspath_wcard(ctx, conn,
5403 req->flags2 & FLAGS2_DFS_PATHNAMES,
5407 if (!NT_STATUS_IS_OK(status)) {
5411 /* Check the new name has no '/' characters. */
5412 if (strchr_m(newname, '/')) {
5413 return NT_STATUS_NOT_SUPPORTED;
5416 if (fsp && fsp->base_fsp) {
5417 /* newname must be a stream name. */
5418 if (newname[0] != ':') {
5419 return NT_STATUS_NOT_SUPPORTED;
5421 base_name = talloc_asprintf(ctx, "%s%s",
5422 fsp->base_fsp->fsp_name,
5425 return NT_STATUS_NO_MEMORY;
5428 /* newname must *not* be a stream name. */
5429 if (is_ntfs_stream_name(newname)) {
5430 return NT_STATUS_NOT_SUPPORTED;
5433 /* Create the base directory. */
5434 base_name = talloc_strdup(ctx, fname);
5436 return NT_STATUS_NO_MEMORY;
5438 p = strrchr_m(base_name, '/');
5442 base_name = talloc_strdup(ctx, "./");
5444 return NT_STATUS_NO_MEMORY;
5447 /* Append the new name. */
5448 base_name = talloc_asprintf_append(base_name,
5452 return NT_STATUS_NO_MEMORY;
5455 status = unix_convert(ctx, conn, newname, False,
5457 &newname_last_component,
5460 /* If an error we expect this to be
5461 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5463 if (!NT_STATUS_IS_OK(status)
5464 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5471 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5472 fsp->fnum, fsp->fsp_name, base_name ));
5473 status = rename_internals_fsp(conn, fsp, base_name,
5474 newname_last_component, 0,
5477 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5478 fname, base_name ));
5479 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5480 overwrite, False, dest_has_wcard,
5481 FILE_WRITE_ATTRIBUTES);
5487 /****************************************************************************
5488 Deal with SMB_SET_POSIX_ACL.
5489 ****************************************************************************/
5491 #if defined(HAVE_POSIX_ACLS)
5492 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5497 SMB_STRUCT_STAT *psbuf)
5499 uint16 posix_acl_version;
5500 uint16 num_file_acls;
5501 uint16 num_def_acls;
5502 bool valid_file_acls = True;
5503 bool valid_def_acls = True;
5505 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5506 return NT_STATUS_INVALID_PARAMETER;
5508 posix_acl_version = SVAL(pdata,0);
5509 num_file_acls = SVAL(pdata,2);
5510 num_def_acls = SVAL(pdata,4);
5512 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5513 valid_file_acls = False;
5517 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5518 valid_def_acls = False;
5522 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5523 return NT_STATUS_INVALID_PARAMETER;
5526 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5527 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5528 return NT_STATUS_INVALID_PARAMETER;
5531 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5532 fname ? fname : fsp->fsp_name,
5533 (unsigned int)num_file_acls,
5534 (unsigned int)num_def_acls));
5536 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5537 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5538 return map_nt_error_from_unix(errno);
5541 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5542 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5543 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5544 return map_nt_error_from_unix(errno);
5546 return NT_STATUS_OK;
5550 /****************************************************************************
5551 Deal with SMB_SET_POSIX_LOCK.
5552 ****************************************************************************/
5554 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5555 struct smb_request *req,
5563 bool blocking_lock = False;
5564 enum brl_type lock_type;
5566 NTSTATUS status = NT_STATUS_OK;
5568 if (fsp == NULL || fsp->fh->fd == -1) {
5569 return NT_STATUS_INVALID_HANDLE;
5572 if (total_data != POSIX_LOCK_DATA_SIZE) {
5573 return NT_STATUS_INVALID_PARAMETER;
5576 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5577 case POSIX_LOCK_TYPE_READ:
5578 lock_type = READ_LOCK;
5580 case POSIX_LOCK_TYPE_WRITE:
5581 /* Return the right POSIX-mappable error code for files opened read-only. */
5582 if (!fsp->can_write) {
5583 return NT_STATUS_INVALID_HANDLE;
5585 lock_type = WRITE_LOCK;
5587 case POSIX_LOCK_TYPE_UNLOCK:
5588 lock_type = UNLOCK_LOCK;
5591 return NT_STATUS_INVALID_PARAMETER;
5594 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5595 blocking_lock = False;
5596 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5597 blocking_lock = True;
5599 return NT_STATUS_INVALID_PARAMETER;
5602 if (!lp_blocking_locks(SNUM(conn))) {
5603 blocking_lock = False;
5606 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5607 #if defined(HAVE_LONGLONG)
5608 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5609 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5610 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5611 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5612 #else /* HAVE_LONGLONG */
5613 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5614 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5615 #endif /* HAVE_LONGLONG */
5617 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5618 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5620 (unsigned int)lock_type,
5621 (unsigned int)lock_pid,
5625 if (lock_type == UNLOCK_LOCK) {
5626 status = do_unlock(smbd_messaging_context(),
5633 uint32 block_smbpid;
5635 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5647 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5649 * A blocking lock was requested. Package up
5650 * this smb into a queued request and push it
5651 * onto the blocking lock queue.
5653 if(push_blocking_lock_request(br_lck,
5656 -1, /* infinite timeout. */
5664 TALLOC_FREE(br_lck);
5668 TALLOC_FREE(br_lck);
5674 /****************************************************************************
5675 Deal with SMB_INFO_STANDARD.
5676 ****************************************************************************/
5678 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5683 const SMB_STRUCT_STAT *psbuf)
5685 struct smb_file_time ft;
5688 if (total_data < 12) {
5689 return NT_STATUS_INVALID_PARAMETER;
5693 ft.create_time = interpret_long_date(pdata);
5696 ft.atime = interpret_long_date(pdata + 8);
5699 ft.mtime = interpret_long_date(pdata + 16);
5701 DEBUG(10,("smb_set_info_standard: file %s\n",
5702 fname ? fname : fsp->fsp_name ));
5704 return smb_set_file_time(conn,
5712 /****************************************************************************
5713 Deal with SMB_SET_FILE_BASIC_INFO.
5714 ****************************************************************************/
5716 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5721 SMB_STRUCT_STAT *psbuf)
5723 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5724 struct timespec write_time;
5725 struct timespec changed_time;
5726 struct smb_file_time ft;
5728 NTSTATUS status = NT_STATUS_OK;
5729 bool setting_write_time = true;
5733 if (total_data < 36) {
5734 return NT_STATUS_INVALID_PARAMETER;
5737 /* Set the attributes */
5738 dosmode = IVAL(pdata,32);
5739 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5740 if (!NT_STATUS_IS_OK(status)) {
5745 ft.atime = interpret_long_date(pdata+8);
5747 write_time = interpret_long_date(pdata+16);
5748 changed_time = interpret_long_date(pdata+24);
5751 ft.mtime = timespec_min(&write_time, &changed_time);
5754 ft.create_time = interpret_long_date(pdata);
5756 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5757 !null_timespec(write_time)) {
5758 ft.mtime = write_time;
5761 /* Prefer a defined time to an undefined one. */
5762 if (null_timespec(ft.mtime)) {
5763 if (null_timespec(write_time)) {
5764 ft.mtime = changed_time;
5765 setting_write_time = false;
5767 ft.mtime = write_time;
5771 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5772 fname ? fname : fsp->fsp_name ));
5774 return smb_set_file_time(conn,
5779 setting_write_time);
5782 /****************************************************************************
5783 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5784 ****************************************************************************/
5786 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5787 struct smb_request *req,
5792 SMB_STRUCT_STAT *psbuf)
5794 uint64_t allocation_size = 0;
5795 NTSTATUS status = NT_STATUS_OK;
5796 files_struct *new_fsp = NULL;
5798 if (!VALID_STAT(*psbuf)) {
5799 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5802 if (total_data < 8) {
5803 return NT_STATUS_INVALID_PARAMETER;
5806 allocation_size = (uint64_t)IVAL(pdata,0);
5807 #ifdef LARGE_SMB_OFF_T
5808 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5809 #else /* LARGE_SMB_OFF_T */
5810 if (IVAL(pdata,4) != 0) {
5811 /* more than 32 bits? */
5812 return NT_STATUS_INVALID_PARAMETER;
5814 #endif /* LARGE_SMB_OFF_T */
5816 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5817 fname, (double)allocation_size ));
5819 if (allocation_size) {
5820 allocation_size = smb_roundup(conn, allocation_size);
5823 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5824 fname, (double)allocation_size ));
5826 if (fsp && fsp->fh->fd != -1) {
5827 /* Open file handle. */
5828 /* Only change if needed. */
5829 if (allocation_size != get_file_size_stat(psbuf)) {
5830 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5831 return map_nt_error_from_unix(errno);
5834 /* But always update the time. */
5836 * This is equivalent to a write. Ensure it's seen immediately
5837 * if there are no pending writes.
5839 trigger_write_time_update_immediate(fsp);
5840 return NT_STATUS_OK;
5843 /* Pathname or stat or directory file. */
5845 status = SMB_VFS_CREATE_FILE(
5848 0, /* root_dir_fid */
5850 0, /* create_file_flags */
5851 FILE_WRITE_DATA, /* access_mask */
5852 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5854 FILE_OPEN, /* create_disposition*/
5855 0, /* create_options */
5856 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5857 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5858 0, /* allocation_size */
5861 &new_fsp, /* result */
5865 if (!NT_STATUS_IS_OK(status)) {
5866 /* NB. We check for open_was_deferred in the caller. */
5870 /* Only change if needed. */
5871 if (allocation_size != get_file_size_stat(psbuf)) {
5872 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5873 status = map_nt_error_from_unix(errno);
5874 close_file(req, new_fsp, NORMAL_CLOSE);
5879 /* Changing the allocation size should set the last mod time. */
5881 * This is equivalent to a write. Ensure it's seen immediately
5882 * if there are no pending writes.
5884 trigger_write_time_update_immediate(new_fsp);
5886 close_file(req, new_fsp, NORMAL_CLOSE);
5887 return NT_STATUS_OK;
5890 /****************************************************************************
5891 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5892 ****************************************************************************/
5894 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5895 struct smb_request *req,
5900 SMB_STRUCT_STAT *psbuf)
5904 if (total_data < 8) {
5905 return NT_STATUS_INVALID_PARAMETER;
5908 size = IVAL(pdata,0);
5909 #ifdef LARGE_SMB_OFF_T
5910 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5911 #else /* LARGE_SMB_OFF_T */
5912 if (IVAL(pdata,4) != 0) {
5913 /* more than 32 bits? */
5914 return NT_STATUS_INVALID_PARAMETER;
5916 #endif /* LARGE_SMB_OFF_T */
5917 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5918 "file %s to %.0f\n", fname, (double)size ));
5920 return smb_set_file_size(conn, req,
5927 /****************************************************************************
5928 Allow a UNIX info mknod.
5929 ****************************************************************************/
5931 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5935 SMB_STRUCT_STAT *psbuf)
5937 uint32 file_type = IVAL(pdata,56);
5938 #if defined(HAVE_MAKEDEV)
5939 uint32 dev_major = IVAL(pdata,60);
5940 uint32 dev_minor = IVAL(pdata,68);
5942 SMB_DEV_T dev = (SMB_DEV_T)0;
5943 uint32 raw_unixmode = IVAL(pdata,84);
5947 if (total_data < 100) {
5948 return NT_STATUS_INVALID_PARAMETER;
5951 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5952 if (!NT_STATUS_IS_OK(status)) {
5956 #if defined(HAVE_MAKEDEV)
5957 dev = makedev(dev_major, dev_minor);
5960 switch (file_type) {
5961 #if defined(S_IFIFO)
5962 case UNIX_TYPE_FIFO:
5963 unixmode |= S_IFIFO;
5966 #if defined(S_IFSOCK)
5967 case UNIX_TYPE_SOCKET:
5968 unixmode |= S_IFSOCK;
5971 #if defined(S_IFCHR)
5972 case UNIX_TYPE_CHARDEV:
5973 unixmode |= S_IFCHR;
5976 #if defined(S_IFBLK)
5977 case UNIX_TYPE_BLKDEV:
5978 unixmode |= S_IFBLK;
5982 return NT_STATUS_INVALID_PARAMETER;
5985 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5986 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5988 /* Ok - do the mknod. */
5989 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5990 return map_nt_error_from_unix(errno);
5993 /* If any of the other "set" calls fail we
5994 * don't want to end up with a half-constructed mknod.
5997 if (lp_inherit_perms(SNUM(conn))) {
5999 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6000 return NT_STATUS_NO_MEMORY;
6002 inherit_access_posix_acl(conn, parent, fname, unixmode);
6003 TALLOC_FREE(parent);
6006 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6007 status = map_nt_error_from_unix(errno);
6008 SMB_VFS_UNLINK(conn,fname);
6011 return NT_STATUS_OK;
6014 /****************************************************************************
6015 Deal with SMB_SET_FILE_UNIX_BASIC.
6016 ****************************************************************************/
6018 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6019 struct smb_request *req,
6024 SMB_STRUCT_STAT *psbuf)
6026 struct smb_file_time ft;
6027 uint32 raw_unixmode;
6030 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6031 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6032 NTSTATUS status = NT_STATUS_OK;
6033 bool delete_on_fail = False;
6034 enum perm_type ptype;
6038 if (total_data < 100) {
6039 return NT_STATUS_INVALID_PARAMETER;
6042 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6043 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6044 size=IVAL(pdata,0); /* first 8 Bytes are size */
6045 #ifdef LARGE_SMB_OFF_T
6046 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6047 #else /* LARGE_SMB_OFF_T */
6048 if (IVAL(pdata,4) != 0) {
6049 /* more than 32 bits? */
6050 return NT_STATUS_INVALID_PARAMETER;
6052 #endif /* LARGE_SMB_OFF_T */
6055 ft.atime = interpret_long_date(pdata+24); /* access_time */
6056 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6057 set_owner = (uid_t)IVAL(pdata,40);
6058 set_grp = (gid_t)IVAL(pdata,48);
6059 raw_unixmode = IVAL(pdata,84);
6061 if (VALID_STAT(*psbuf)) {
6062 if (S_ISDIR(psbuf->st_mode)) {
6063 ptype = PERM_EXISTING_DIR;
6065 ptype = PERM_EXISTING_FILE;
6068 ptype = PERM_NEW_FILE;
6071 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6072 if (!NT_STATUS_IS_OK(status)) {
6076 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6077 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6078 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6080 if (!VALID_STAT(*psbuf)) {
6082 * The only valid use of this is to create character and block
6083 * devices, and named pipes. This is deprecated (IMHO) and
6084 * a new info level should be used for mknod. JRA.
6087 status = smb_unix_mknod(conn,
6092 if (!NT_STATUS_IS_OK(status)) {
6096 /* Ensure we don't try and change anything else. */
6097 raw_unixmode = SMB_MODE_NO_CHANGE;
6098 size = get_file_size_stat(psbuf);
6099 ft.atime = get_atimespec(psbuf);
6100 ft.mtime = get_mtimespec(psbuf);
6102 * We continue here as we might want to change the
6105 delete_on_fail = True;
6109 /* Horrible backwards compatibility hack as an old server bug
6110 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6114 size = get_file_size_stat(psbuf);
6119 * Deal with the UNIX specific mode set.
6122 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6123 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6124 (unsigned int)unixmode, fname ));
6125 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6126 return map_nt_error_from_unix(errno);
6131 * Deal with the UNIX specific uid set.
6134 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6137 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6138 (unsigned int)set_owner, fname ));
6140 if (S_ISLNK(psbuf->st_mode)) {
6141 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6143 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6147 status = map_nt_error_from_unix(errno);
6148 if (delete_on_fail) {
6149 SMB_VFS_UNLINK(conn,fname);
6156 * Deal with the UNIX specific gid set.
6159 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6160 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6161 (unsigned int)set_owner, fname ));
6162 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6163 status = map_nt_error_from_unix(errno);
6164 if (delete_on_fail) {
6165 SMB_VFS_UNLINK(conn,fname);
6171 /* Deal with any size changes. */
6173 status = smb_set_file_size(conn, req,
6178 if (!NT_STATUS_IS_OK(status)) {
6182 /* Deal with any time changes. */
6184 return smb_set_file_time(conn,
6192 /****************************************************************************
6193 Deal with SMB_SET_FILE_UNIX_INFO2.
6194 ****************************************************************************/
6196 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6197 struct smb_request *req,
6202 SMB_STRUCT_STAT *psbuf)
6208 if (total_data < 116) {
6209 return NT_STATUS_INVALID_PARAMETER;
6212 /* Start by setting all the fields that are common between UNIX_BASIC
6215 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6217 if (!NT_STATUS_IS_OK(status)) {
6221 smb_fflags = IVAL(pdata, 108);
6222 smb_fmask = IVAL(pdata, 112);
6224 /* NB: We should only attempt to alter the file flags if the client
6225 * sends a non-zero mask.
6227 if (smb_fmask != 0) {
6228 int stat_fflags = 0;
6230 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6232 /* Client asked to alter a flag we don't understand. */
6233 return NT_STATUS_INVALID_PARAMETER;
6236 if (fsp && fsp->fh->fd != -1) {
6237 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6238 return NT_STATUS_NOT_SUPPORTED;
6240 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6241 return map_nt_error_from_unix(errno);
6246 /* XXX: need to add support for changing the create_time here. You
6247 * can do this for paths on Darwin with setattrlist(2). The right way
6248 * to hook this up is probably by extending the VFS utimes interface.
6251 return NT_STATUS_OK;
6254 /****************************************************************************
6255 Create a directory with POSIX semantics.
6256 ****************************************************************************/
6258 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6259 struct smb_request *req,
6263 SMB_STRUCT_STAT *psbuf,
6264 int *pdata_return_size)
6266 NTSTATUS status = NT_STATUS_OK;
6267 uint32 raw_unixmode = 0;
6268 uint32 mod_unixmode = 0;
6269 mode_t unixmode = (mode_t)0;
6270 files_struct *fsp = NULL;
6271 uint16 info_level_return = 0;
6273 char *pdata = *ppdata;
6275 if (total_data < 18) {
6276 return NT_STATUS_INVALID_PARAMETER;
6279 raw_unixmode = IVAL(pdata,8);
6280 /* Next 4 bytes are not yet defined. */
6282 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6283 if (!NT_STATUS_IS_OK(status)) {
6287 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6289 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6290 fname, (unsigned int)unixmode ));
6292 status = SMB_VFS_CREATE_FILE(
6295 0, /* root_dir_fid */
6297 0, /* create_file_flags */
6298 FILE_READ_ATTRIBUTES, /* access_mask */
6299 FILE_SHARE_NONE, /* share_access */
6300 FILE_CREATE, /* create_disposition*/
6301 FILE_DIRECTORY_FILE, /* create_options */
6302 mod_unixmode, /* file_attributes */
6303 0, /* oplock_request */
6304 0, /* allocation_size */
6311 if (NT_STATUS_IS_OK(status)) {
6312 close_file(req, fsp, NORMAL_CLOSE);
6315 info_level_return = SVAL(pdata,16);
6317 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6318 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6319 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6320 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6322 *pdata_return_size = 12;
6325 /* Realloc the data size */
6326 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6327 if (*ppdata == NULL) {
6328 *pdata_return_size = 0;
6329 return NT_STATUS_NO_MEMORY;
6333 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6334 SSVAL(pdata,2,0); /* No fnum. */
6335 SIVAL(pdata,4,info); /* Was directory created. */
6337 switch (info_level_return) {
6338 case SMB_QUERY_FILE_UNIX_BASIC:
6339 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6340 SSVAL(pdata,10,0); /* Padding. */
6341 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6343 case SMB_QUERY_FILE_UNIX_INFO2:
6344 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6345 SSVAL(pdata,10,0); /* Padding. */
6346 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6349 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6350 SSVAL(pdata,10,0); /* Padding. */
6357 /****************************************************************************
6358 Open/Create a file with POSIX semantics.
6359 ****************************************************************************/
6361 static NTSTATUS smb_posix_open(connection_struct *conn,
6362 struct smb_request *req,
6366 SMB_STRUCT_STAT *psbuf,
6367 int *pdata_return_size)
6369 bool extended_oplock_granted = False;
6370 char *pdata = *ppdata;
6372 uint32 wire_open_mode = 0;
6373 uint32 raw_unixmode = 0;
6374 uint32 mod_unixmode = 0;
6375 uint32 create_disp = 0;
6376 uint32 access_mask = 0;
6377 uint32 create_options = 0;
6378 NTSTATUS status = NT_STATUS_OK;
6379 mode_t unixmode = (mode_t)0;
6380 files_struct *fsp = NULL;
6381 int oplock_request = 0;
6383 uint16 info_level_return = 0;
6385 if (total_data < 18) {
6386 return NT_STATUS_INVALID_PARAMETER;
6389 flags = IVAL(pdata,0);
6390 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6391 if (oplock_request) {
6392 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6395 wire_open_mode = IVAL(pdata,4);
6397 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6398 return smb_posix_mkdir(conn, req,
6406 switch (wire_open_mode & SMB_ACCMODE) {
6408 access_mask = FILE_READ_DATA;
6411 access_mask = FILE_WRITE_DATA;
6414 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6417 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6418 (unsigned int)wire_open_mode ));
6419 return NT_STATUS_INVALID_PARAMETER;
6422 wire_open_mode &= ~SMB_ACCMODE;
6424 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6425 create_disp = FILE_CREATE;
6426 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6427 create_disp = FILE_OVERWRITE_IF;
6428 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6429 create_disp = FILE_OPEN_IF;
6430 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6431 create_disp = FILE_OPEN;
6433 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6434 (unsigned int)wire_open_mode ));
6435 return NT_STATUS_INVALID_PARAMETER;
6438 raw_unixmode = IVAL(pdata,8);
6439 /* Next 4 bytes are not yet defined. */
6441 status = unix_perms_from_wire(conn,
6444 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6447 if (!NT_STATUS_IS_OK(status)) {
6451 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6453 if (wire_open_mode & SMB_O_SYNC) {
6454 create_options |= FILE_WRITE_THROUGH;
6456 if (wire_open_mode & SMB_O_APPEND) {
6457 access_mask |= FILE_APPEND_DATA;
6459 if (wire_open_mode & SMB_O_DIRECT) {
6460 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6463 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6465 (unsigned int)wire_open_mode,
6466 (unsigned int)unixmode ));
6468 status = SMB_VFS_CREATE_FILE(
6471 0, /* root_dir_fid */
6473 0, /* create_file_flags */
6474 access_mask, /* access_mask */
6475 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6477 create_disp, /* create_disposition*/
6478 0, /* create_options */
6479 mod_unixmode, /* file_attributes */
6480 oplock_request, /* oplock_request */
6481 0, /* allocation_size */
6488 if (!NT_STATUS_IS_OK(status)) {
6492 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6493 extended_oplock_granted = True;
6496 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6497 extended_oplock_granted = True;
6500 info_level_return = SVAL(pdata,16);
6502 /* Allocate the correct return size. */
6504 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6505 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6506 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6507 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6509 *pdata_return_size = 12;
6512 /* Realloc the data size */
6513 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6514 if (*ppdata == NULL) {
6515 close_file(req, fsp, ERROR_CLOSE);
6516 *pdata_return_size = 0;
6517 return NT_STATUS_NO_MEMORY;
6521 if (extended_oplock_granted) {
6522 if (flags & REQUEST_BATCH_OPLOCK) {
6523 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6525 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6527 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6528 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6530 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6533 SSVAL(pdata,2,fsp->fnum);
6534 SIVAL(pdata,4,info); /* Was file created etc. */
6536 switch (info_level_return) {
6537 case SMB_QUERY_FILE_UNIX_BASIC:
6538 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6539 SSVAL(pdata,10,0); /* padding. */
6540 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6542 case SMB_QUERY_FILE_UNIX_INFO2:
6543 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6544 SSVAL(pdata,10,0); /* padding. */
6545 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6548 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6549 SSVAL(pdata,10,0); /* padding. */
6552 return NT_STATUS_OK;
6555 /****************************************************************************
6556 Delete a file with POSIX semantics.
6557 ****************************************************************************/
6559 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6560 struct smb_request *req,
6564 SMB_STRUCT_STAT *psbuf)
6566 NTSTATUS status = NT_STATUS_OK;
6567 files_struct *fsp = NULL;
6571 int create_options = 0;
6573 struct share_mode_lock *lck = NULL;
6575 if (total_data < 2) {
6576 return NT_STATUS_INVALID_PARAMETER;
6579 flags = SVAL(pdata,0);
6581 if (!VALID_STAT(*psbuf)) {
6582 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6585 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6586 !VALID_STAT_OF_DIR(*psbuf)) {
6587 return NT_STATUS_NOT_A_DIRECTORY;
6590 DEBUG(10,("smb_posix_unlink: %s %s\n",
6591 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6594 if (VALID_STAT_OF_DIR(*psbuf)) {
6595 create_options |= FILE_DIRECTORY_FILE;
6598 status = SMB_VFS_CREATE_FILE(
6601 0, /* root_dir_fid */
6603 0, /* create_file_flags */
6604 DELETE_ACCESS, /* access_mask */
6605 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6607 FILE_OPEN, /* create_disposition*/
6608 create_options, /* create_options */
6609 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6610 0, /* oplock_request */
6611 0, /* allocation_size */
6618 if (!NT_STATUS_IS_OK(status)) {
6623 * Don't lie to client. If we can't really delete due to
6624 * non-POSIX opens return SHARING_VIOLATION.
6627 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6630 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6631 "lock for file %s\n", fsp->fsp_name));
6632 close_file(req, fsp, NORMAL_CLOSE);
6633 return NT_STATUS_INVALID_PARAMETER;
6637 * See if others still have the file open. If this is the case, then
6638 * don't delete. If all opens are POSIX delete we can set the delete
6639 * on close disposition.
6641 for (i=0; i<lck->num_share_modes; i++) {
6642 struct share_mode_entry *e = &lck->share_modes[i];
6643 if (is_valid_share_mode_entry(e)) {
6644 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6647 /* Fail with sharing violation. */
6648 close_file(req, fsp, NORMAL_CLOSE);
6650 return NT_STATUS_SHARING_VIOLATION;
6655 * Set the delete on close.
6657 status = smb_set_file_disposition_info(conn,
6664 if (!NT_STATUS_IS_OK(status)) {
6665 close_file(req, fsp, NORMAL_CLOSE);
6670 return close_file(req, fsp, NORMAL_CLOSE);
6673 /****************************************************************************
6674 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6675 ****************************************************************************/
6677 static void call_trans2setfilepathinfo(connection_struct *conn,
6678 struct smb_request *req,
6679 unsigned int tran_call,
6680 char **pparams, int total_params,
6681 char **ppdata, int total_data,
6682 unsigned int max_data_bytes)
6684 char *params = *pparams;
6685 char *pdata = *ppdata;
6687 SMB_STRUCT_STAT sbuf;
6689 files_struct *fsp = NULL;
6690 NTSTATUS status = NT_STATUS_OK;
6691 int data_return_size = 0;
6692 TALLOC_CTX *ctx = talloc_tos();
6695 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6701 if (tran_call == TRANSACT2_SETFILEINFO) {
6702 if (total_params < 4) {
6703 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6707 fsp = file_fsp(req, SVAL(params,0));
6708 /* Basic check for non-null fsp. */
6709 if (!check_fsp_open(conn, req, fsp)) {
6712 info_level = SVAL(params,2);
6714 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6716 reply_nterror(req, NT_STATUS_NO_MEMORY);
6720 if(fsp->is_directory || fsp->fh->fd == -1) {
6722 * This is actually a SETFILEINFO on a directory
6723 * handle (returned from an NT SMB). NT5.0 seems
6724 * to do this call. JRA.
6726 if (INFO_LEVEL_IS_UNIX(info_level)) {
6727 /* Always do lstat for UNIX calls. */
6728 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6729 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6730 reply_unixerror(req,ERRDOS,ERRbadpath);
6734 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6735 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6736 reply_unixerror(req,ERRDOS,ERRbadpath);
6740 } else if (fsp->print_file) {
6742 * Doing a DELETE_ON_CLOSE should cancel a print job.
6744 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6745 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6747 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6750 send_trans2_replies(conn, req, params, 2,
6755 reply_unixerror(req, ERRDOS, ERRbadpath);
6760 * Original code - this is an open file.
6762 if (!check_fsp(conn, req, fsp)) {
6766 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6767 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6768 reply_unixerror(req, ERRDOS, ERRbadfid);
6774 if (total_params < 7) {
6775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6779 info_level = SVAL(params,0);
6780 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6781 total_params - 6, STR_TERMINATE,
6783 if (!NT_STATUS_IS_OK(status)) {
6784 reply_nterror(req, status);
6788 status = resolve_dfspath(ctx, conn,
6789 req->flags2 & FLAGS2_DFS_PATHNAMES,
6792 if (!NT_STATUS_IS_OK(status)) {
6793 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6794 reply_botherror(req,
6795 NT_STATUS_PATH_NOT_COVERED,
6796 ERRSRV, ERRbadpath);
6799 reply_nterror(req, status);
6803 status = unix_convert(ctx, conn, fname, False,
6804 &fname, NULL, &sbuf);
6805 if (!NT_STATUS_IS_OK(status)) {
6806 reply_nterror(req, status);
6810 status = check_name(conn, fname);
6811 if (!NT_STATUS_IS_OK(status)) {
6812 reply_nterror(req, status);
6816 if (INFO_LEVEL_IS_UNIX(info_level)) {
6818 * For CIFS UNIX extensions the target name may not exist.
6821 /* Always do lstat for UNIX calls. */
6822 SMB_VFS_LSTAT(conn,fname,&sbuf);
6824 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6825 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6826 reply_unixerror(req, ERRDOS, ERRbadpath);
6831 if (!CAN_WRITE(conn)) {
6832 reply_doserror(req, ERRSRV, ERRaccess);
6836 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6837 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6841 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6842 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6844 /* Realloc the parameter size */
6845 *pparams = (char *)SMB_REALLOC(*pparams,2);
6846 if (*pparams == NULL) {
6847 reply_nterror(req, NT_STATUS_NO_MEMORY);
6854 switch (info_level) {
6856 case SMB_INFO_STANDARD:
6858 status = smb_set_info_standard(conn,
6867 case SMB_INFO_SET_EA:
6869 status = smb_info_set_ea(conn,
6877 case SMB_SET_FILE_BASIC_INFO:
6878 case SMB_FILE_BASIC_INFORMATION:
6880 status = smb_set_file_basic_info(conn,
6889 case SMB_FILE_ALLOCATION_INFORMATION:
6890 case SMB_SET_FILE_ALLOCATION_INFO:
6892 status = smb_set_file_allocation_info(conn, req,
6901 case SMB_FILE_END_OF_FILE_INFORMATION:
6902 case SMB_SET_FILE_END_OF_FILE_INFO:
6904 status = smb_set_file_end_of_file_info(conn, req,
6913 case SMB_FILE_DISPOSITION_INFORMATION:
6914 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6917 /* JRA - We used to just ignore this on a path ?
6918 * Shouldn't this be invalid level on a pathname
6921 if (tran_call != TRANSACT2_SETFILEINFO) {
6922 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6925 status = smb_set_file_disposition_info(conn,
6934 case SMB_FILE_POSITION_INFORMATION:
6936 status = smb_file_position_information(conn,
6943 /* From tridge Samba4 :
6944 * MODE_INFORMATION in setfileinfo (I have no
6945 * idea what "mode information" on a file is - it takes a value of 0,
6946 * 2, 4 or 6. What could it be?).
6949 case SMB_FILE_MODE_INFORMATION:
6951 status = smb_file_mode_information(conn,
6958 * CIFS UNIX extensions.
6961 case SMB_SET_FILE_UNIX_BASIC:
6963 status = smb_set_file_unix_basic(conn, req,
6972 case SMB_SET_FILE_UNIX_INFO2:
6974 status = smb_set_file_unix_info2(conn, req,
6983 case SMB_SET_FILE_UNIX_LINK:
6985 if (tran_call != TRANSACT2_SETPATHINFO) {
6986 /* We must have a pathname for this. */
6987 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6990 status = smb_set_file_unix_link(conn, req, pdata,
6995 case SMB_SET_FILE_UNIX_HLINK:
6997 if (tran_call != TRANSACT2_SETPATHINFO) {
6998 /* We must have a pathname for this. */
6999 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7002 status = smb_set_file_unix_hlink(conn, req,
7008 case SMB_FILE_RENAME_INFORMATION:
7010 status = smb_file_rename_information(conn, req,
7016 #if defined(HAVE_POSIX_ACLS)
7017 case SMB_SET_POSIX_ACL:
7019 status = smb_set_posix_acl(conn,
7029 case SMB_SET_POSIX_LOCK:
7031 if (tran_call != TRANSACT2_SETFILEINFO) {
7032 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7035 status = smb_set_posix_lock(conn, req,
7036 pdata, total_data, fsp);
7040 case SMB_POSIX_PATH_OPEN:
7042 if (tran_call != TRANSACT2_SETPATHINFO) {
7043 /* We must have a pathname for this. */
7044 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7048 status = smb_posix_open(conn, req,
7057 case SMB_POSIX_PATH_UNLINK:
7059 if (tran_call != TRANSACT2_SETPATHINFO) {
7060 /* We must have a pathname for this. */
7061 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7065 status = smb_posix_unlink(conn, req,
7074 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7079 if (!NT_STATUS_IS_OK(status)) {
7080 if (open_was_deferred(req->mid)) {
7081 /* We have re-scheduled this call. */
7084 if (blocking_lock_was_deferred(req->mid)) {
7085 /* We have re-scheduled this call. */
7088 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7089 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7090 ERRSRV, ERRbadpath);
7093 if (info_level == SMB_POSIX_PATH_OPEN) {
7094 reply_openerror(req, status);
7098 reply_nterror(req, status);
7103 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7109 /****************************************************************************
7110 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7111 ****************************************************************************/
7113 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7114 char **pparams, int total_params,
7115 char **ppdata, int total_data,
7116 unsigned int max_data_bytes)
7118 char *params = *pparams;
7119 char *pdata = *ppdata;
7120 char *directory = NULL;
7121 SMB_STRUCT_STAT sbuf;
7122 NTSTATUS status = NT_STATUS_OK;
7123 struct ea_list *ea_list = NULL;
7124 TALLOC_CTX *ctx = talloc_tos();
7126 if (!CAN_WRITE(conn)) {
7127 reply_doserror(req, ERRSRV, ERRaccess);
7131 if (total_params < 5) {
7132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7136 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7137 total_params - 4, STR_TERMINATE,
7139 if (!NT_STATUS_IS_OK(status)) {
7140 reply_nterror(req, status);
7144 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7146 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7147 if (!NT_STATUS_IS_OK(status)) {
7148 reply_nterror(req, status);
7152 status = check_name(conn, directory);
7153 if (!NT_STATUS_IS_OK(status)) {
7154 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7155 reply_nterror(req, status);
7159 /* Any data in this call is an EA list. */
7160 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7161 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7166 * OS/2 workplace shell seems to send SET_EA requests of "null"
7167 * length (4 bytes containing IVAL 4).
7168 * They seem to have no effect. Bug #3212. JRA.
7171 if (total_data != 4) {
7172 if (total_data < 10) {
7173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7177 if (IVAL(pdata,0) > total_data) {
7178 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7179 IVAL(pdata,0), (unsigned int)total_data));
7180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7184 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7191 /* If total_data == 4 Windows doesn't care what values
7192 * are placed in that field, it just ignores them.
7193 * The System i QNTC IBM SMB client puts bad values here,
7194 * so ignore them. */
7196 status = create_directory(conn, req, directory);
7198 if (!NT_STATUS_IS_OK(status)) {
7199 reply_nterror(req, status);
7203 /* Try and set any given EA. */
7205 status = set_ea(conn, NULL, directory, ea_list);
7206 if (!NT_STATUS_IS_OK(status)) {
7207 reply_nterror(req, status);
7212 /* Realloc the parameter and data sizes */
7213 *pparams = (char *)SMB_REALLOC(*pparams,2);
7214 if(*pparams == NULL) {
7215 reply_nterror(req, NT_STATUS_NO_MEMORY);
7222 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7227 /****************************************************************************
7228 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7229 We don't actually do this - we just send a null response.
7230 ****************************************************************************/
7232 static void call_trans2findnotifyfirst(connection_struct *conn,
7233 struct smb_request *req,
7234 char **pparams, int total_params,
7235 char **ppdata, int total_data,
7236 unsigned int max_data_bytes)
7238 char *params = *pparams;
7241 if (total_params < 6) {
7242 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7246 info_level = SVAL(params,4);
7247 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7249 switch (info_level) {
7254 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7258 /* Realloc the parameter and data sizes */
7259 *pparams = (char *)SMB_REALLOC(*pparams,6);
7260 if (*pparams == NULL) {
7261 reply_nterror(req, NT_STATUS_NO_MEMORY);
7266 SSVAL(params,0,fnf_handle);
7267 SSVAL(params,2,0); /* No changes */
7268 SSVAL(params,4,0); /* No EA errors */
7275 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7280 /****************************************************************************
7281 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7282 changes). Currently this does nothing.
7283 ****************************************************************************/
7285 static void call_trans2findnotifynext(connection_struct *conn,
7286 struct smb_request *req,
7287 char **pparams, int total_params,
7288 char **ppdata, int total_data,
7289 unsigned int max_data_bytes)
7291 char *params = *pparams;
7293 DEBUG(3,("call_trans2findnotifynext\n"));
7295 /* Realloc the parameter and data sizes */
7296 *pparams = (char *)SMB_REALLOC(*pparams,4);
7297 if (*pparams == NULL) {
7298 reply_nterror(req, NT_STATUS_NO_MEMORY);
7303 SSVAL(params,0,0); /* No changes */
7304 SSVAL(params,2,0); /* No EA errors */
7306 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7311 /****************************************************************************
7312 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7313 ****************************************************************************/
7315 static void call_trans2getdfsreferral(connection_struct *conn,
7316 struct smb_request *req,
7317 char **pparams, int total_params,
7318 char **ppdata, int total_data,
7319 unsigned int max_data_bytes)
7321 char *params = *pparams;
7322 char *pathname = NULL;
7324 int max_referral_level;
7325 NTSTATUS status = NT_STATUS_OK;
7326 TALLOC_CTX *ctx = talloc_tos();
7328 DEBUG(10,("call_trans2getdfsreferral\n"));
7330 if (total_params < 3) {
7331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7335 max_referral_level = SVAL(params,0);
7337 if(!lp_host_msdfs()) {
7338 reply_doserror(req, ERRDOS, ERRbadfunc);
7342 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7343 total_params - 2, STR_TERMINATE);
7345 reply_nterror(req, NT_STATUS_NOT_FOUND);
7348 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7349 ppdata,&status)) < 0) {
7350 reply_nterror(req, status);
7354 SSVAL(req->inbuf, smb_flg2,
7355 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7356 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7361 #define LMCAT_SPL 0x53
7362 #define LMFUNC_GETJOBID 0x60
7364 /****************************************************************************
7365 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7366 ****************************************************************************/
7368 static void call_trans2ioctl(connection_struct *conn,
7369 struct smb_request *req,
7370 char **pparams, int total_params,
7371 char **ppdata, int total_data,
7372 unsigned int max_data_bytes)
7374 char *pdata = *ppdata;
7375 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7377 /* check for an invalid fid before proceeding */
7380 reply_doserror(req, ERRDOS, ERRbadfid);
7384 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7385 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7386 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7387 if (*ppdata == NULL) {
7388 reply_nterror(req, NT_STATUS_NO_MEMORY);
7393 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7394 CAN ACCEPT THIS IN UNICODE. JRA. */
7396 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7397 srvstr_push(pdata, req->flags2, pdata + 2,
7398 global_myname(), 15,
7399 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7400 srvstr_push(pdata, req->flags2, pdata+18,
7401 lp_servicename(SNUM(conn)), 13,
7402 STR_ASCII|STR_TERMINATE); /* Service name */
7403 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7408 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7409 reply_doserror(req, ERRSRV, ERRerror);
7412 /****************************************************************************
7413 Reply to a SMBfindclose (stop trans2 directory search).
7414 ****************************************************************************/
7416 void reply_findclose(struct smb_request *req)
7420 START_PROFILE(SMBfindclose);
7423 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7424 END_PROFILE(SMBfindclose);
7428 dptr_num = SVALS(req->vwv+0, 0);
7430 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7432 dptr_close(&dptr_num);
7434 reply_outbuf(req, 0, 0);
7436 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7438 END_PROFILE(SMBfindclose);
7442 /****************************************************************************
7443 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7444 ****************************************************************************/
7446 void reply_findnclose(struct smb_request *req)
7450 START_PROFILE(SMBfindnclose);
7453 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7454 END_PROFILE(SMBfindnclose);
7458 dptr_num = SVAL(req->vwv+0, 0);
7460 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7462 /* We never give out valid handles for a
7463 findnotifyfirst - so any dptr_num is ok here.
7466 reply_outbuf(req, 0, 0);
7468 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7470 END_PROFILE(SMBfindnclose);
7474 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7475 struct trans_state *state)
7477 if (Protocol >= PROTOCOL_NT1) {
7478 req->flags2 |= 0x40; /* IS_LONG_NAME */
7479 SSVAL(req->inbuf,smb_flg2,req->flags2);
7482 if (conn->encrypt_level == Required && !req->encrypted) {
7483 if (state->call != TRANSACT2_QFSINFO &&
7484 state->call != TRANSACT2_SETFSINFO) {
7485 DEBUG(0,("handle_trans2: encryption required "
7487 (unsigned int)state->call));
7488 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7493 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7495 /* Now we must call the relevant TRANS2 function */
7496 switch(state->call) {
7497 case TRANSACT2_OPEN:
7499 START_PROFILE(Trans2_open);
7500 call_trans2open(conn, req,
7501 &state->param, state->total_param,
7502 &state->data, state->total_data,
7503 state->max_data_return);
7504 END_PROFILE(Trans2_open);
7508 case TRANSACT2_FINDFIRST:
7510 START_PROFILE(Trans2_findfirst);
7511 call_trans2findfirst(conn, req,
7512 &state->param, state->total_param,
7513 &state->data, state->total_data,
7514 state->max_data_return);
7515 END_PROFILE(Trans2_findfirst);
7519 case TRANSACT2_FINDNEXT:
7521 START_PROFILE(Trans2_findnext);
7522 call_trans2findnext(conn, req,
7523 &state->param, state->total_param,
7524 &state->data, state->total_data,
7525 state->max_data_return);
7526 END_PROFILE(Trans2_findnext);
7530 case TRANSACT2_QFSINFO:
7532 START_PROFILE(Trans2_qfsinfo);
7533 call_trans2qfsinfo(conn, req,
7534 &state->param, state->total_param,
7535 &state->data, state->total_data,
7536 state->max_data_return);
7537 END_PROFILE(Trans2_qfsinfo);
7541 case TRANSACT2_SETFSINFO:
7543 START_PROFILE(Trans2_setfsinfo);
7544 call_trans2setfsinfo(conn, req,
7545 &state->param, state->total_param,
7546 &state->data, state->total_data,
7547 state->max_data_return);
7548 END_PROFILE(Trans2_setfsinfo);
7552 case TRANSACT2_QPATHINFO:
7553 case TRANSACT2_QFILEINFO:
7555 START_PROFILE(Trans2_qpathinfo);
7556 call_trans2qfilepathinfo(conn, req, state->call,
7557 &state->param, state->total_param,
7558 &state->data, state->total_data,
7559 state->max_data_return);
7560 END_PROFILE(Trans2_qpathinfo);
7564 case TRANSACT2_SETPATHINFO:
7565 case TRANSACT2_SETFILEINFO:
7567 START_PROFILE(Trans2_setpathinfo);
7568 call_trans2setfilepathinfo(conn, req, state->call,
7569 &state->param, state->total_param,
7570 &state->data, state->total_data,
7571 state->max_data_return);
7572 END_PROFILE(Trans2_setpathinfo);
7576 case TRANSACT2_FINDNOTIFYFIRST:
7578 START_PROFILE(Trans2_findnotifyfirst);
7579 call_trans2findnotifyfirst(conn, req,
7580 &state->param, state->total_param,
7581 &state->data, state->total_data,
7582 state->max_data_return);
7583 END_PROFILE(Trans2_findnotifyfirst);
7587 case TRANSACT2_FINDNOTIFYNEXT:
7589 START_PROFILE(Trans2_findnotifynext);
7590 call_trans2findnotifynext(conn, req,
7591 &state->param, state->total_param,
7592 &state->data, state->total_data,
7593 state->max_data_return);
7594 END_PROFILE(Trans2_findnotifynext);
7598 case TRANSACT2_MKDIR:
7600 START_PROFILE(Trans2_mkdir);
7601 call_trans2mkdir(conn, req,
7602 &state->param, state->total_param,
7603 &state->data, state->total_data,
7604 state->max_data_return);
7605 END_PROFILE(Trans2_mkdir);
7609 case TRANSACT2_GET_DFS_REFERRAL:
7611 START_PROFILE(Trans2_get_dfs_referral);
7612 call_trans2getdfsreferral(conn, req,
7613 &state->param, state->total_param,
7614 &state->data, state->total_data,
7615 state->max_data_return);
7616 END_PROFILE(Trans2_get_dfs_referral);
7620 case TRANSACT2_IOCTL:
7622 START_PROFILE(Trans2_ioctl);
7623 call_trans2ioctl(conn, req,
7624 &state->param, state->total_param,
7625 &state->data, state->total_data,
7626 state->max_data_return);
7627 END_PROFILE(Trans2_ioctl);
7632 /* Error in request */
7633 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7634 reply_doserror(req, ERRSRV,ERRerror);
7638 /****************************************************************************
7639 Reply to a SMBtrans2.
7640 ****************************************************************************/
7642 void reply_trans2(struct smb_request *req)
7644 connection_struct *conn = req->conn;
7649 unsigned int tran_call;
7650 struct trans_state *state;
7653 START_PROFILE(SMBtrans2);
7655 if (req->wct < 14) {
7656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7657 END_PROFILE(SMBtrans2);
7661 dsoff = SVAL(req->vwv+12, 0);
7662 dscnt = SVAL(req->vwv+11, 0);
7663 psoff = SVAL(req->vwv+10, 0);
7664 pscnt = SVAL(req->vwv+9, 0);
7665 tran_call = SVAL(req->vwv+14, 0);
7667 result = allow_new_trans(conn->pending_trans, req->mid);
7668 if (!NT_STATUS_IS_OK(result)) {
7669 DEBUG(2, ("Got invalid trans2 request: %s\n",
7670 nt_errstr(result)));
7671 reply_nterror(req, result);
7672 END_PROFILE(SMBtrans2);
7677 switch (tran_call) {
7678 /* List the allowed trans2 calls on IPC$ */
7679 case TRANSACT2_OPEN:
7680 case TRANSACT2_GET_DFS_REFERRAL:
7681 case TRANSACT2_QFILEINFO:
7682 case TRANSACT2_QFSINFO:
7683 case TRANSACT2_SETFSINFO:
7686 reply_doserror(req, ERRSRV, ERRaccess);
7687 END_PROFILE(SMBtrans2);
7692 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7693 DEBUG(0, ("talloc failed\n"));
7694 reply_nterror(req, NT_STATUS_NO_MEMORY);
7695 END_PROFILE(SMBtrans2);
7699 state->cmd = SMBtrans2;
7701 state->mid = req->mid;
7702 state->vuid = req->vuid;
7703 state->setup_count = SVAL(req->vwv+13, 0);
7704 state->setup = NULL;
7705 state->total_param = SVAL(req->vwv+0, 0);
7706 state->param = NULL;
7707 state->total_data = SVAL(req->vwv+1, 0);
7709 state->max_param_return = SVAL(req->vwv+2, 0);
7710 state->max_data_return = SVAL(req->vwv+3, 0);
7711 state->max_setup_return = SVAL(req->vwv+4, 0);
7712 state->close_on_completion = BITSETW(req->vwv+5, 0);
7713 state->one_way = BITSETW(req->vwv+5, 1);
7715 state->call = tran_call;
7717 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7718 is so as a sanity check */
7719 if (state->setup_count != 1) {
7721 * Need to have rc=0 for ioctl to get job id for OS/2.
7722 * Network printing will fail if function is not successful.
7723 * Similar function in reply.c will be used if protocol
7724 * is LANMAN1.0 instead of LM1.2X002.
7725 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7726 * outbuf doesn't have to be set(only job id is used).
7728 if ( (state->setup_count == 4)
7729 && (tran_call == TRANSACT2_IOCTL)
7730 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7731 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7732 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7734 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7735 DEBUG(2,("Transaction is %d\n",tran_call));
7737 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7738 END_PROFILE(SMBtrans2);
7743 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7746 if (state->total_data) {
7748 if (trans_oob(state->total_data, 0, dscnt)
7749 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7753 /* Can't use talloc here, the core routines do realloc on the
7754 * params and data. */
7755 state->data = (char *)SMB_MALLOC(state->total_data);
7756 if (state->data == NULL) {
7757 DEBUG(0,("reply_trans2: data malloc fail for %u "
7758 "bytes !\n", (unsigned int)state->total_data));
7760 reply_nterror(req, NT_STATUS_NO_MEMORY);
7761 END_PROFILE(SMBtrans2);
7765 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7768 if (state->total_param) {
7770 if (trans_oob(state->total_param, 0, pscnt)
7771 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7775 /* Can't use talloc here, the core routines do realloc on the
7776 * params and data. */
7777 state->param = (char *)SMB_MALLOC(state->total_param);
7778 if (state->param == NULL) {
7779 DEBUG(0,("reply_trans: param malloc fail for %u "
7780 "bytes !\n", (unsigned int)state->total_param));
7781 SAFE_FREE(state->data);
7783 reply_nterror(req, NT_STATUS_NO_MEMORY);
7784 END_PROFILE(SMBtrans2);
7788 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7791 state->received_data = dscnt;
7792 state->received_param = pscnt;
7794 if ((state->received_param == state->total_param) &&
7795 (state->received_data == state->total_data)) {
7797 handle_trans2(conn, req, state);
7799 SAFE_FREE(state->data);
7800 SAFE_FREE(state->param);
7802 END_PROFILE(SMBtrans2);
7806 DLIST_ADD(conn->pending_trans, state);
7808 /* We need to send an interim response then receive the rest
7809 of the parameter/data bytes */
7810 reply_outbuf(req, 0, 0);
7811 show_msg((char *)req->outbuf);
7812 END_PROFILE(SMBtrans2);
7817 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7818 SAFE_FREE(state->data);
7819 SAFE_FREE(state->param);
7821 END_PROFILE(SMBtrans2);
7822 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7826 /****************************************************************************
7827 Reply to a SMBtranss2
7828 ****************************************************************************/
7830 void reply_transs2(struct smb_request *req)
7832 connection_struct *conn = req->conn;
7833 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7834 struct trans_state *state;
7836 START_PROFILE(SMBtranss2);
7838 show_msg((char *)req->inbuf);
7841 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7842 END_PROFILE(SMBtranss2);
7846 for (state = conn->pending_trans; state != NULL;
7847 state = state->next) {
7848 if (state->mid == req->mid) {
7853 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7855 END_PROFILE(SMBtranss2);
7859 /* Revise state->total_param and state->total_data in case they have
7860 changed downwards */
7862 if (SVAL(req->vwv+0, 0) < state->total_param)
7863 state->total_param = SVAL(req->vwv+0, 0);
7864 if (SVAL(req->vwv+1, 0) < state->total_data)
7865 state->total_data = SVAL(req->vwv+1, 0);
7867 pcnt = SVAL(req->vwv+2, 0);
7868 poff = SVAL(req->vwv+3, 0);
7869 pdisp = SVAL(req->vwv+4, 0);
7871 dcnt = SVAL(req->vwv+5, 0);
7872 doff = SVAL(req->vwv+6, 0);
7873 ddisp = SVAL(req->vwv+7, 0);
7875 state->received_param += pcnt;
7876 state->received_data += dcnt;
7878 if ((state->received_data > state->total_data) ||
7879 (state->received_param > state->total_param))
7883 if (trans_oob(state->total_param, pdisp, pcnt)
7884 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7887 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7891 if (trans_oob(state->total_data, ddisp, dcnt)
7892 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7895 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7898 if ((state->received_param < state->total_param) ||
7899 (state->received_data < state->total_data)) {
7900 END_PROFILE(SMBtranss2);
7904 handle_trans2(conn, req, state);
7906 DLIST_REMOVE(conn->pending_trans, state);
7907 SAFE_FREE(state->data);
7908 SAFE_FREE(state->param);
7911 END_PROFILE(SMBtranss2);
7916 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7917 DLIST_REMOVE(conn->pending_trans, state);
7918 SAFE_FREE(state->data);
7919 SAFE_FREE(state->param);
7921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7922 END_PROFILE(SMBtranss2);