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;
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)) {
1323 continue; /* Error - couldn't mangle. */
1325 fname = talloc_strdup(ctx, mangled_name);
1331 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1332 got_match = mask_match(fname, mask, conn->case_sensitive);
1335 if(!got_match && check_mangled_names &&
1336 !mangle_is_8_3(fname, False, conn->params)) {
1338 * It turns out that NT matches wildcards against
1339 * both long *and* short names. This may explain some
1340 * of the wildcard wierdness from old DOS clients
1341 * that some people have been seeing.... JRA.
1343 /* Force the mangling into 8.3. */
1344 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1346 continue; /* Error - couldn't mangle. */
1349 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1350 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1355 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1357 if (dont_descend && !isdots) {
1364 pathreal = talloc_asprintf(ctx,
1369 pathreal = talloc_asprintf(ctx,
1380 if (INFO_LEVEL_IS_UNIX(info_level)) {
1381 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1382 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1383 pathreal,strerror(errno)));
1384 TALLOC_FREE(pathreal);
1388 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1389 /* Needed to show the msdfs symlinks as
1392 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1394 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1395 pathreal,strerror(errno)));
1396 TALLOC_FREE(pathreal);
1403 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1405 mode = dos_mode(conn,pathreal,&sbuf);
1408 if (!dir_check_ftype(conn,mode,dirtype)) {
1409 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1410 TALLOC_FREE(pathreal);
1415 if (!(mode & aDIR)) {
1416 file_size = get_file_size_stat(&sbuf);
1418 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1420 mdate_ts = get_mtimespec(&sbuf);
1421 adate_ts = get_atimespec(&sbuf);
1422 create_date_ts = get_create_timespec(&sbuf,
1423 lp_fake_dir_create_times(SNUM(conn)));
1425 if (ask_sharemode) {
1426 struct timespec write_time_ts;
1427 struct file_id fileid;
1429 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1430 get_file_infos(fileid, NULL, &write_time_ts);
1431 if (!null_timespec(write_time_ts)) {
1432 mdate_ts = write_time_ts;
1436 if (lp_dos_filetime_resolution(SNUM(conn))) {
1437 dos_filetime_timespec(&create_date_ts);
1438 dos_filetime_timespec(&mdate_ts);
1439 dos_filetime_timespec(&adate_ts);
1442 create_date = convert_timespec_to_time_t(create_date_ts);
1443 mdate = convert_timespec_to_time_t(mdate_ts);
1444 adate = convert_timespec_to_time_t(adate_ts);
1446 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1451 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1461 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1463 switch (info_level) {
1464 case SMB_FIND_INFO_STANDARD:
1465 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1466 if(requires_resume_key) {
1470 srv_put_dos_date2(p,0,create_date);
1471 srv_put_dos_date2(p,4,adate);
1472 srv_put_dos_date2(p,8,mdate);
1473 SIVAL(p,12,(uint32)file_size);
1474 SIVAL(p,16,(uint32)allocation_size);
1478 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1479 p += ucs2_align(base_data, p, 0);
1481 len = srvstr_push(base_data, flags2, p,
1482 fname, PTR_DIFF(end_data, p),
1484 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1486 SCVAL(nameptr, -1, len - 2);
1488 SCVAL(nameptr, -1, 0);
1492 SCVAL(nameptr, -1, len - 1);
1494 SCVAL(nameptr, -1, 0);
1500 case SMB_FIND_EA_SIZE:
1501 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1502 if(requires_resume_key) {
1506 srv_put_dos_date2(p,0,create_date);
1507 srv_put_dos_date2(p,4,adate);
1508 srv_put_dos_date2(p,8,mdate);
1509 SIVAL(p,12,(uint32)file_size);
1510 SIVAL(p,16,(uint32)allocation_size);
1513 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1514 SIVAL(p,22,ea_size); /* Extended attributes */
1518 len = srvstr_push(base_data, flags2,
1519 p, fname, PTR_DIFF(end_data, p),
1520 STR_TERMINATE | STR_NOALIGN);
1521 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1534 SCVAL(nameptr,0,len);
1536 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1539 case SMB_FIND_EA_LIST:
1541 struct ea_list *file_list = NULL;
1544 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1548 if(requires_resume_key) {
1552 srv_put_dos_date2(p,0,create_date);
1553 srv_put_dos_date2(p,4,adate);
1554 srv_put_dos_date2(p,8,mdate);
1555 SIVAL(p,12,(uint32)file_size);
1556 SIVAL(p,16,(uint32)allocation_size);
1558 p += 22; /* p now points to the EA area. */
1560 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1561 name_list = ea_list_union(name_list, file_list, &ea_len);
1563 /* We need to determine if this entry will fit in the space available. */
1564 /* Max string size is 255 bytes. */
1565 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1566 /* Move the dirptr back to prev_dirpos */
1567 dptr_SeekDir(conn->dirptr, prev_dirpos);
1568 *out_of_space = True;
1569 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1570 return False; /* Not finished - just out of space */
1573 /* Push the ea_data followed by the name. */
1574 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1576 len = srvstr_push(base_data, flags2,
1577 p + 1, fname, PTR_DIFF(end_data, p+1),
1578 STR_TERMINATE | STR_NOALIGN);
1579 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1592 SCVAL(nameptr,0,len);
1594 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1598 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1599 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1600 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1602 SIVAL(p,0,reskey); p += 4;
1603 put_long_date_timespec(p,create_date_ts); p += 8;
1604 put_long_date_timespec(p,adate_ts); p += 8;
1605 put_long_date_timespec(p,mdate_ts); p += 8;
1606 put_long_date_timespec(p,mdate_ts); p += 8;
1607 SOFF_T(p,0,file_size); p += 8;
1608 SOFF_T(p,0,allocation_size); p += 8;
1609 SIVAL(p,0,nt_extmode); p += 4;
1610 q = p; p += 4; /* q is placeholder for name length. */
1612 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1613 SIVAL(p,0,ea_size); /* Extended attributes */
1616 /* Clear the short name buffer. This is
1617 * IMPORTANT as not doing so will trigger
1618 * a Win2k client bug. JRA.
1620 if (!was_8_3 && check_mangled_names) {
1621 if (!name_to_8_3(fname,mangled_name,True,
1623 /* Error - mangle failed ! */
1624 memset(mangled_name,'\0',12);
1626 mangled_name[12] = 0;
1627 len = srvstr_push(base_data, flags2,
1628 p+2, mangled_name, 24,
1629 STR_UPPER|STR_UNICODE);
1631 memset(p + 2 + len,'\0',24 - len);
1638 len = srvstr_push(base_data, flags2, p,
1639 fname, PTR_DIFF(end_data, p),
1640 STR_TERMINATE_ASCII);
1643 SIVAL(p,0,0); /* Ensure any padding is null. */
1644 len = PTR_DIFF(p, pdata);
1645 len = (len + 3) & ~3;
1650 case SMB_FIND_FILE_DIRECTORY_INFO:
1651 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1653 SIVAL(p,0,reskey); p += 4;
1654 put_long_date_timespec(p,create_date_ts); p += 8;
1655 put_long_date_timespec(p,adate_ts); p += 8;
1656 put_long_date_timespec(p,mdate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 SOFF_T(p,0,file_size); p += 8;
1659 SOFF_T(p,0,allocation_size); p += 8;
1660 SIVAL(p,0,nt_extmode); p += 4;
1661 len = srvstr_push(base_data, flags2,
1662 p + 4, fname, PTR_DIFF(end_data, p+4),
1663 STR_TERMINATE_ASCII);
1666 SIVAL(p,0,0); /* Ensure any padding is null. */
1667 len = PTR_DIFF(p, pdata);
1668 len = (len + 3) & ~3;
1673 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1674 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1676 SIVAL(p,0,reskey); p += 4;
1677 put_long_date_timespec(p,create_date_ts); p += 8;
1678 put_long_date_timespec(p,adate_ts); p += 8;
1679 put_long_date_timespec(p,mdate_ts); p += 8;
1680 put_long_date_timespec(p,mdate_ts); p += 8;
1681 SOFF_T(p,0,file_size); p += 8;
1682 SOFF_T(p,0,allocation_size); p += 8;
1683 SIVAL(p,0,nt_extmode); p += 4;
1684 q = p; p += 4; /* q is placeholder for name length. */
1686 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1687 SIVAL(p,0,ea_size); /* Extended attributes */
1690 len = srvstr_push(base_data, flags2, p,
1691 fname, PTR_DIFF(end_data, p),
1692 STR_TERMINATE_ASCII);
1696 SIVAL(p,0,0); /* Ensure any padding is null. */
1697 len = PTR_DIFF(p, pdata);
1698 len = (len + 3) & ~3;
1703 case SMB_FIND_FILE_NAMES_INFO:
1704 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1706 SIVAL(p,0,reskey); p += 4;
1708 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1709 acl on a dir (tridge) */
1710 len = srvstr_push(base_data, flags2, p,
1711 fname, PTR_DIFF(end_data, p),
1712 STR_TERMINATE_ASCII);
1715 SIVAL(p,0,0); /* Ensure any padding is null. */
1716 len = PTR_DIFF(p, pdata);
1717 len = (len + 3) & ~3;
1722 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1723 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1725 SIVAL(p,0,reskey); p += 4;
1726 put_long_date_timespec(p,create_date_ts); p += 8;
1727 put_long_date_timespec(p,adate_ts); p += 8;
1728 put_long_date_timespec(p,mdate_ts); p += 8;
1729 put_long_date_timespec(p,mdate_ts); p += 8;
1730 SOFF_T(p,0,file_size); p += 8;
1731 SOFF_T(p,0,allocation_size); p += 8;
1732 SIVAL(p,0,nt_extmode); p += 4;
1733 q = p; p += 4; /* q is placeholder for name length. */
1735 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1736 SIVAL(p,0,ea_size); /* Extended attributes */
1739 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1740 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1741 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1742 len = srvstr_push(base_data, flags2, p,
1743 fname, PTR_DIFF(end_data, p),
1744 STR_TERMINATE_ASCII);
1747 SIVAL(p,0,0); /* Ensure any padding is null. */
1748 len = PTR_DIFF(p, pdata);
1749 len = (len + 3) & ~3;
1754 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1755 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1756 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1758 SIVAL(p,0,reskey); p += 4;
1759 put_long_date_timespec(p,create_date_ts); p += 8;
1760 put_long_date_timespec(p,adate_ts); p += 8;
1761 put_long_date_timespec(p,mdate_ts); p += 8;
1762 put_long_date_timespec(p,mdate_ts); p += 8;
1763 SOFF_T(p,0,file_size); p += 8;
1764 SOFF_T(p,0,allocation_size); p += 8;
1765 SIVAL(p,0,nt_extmode); p += 4;
1766 q = p; p += 4; /* q is placeholder for name length */
1768 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1769 SIVAL(p,0,ea_size); /* Extended attributes */
1772 /* Clear the short name buffer. This is
1773 * IMPORTANT as not doing so will trigger
1774 * a Win2k client bug. JRA.
1776 if (!was_8_3 && check_mangled_names) {
1777 if (!name_to_8_3(fname,mangled_name,True,
1779 /* Error - mangle failed ! */
1780 memset(mangled_name,'\0',12);
1782 mangled_name[12] = 0;
1783 len = srvstr_push(base_data, flags2,
1784 p+2, mangled_name, 24,
1785 STR_UPPER|STR_UNICODE);
1788 memset(p + 2 + len,'\0',24 - len);
1795 SSVAL(p,0,0); p += 2; /* Reserved ? */
1796 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1797 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1798 len = srvstr_push(base_data, flags2, p,
1799 fname, PTR_DIFF(end_data, p),
1800 STR_TERMINATE_ASCII);
1803 SIVAL(p,0,0); /* Ensure any padding is null. */
1804 len = PTR_DIFF(p, pdata);
1805 len = (len + 3) & ~3;
1810 /* CIFS UNIX Extension. */
1812 case SMB_FIND_FILE_UNIX:
1813 case SMB_FIND_FILE_UNIX_INFO2:
1815 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1817 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1819 if (info_level == SMB_FIND_FILE_UNIX) {
1820 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1821 p = store_file_unix_basic(conn, p,
1823 len = srvstr_push(base_data, flags2, p,
1824 fname, PTR_DIFF(end_data, p),
1827 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1828 p = store_file_unix_basic_info2(conn, p,
1832 len = srvstr_push(base_data, flags2, p, fname,
1833 PTR_DIFF(end_data, p), 0);
1834 SIVAL(nameptr, 0, len);
1838 SIVAL(p,0,0); /* Ensure any padding is null. */
1840 len = PTR_DIFF(p, pdata);
1841 len = (len + 3) & ~3;
1842 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1844 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1854 if (PTR_DIFF(p,pdata) > space_remaining) {
1855 /* Move the dirptr back to prev_dirpos */
1856 dptr_SeekDir(conn->dirptr, prev_dirpos);
1857 *out_of_space = True;
1858 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1859 return False; /* Not finished - just out of space */
1862 /* Setup the last entry pointer, as an offset from base_data */
1863 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1864 /* Advance the data pointer to the next slot */
1870 /****************************************************************************
1871 Reply to a TRANS2_FINDFIRST.
1872 ****************************************************************************/
1874 static void call_trans2findfirst(connection_struct *conn,
1875 struct smb_request *req,
1876 char **pparams, int total_params,
1877 char **ppdata, int total_data,
1878 unsigned int max_data_bytes)
1880 /* We must be careful here that we don't return more than the
1881 allowed number of data bytes. If this means returning fewer than
1882 maxentries then so be it. We assume that the redirector has
1883 enough room for the fixed number of parameter bytes it has
1885 char *params = *pparams;
1886 char *pdata = *ppdata;
1890 uint16 findfirst_flags;
1891 bool close_after_first;
1893 bool requires_resume_key;
1895 char *directory = NULL;
1898 int last_entry_off=0;
1902 bool finished = False;
1903 bool dont_descend = False;
1904 bool out_of_space = False;
1905 int space_remaining;
1906 bool mask_contains_wcard = False;
1907 SMB_STRUCT_STAT sbuf;
1908 struct ea_list *ea_list = NULL;
1909 NTSTATUS ntstatus = NT_STATUS_OK;
1910 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1911 TALLOC_CTX *ctx = talloc_tos();
1913 if (total_params < 13) {
1914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1918 dirtype = SVAL(params,0);
1919 maxentries = SVAL(params,2);
1920 findfirst_flags = SVAL(params,4);
1921 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1922 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1923 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1924 info_level = SVAL(params,6);
1926 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1927 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1928 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1929 info_level, max_data_bytes));
1932 /* W2K3 seems to treat zero as 1. */
1936 switch (info_level) {
1937 case SMB_FIND_INFO_STANDARD:
1938 case SMB_FIND_EA_SIZE:
1939 case SMB_FIND_EA_LIST:
1940 case SMB_FIND_FILE_DIRECTORY_INFO:
1941 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1942 case SMB_FIND_FILE_NAMES_INFO:
1943 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1944 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1945 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1947 case SMB_FIND_FILE_UNIX:
1948 case SMB_FIND_FILE_UNIX_INFO2:
1949 /* Always use filesystem for UNIX mtime query. */
1950 ask_sharemode = false;
1951 if (!lp_unix_extensions()) {
1952 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1957 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1961 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1962 params+12, total_params - 12,
1963 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1964 if (!NT_STATUS_IS_OK(ntstatus)) {
1965 reply_nterror(req, ntstatus);
1969 ntstatus = resolve_dfspath_wcard(ctx, conn,
1970 req->flags2 & FLAGS2_DFS_PATHNAMES,
1973 &mask_contains_wcard);
1974 if (!NT_STATUS_IS_OK(ntstatus)) {
1975 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1976 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1977 ERRSRV, ERRbadpath);
1980 reply_nterror(req, ntstatus);
1984 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1985 if (!NT_STATUS_IS_OK(ntstatus)) {
1986 reply_nterror(req, ntstatus);
1990 ntstatus = check_name(conn, directory);
1991 if (!NT_STATUS_IS_OK(ntstatus)) {
1992 reply_nterror(req, ntstatus);
1996 p = strrchr_m(directory,'/');
1998 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1999 if((directory[0] == '.') && (directory[1] == '\0')) {
2000 mask = talloc_strdup(ctx,"*");
2002 reply_nterror(req, NT_STATUS_NO_MEMORY);
2005 mask_contains_wcard = True;
2007 directory = talloc_strdup(talloc_tos(), "./");
2009 reply_nterror(req, NT_STATUS_NO_MEMORY);
2016 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2018 if (info_level == SMB_FIND_EA_LIST) {
2021 if (total_data < 4) {
2022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2026 ea_size = IVAL(pdata,0);
2027 if (ea_size != total_data) {
2028 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2029 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2034 if (!lp_ea_support(SNUM(conn))) {
2035 reply_doserror(req, ERRDOS, ERReasnotsupported);
2039 /* Pull out the list of names. */
2040 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2047 *ppdata = (char *)SMB_REALLOC(
2048 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2049 if(*ppdata == NULL ) {
2050 reply_nterror(req, NT_STATUS_NO_MEMORY);
2054 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2056 /* Realloc the params space */
2057 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2058 if (*pparams == NULL) {
2059 reply_nterror(req, NT_STATUS_NO_MEMORY);
2064 /* Save the wildcard match and attribs we are using on this directory -
2065 needed as lanman2 assumes these are being saved between calls */
2067 ntstatus = dptr_create(conn,
2073 mask_contains_wcard,
2077 if (!NT_STATUS_IS_OK(ntstatus)) {
2078 reply_nterror(req, ntstatus);
2082 dptr_num = dptr_dnum(conn->dirptr);
2083 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2085 /* Initialize per TRANS2_FIND_FIRST operation data */
2086 dptr_init_search_op(conn->dirptr);
2088 /* We don't need to check for VOL here as this is returned by
2089 a different TRANS2 call. */
2091 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2092 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2093 dont_descend = True;
2096 space_remaining = max_data_bytes;
2097 out_of_space = False;
2099 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2100 bool got_exact_match = False;
2102 /* this is a heuristic to avoid seeking the dirptr except when
2103 absolutely necessary. It allows for a filename of about 40 chars */
2104 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2105 out_of_space = True;
2108 finished = !get_lanman2_dir_entry(ctx,
2111 mask,dirtype,info_level,
2112 requires_resume_key,dont_descend,
2115 space_remaining, &out_of_space,
2117 &last_entry_off, ea_list);
2120 if (finished && out_of_space)
2123 if (!finished && !out_of_space)
2127 * As an optimisation if we know we aren't looking
2128 * for a wildcard name (ie. the name matches the wildcard exactly)
2129 * then we can finish on any (first) match.
2130 * This speeds up large directory searches. JRA.
2136 /* Ensure space_remaining never goes -ve. */
2137 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2138 space_remaining = 0;
2139 out_of_space = true;
2141 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2145 /* Check if we can close the dirptr */
2146 if(close_after_first || (finished && close_if_end)) {
2147 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2148 dptr_close(&dptr_num);
2152 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2153 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2154 * the protocol level is less than NT1. Tested with smbclient. JRA.
2155 * This should fix the OS/2 client bug #2335.
2158 if(numentries == 0) {
2159 dptr_close(&dptr_num);
2160 if (Protocol < PROTOCOL_NT1) {
2161 reply_doserror(req, ERRDOS, ERRnofiles);
2164 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2165 ERRDOS, ERRbadfile);
2170 /* At this point pdata points to numentries directory entries. */
2172 /* Set up the return parameter block */
2173 SSVAL(params,0,dptr_num);
2174 SSVAL(params,2,numentries);
2175 SSVAL(params,4,finished);
2176 SSVAL(params,6,0); /* Never an EA error */
2177 SSVAL(params,8,last_entry_off);
2179 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2182 if ((! *directory) && dptr_path(dptr_num)) {
2183 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2185 reply_nterror(req, NT_STATUS_NO_MEMORY);
2189 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2190 smb_fn_name(req->cmd),
2191 mask, directory, dirtype, numentries ) );
2194 * Force a name mangle here to ensure that the
2195 * mask as an 8.3 name is top of the mangled cache.
2196 * The reasons for this are subtle. Don't remove
2197 * this code unless you know what you are doing
2198 * (see PR#13758). JRA.
2201 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2202 char mangled_name[13];
2203 name_to_8_3(mask, mangled_name, True, conn->params);
2209 /****************************************************************************
2210 Reply to a TRANS2_FINDNEXT.
2211 ****************************************************************************/
2213 static void call_trans2findnext(connection_struct *conn,
2214 struct smb_request *req,
2215 char **pparams, int total_params,
2216 char **ppdata, int total_data,
2217 unsigned int max_data_bytes)
2219 /* We must be careful here that we don't return more than the
2220 allowed number of data bytes. If this means returning fewer than
2221 maxentries then so be it. We assume that the redirector has
2222 enough room for the fixed number of parameter bytes it has
2224 char *params = *pparams;
2225 char *pdata = *ppdata;
2231 uint16 findnext_flags;
2232 bool close_after_request;
2234 bool requires_resume_key;
2236 bool mask_contains_wcard = False;
2237 char *resume_name = NULL;
2238 const char *mask = NULL;
2239 const char *directory = NULL;
2243 int i, last_entry_off=0;
2244 bool finished = False;
2245 bool dont_descend = False;
2246 bool out_of_space = False;
2247 int space_remaining;
2248 struct ea_list *ea_list = NULL;
2249 NTSTATUS ntstatus = NT_STATUS_OK;
2250 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2251 TALLOC_CTX *ctx = talloc_tos();
2253 if (total_params < 13) {
2254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2258 dptr_num = SVAL(params,0);
2259 maxentries = SVAL(params,2);
2260 info_level = SVAL(params,4);
2261 resume_key = IVAL(params,6);
2262 findnext_flags = SVAL(params,10);
2263 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2264 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2265 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2266 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2268 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2270 total_params - 12, STR_TERMINATE, &ntstatus,
2271 &mask_contains_wcard);
2272 if (!NT_STATUS_IS_OK(ntstatus)) {
2273 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2274 complain (it thinks we're asking for the directory above the shared
2275 path or an invalid name). Catch this as the resume name is only compared, never used in
2276 a file access. JRA. */
2277 srvstr_pull_talloc(ctx, params, req->flags2,
2278 &resume_name, params+12,
2282 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2283 reply_nterror(req, ntstatus);
2288 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2289 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2290 resume_key = %d resume name = %s continue=%d level = %d\n",
2291 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2292 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2295 /* W2K3 seems to treat zero as 1. */
2299 switch (info_level) {
2300 case SMB_FIND_INFO_STANDARD:
2301 case SMB_FIND_EA_SIZE:
2302 case SMB_FIND_EA_LIST:
2303 case SMB_FIND_FILE_DIRECTORY_INFO:
2304 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2305 case SMB_FIND_FILE_NAMES_INFO:
2306 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2307 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2308 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2310 case SMB_FIND_FILE_UNIX:
2311 case SMB_FIND_FILE_UNIX_INFO2:
2312 /* Always use filesystem for UNIX mtime query. */
2313 ask_sharemode = false;
2314 if (!lp_unix_extensions()) {
2315 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2320 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2324 if (info_level == SMB_FIND_EA_LIST) {
2327 if (total_data < 4) {
2328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2332 ea_size = IVAL(pdata,0);
2333 if (ea_size != total_data) {
2334 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2335 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2340 if (!lp_ea_support(SNUM(conn))) {
2341 reply_doserror(req, ERRDOS, ERReasnotsupported);
2345 /* Pull out the list of names. */
2346 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2353 *ppdata = (char *)SMB_REALLOC(
2354 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2355 if(*ppdata == NULL) {
2356 reply_nterror(req, NT_STATUS_NO_MEMORY);
2361 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2363 /* Realloc the params space */
2364 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2365 if(*pparams == NULL ) {
2366 reply_nterror(req, NT_STATUS_NO_MEMORY);
2372 /* Check that the dptr is valid */
2373 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2374 reply_doserror(req, ERRDOS, ERRnofiles);
2378 string_set(&conn->dirpath,dptr_path(dptr_num));
2380 /* Get the wildcard mask from the dptr */
2381 if((p = dptr_wcard(dptr_num))== NULL) {
2382 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2383 reply_doserror(req, ERRDOS, ERRnofiles);
2388 directory = conn->dirpath;
2390 /* Get the attr mask from the dptr */
2391 dirtype = dptr_attr(dptr_num);
2393 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2394 dptr_num, mask, dirtype,
2396 dptr_TellDir(conn->dirptr)));
2398 /* Initialize per TRANS2_FIND_NEXT operation data */
2399 dptr_init_search_op(conn->dirptr);
2401 /* We don't need to check for VOL here as this is returned by
2402 a different TRANS2 call. */
2404 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2405 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2406 dont_descend = True;
2409 space_remaining = max_data_bytes;
2410 out_of_space = False;
2413 * Seek to the correct position. We no longer use the resume key but
2414 * depend on the last file name instead.
2417 if(*resume_name && !continue_bit) {
2420 long current_pos = 0;
2422 * Remember, name_to_8_3 is called by
2423 * get_lanman2_dir_entry(), so the resume name
2424 * could be mangled. Ensure we check the unmangled name.
2427 if (mangle_is_mangled(resume_name, conn->params)) {
2428 char *new_resume_name = NULL;
2429 mangle_lookup_name_from_8_3(ctx,
2433 if (new_resume_name) {
2434 resume_name = new_resume_name;
2439 * Fix for NT redirector problem triggered by resume key indexes
2440 * changing between directory scans. We now return a resume key of 0
2441 * and instead look for the filename to continue from (also given
2442 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2443 * findfirst/findnext (as is usual) then the directory pointer
2444 * should already be at the correct place.
2447 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2448 } /* end if resume_name && !continue_bit */
2450 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2451 bool got_exact_match = False;
2453 /* this is a heuristic to avoid seeking the dirptr except when
2454 absolutely necessary. It allows for a filename of about 40 chars */
2455 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2456 out_of_space = True;
2459 finished = !get_lanman2_dir_entry(ctx,
2462 mask,dirtype,info_level,
2463 requires_resume_key,dont_descend,
2466 space_remaining, &out_of_space,
2468 &last_entry_off, ea_list);
2471 if (finished && out_of_space)
2474 if (!finished && !out_of_space)
2478 * As an optimisation if we know we aren't looking
2479 * for a wildcard name (ie. the name matches the wildcard exactly)
2480 * then we can finish on any (first) match.
2481 * This speeds up large directory searches. JRA.
2487 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2490 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2491 smb_fn_name(req->cmd),
2492 mask, directory, dirtype, numentries ) );
2494 /* Check if we can close the dirptr */
2495 if(close_after_request || (finished && close_if_end)) {
2496 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2497 dptr_close(&dptr_num); /* This frees up the saved mask */
2500 /* Set up the return parameter block */
2501 SSVAL(params,0,numentries);
2502 SSVAL(params,2,finished);
2503 SSVAL(params,4,0); /* Never an EA error */
2504 SSVAL(params,6,last_entry_off);
2506 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2512 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2514 E_md4hash(lp_servicename(SNUM(conn)),objid);
2518 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2520 SMB_ASSERT(extended_info != NULL);
2522 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2523 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2524 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2525 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2526 #ifdef SAMBA_VERSION_REVISION
2527 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2529 extended_info->samba_subversion = 0;
2530 #ifdef SAMBA_VERSION_RC_RELEASE
2531 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2533 #ifdef SAMBA_VERSION_PRE_RELEASE
2534 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2537 #ifdef SAMBA_VERSION_VENDOR_PATCH
2538 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2540 extended_info->samba_gitcommitdate = 0;
2541 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2542 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2545 memset(extended_info->samba_version_string, 0,
2546 sizeof(extended_info->samba_version_string));
2548 snprintf (extended_info->samba_version_string,
2549 sizeof(extended_info->samba_version_string),
2550 "%s", samba_version_string());
2553 /****************************************************************************
2554 Reply to a TRANS2_QFSINFO (query filesystem info).
2555 ****************************************************************************/
2557 static void call_trans2qfsinfo(connection_struct *conn,
2558 struct smb_request *req,
2559 char **pparams, int total_params,
2560 char **ppdata, int total_data,
2561 unsigned int max_data_bytes)
2563 char *pdata, *end_data;
2564 char *params = *pparams;
2568 const char *vname = volume_label(SNUM(conn));
2569 int snum = SNUM(conn);
2570 char *fstype = lp_fstype(SNUM(conn));
2571 uint32 additional_flags = 0;
2573 if (total_params < 2) {
2574 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2578 info_level = SVAL(params,0);
2581 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2582 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2583 "info level (0x%x) on IPC$.\n",
2584 (unsigned int)info_level));
2585 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2590 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2591 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2592 DEBUG(0,("call_trans2qfsinfo: encryption required "
2593 "and info level 0x%x sent.\n",
2594 (unsigned int)info_level));
2595 exit_server_cleanly("encryption required "
2601 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2603 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2604 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2605 reply_doserror(req, ERRSRV, ERRinvdevice);
2609 *ppdata = (char *)SMB_REALLOC(
2610 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2611 if (*ppdata == NULL ) {
2612 reply_nterror(req, NT_STATUS_NO_MEMORY);
2617 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2618 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2620 switch (info_level) {
2621 case SMB_INFO_ALLOCATION:
2623 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2625 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2626 reply_unixerror(req, ERRHRD, ERRgeneral);
2630 block_size = lp_block_size(snum);
2631 if (bsize < block_size) {
2632 uint64_t factor = block_size/bsize;
2637 if (bsize > block_size) {
2638 uint64_t factor = bsize/block_size;
2643 bytes_per_sector = 512;
2644 sectors_per_unit = bsize/bytes_per_sector;
2646 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2647 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2648 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2650 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2651 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2652 SIVAL(pdata,l1_cUnit,dsize);
2653 SIVAL(pdata,l1_cUnitAvail,dfree);
2654 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2658 case SMB_INFO_VOLUME:
2659 /* Return volume name */
2661 * Add volume serial number - hash of a combination of
2662 * the called hostname and the service name.
2664 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2666 * Win2k3 and previous mess this up by sending a name length
2667 * one byte short. I believe only older clients (OS/2 Win9x) use
2668 * this call so try fixing this by adding a terminating null to
2669 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2673 pdata+l2_vol_szVolLabel, vname,
2674 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2675 STR_NOALIGN|STR_TERMINATE);
2676 SCVAL(pdata,l2_vol_cch,len);
2677 data_len = l2_vol_szVolLabel + len;
2678 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2679 (unsigned)st.st_ctime, len, vname));
2682 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2683 case SMB_FS_ATTRIBUTE_INFORMATION:
2685 additional_flags = 0;
2686 #if defined(HAVE_SYS_QUOTAS)
2687 additional_flags |= FILE_VOLUME_QUOTAS;
2690 if(lp_nt_acl_support(SNUM(conn))) {
2691 additional_flags |= FILE_PERSISTENT_ACLS;
2694 /* Capabilities are filled in at connection time through STATVFS call */
2695 additional_flags |= conn->fs_capabilities;
2697 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2698 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2699 additional_flags); /* FS ATTRIBUTES */
2701 SIVAL(pdata,4,255); /* Max filename component length */
2702 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2703 and will think we can't do long filenames */
2704 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2705 PTR_DIFF(end_data, pdata+12),
2708 data_len = 12 + len;
2711 case SMB_QUERY_FS_LABEL_INFO:
2712 case SMB_FS_LABEL_INFORMATION:
2713 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2714 PTR_DIFF(end_data, pdata+4), 0);
2719 case SMB_QUERY_FS_VOLUME_INFO:
2720 case SMB_FS_VOLUME_INFORMATION:
2723 * Add volume serial number - hash of a combination of
2724 * the called hostname and the service name.
2726 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2727 (str_checksum(get_local_machine_name())<<16));
2729 /* Max label len is 32 characters. */
2730 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2731 PTR_DIFF(end_data, pdata+18),
2733 SIVAL(pdata,12,len);
2736 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2737 (int)strlen(vname),vname, lp_servicename(snum)));
2740 case SMB_QUERY_FS_SIZE_INFO:
2741 case SMB_FS_SIZE_INFORMATION:
2743 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2745 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2746 reply_unixerror(req, ERRHRD, ERRgeneral);
2749 block_size = lp_block_size(snum);
2750 if (bsize < block_size) {
2751 uint64_t factor = block_size/bsize;
2756 if (bsize > block_size) {
2757 uint64_t factor = bsize/block_size;
2762 bytes_per_sector = 512;
2763 sectors_per_unit = bsize/bytes_per_sector;
2764 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2765 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2766 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2767 SBIG_UINT(pdata,0,dsize);
2768 SBIG_UINT(pdata,8,dfree);
2769 SIVAL(pdata,16,sectors_per_unit);
2770 SIVAL(pdata,20,bytes_per_sector);
2774 case SMB_FS_FULL_SIZE_INFORMATION:
2776 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2778 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2779 reply_unixerror(req, ERRHRD, ERRgeneral);
2782 block_size = lp_block_size(snum);
2783 if (bsize < block_size) {
2784 uint64_t factor = block_size/bsize;
2789 if (bsize > block_size) {
2790 uint64_t factor = bsize/block_size;
2795 bytes_per_sector = 512;
2796 sectors_per_unit = bsize/bytes_per_sector;
2797 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2798 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2799 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2800 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2801 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2802 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2803 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2804 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2808 case SMB_QUERY_FS_DEVICE_INFO:
2809 case SMB_FS_DEVICE_INFORMATION:
2811 SIVAL(pdata,0,0); /* dev type */
2812 SIVAL(pdata,4,0); /* characteristics */
2815 #ifdef HAVE_SYS_QUOTAS
2816 case SMB_FS_QUOTA_INFORMATION:
2818 * what we have to send --metze:
2820 * Unknown1: 24 NULL bytes
2821 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2822 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2823 * Quota Flags: 2 byte :
2824 * Unknown3: 6 NULL bytes
2828 * details for Quota Flags:
2830 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2831 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2832 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2833 * 0x0001 Enable Quotas: enable quota for this fs
2837 /* we need to fake up a fsp here,
2838 * because its not send in this call
2841 SMB_NTQUOTA_STRUCT quotas;
2844 ZERO_STRUCT(quotas);
2850 if (conn->server_info->utok.uid != 0) {
2851 DEBUG(0,("set_user_quota: access_denied "
2852 "service [%s] user [%s]\n",
2853 lp_servicename(SNUM(conn)),
2854 conn->server_info->unix_name));
2855 reply_doserror(req, ERRDOS, ERRnoaccess);
2859 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2860 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2861 reply_doserror(req, ERRSRV, ERRerror);
2867 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2869 /* Unknown1 24 NULL bytes*/
2870 SBIG_UINT(pdata,0,(uint64_t)0);
2871 SBIG_UINT(pdata,8,(uint64_t)0);
2872 SBIG_UINT(pdata,16,(uint64_t)0);
2874 /* Default Soft Quota 8 bytes */
2875 SBIG_UINT(pdata,24,quotas.softlim);
2877 /* Default Hard Quota 8 bytes */
2878 SBIG_UINT(pdata,32,quotas.hardlim);
2880 /* Quota flag 2 bytes */
2881 SSVAL(pdata,40,quotas.qflags);
2883 /* Unknown3 6 NULL bytes */
2889 #endif /* HAVE_SYS_QUOTAS */
2890 case SMB_FS_OBJECTID_INFORMATION:
2892 unsigned char objid[16];
2893 struct smb_extended_info extended_info;
2894 memcpy(pdata,create_volume_objectid(conn, objid),16);
2895 samba_extended_info_version (&extended_info);
2896 SIVAL(pdata,16,extended_info.samba_magic);
2897 SIVAL(pdata,20,extended_info.samba_version);
2898 SIVAL(pdata,24,extended_info.samba_subversion);
2899 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2900 memcpy(pdata+36,extended_info.samba_version_string,28);
2906 * Query the version and capabilities of the CIFS UNIX extensions
2910 case SMB_QUERY_CIFS_UNIX_INFO:
2912 bool large_write = lp_min_receive_file_size() &&
2913 !srv_is_signing_active(smbd_server_conn);
2914 bool large_read = !srv_is_signing_active(smbd_server_conn);
2915 int encrypt_caps = 0;
2917 if (!lp_unix_extensions()) {
2918 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2922 switch (conn->encrypt_level) {
2928 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2931 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2932 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2933 large_write = false;
2939 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2940 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2942 /* We have POSIX ACLs, pathname, encryption,
2943 * large read/write, and locking capability. */
2945 SBIG_UINT(pdata,4,((uint64_t)(
2946 CIFS_UNIX_POSIX_ACLS_CAP|
2947 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2948 CIFS_UNIX_FCNTL_LOCKS_CAP|
2949 CIFS_UNIX_EXTATTR_CAP|
2950 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2952 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2954 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2958 case SMB_QUERY_POSIX_FS_INFO:
2961 vfs_statvfs_struct svfs;
2963 if (!lp_unix_extensions()) {
2964 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2968 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2972 SIVAL(pdata,0,svfs.OptimalTransferSize);
2973 SIVAL(pdata,4,svfs.BlockSize);
2974 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2975 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2976 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2977 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2978 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2979 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2980 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2982 } else if (rc == EOPNOTSUPP) {
2983 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2985 #endif /* EOPNOTSUPP */
2987 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2988 reply_doserror(req, ERRSRV, ERRerror);
2994 case SMB_QUERY_POSIX_WHOAMI:
3000 if (!lp_unix_extensions()) {
3001 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3005 if (max_data_bytes < 40) {
3006 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3010 /* We ARE guest if global_sid_Builtin_Guests is
3011 * in our list of SIDs.
3013 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3014 conn->server_info->ptok)) {
3015 flags |= SMB_WHOAMI_GUEST;
3018 /* We are NOT guest if global_sid_Authenticated_Users
3019 * is in our list of SIDs.
3021 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3022 conn->server_info->ptok)) {
3023 flags &= ~SMB_WHOAMI_GUEST;
3026 /* NOTE: 8 bytes for UID/GID, irrespective of native
3027 * platform size. This matches
3028 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3030 data_len = 4 /* flags */
3037 + 4 /* pad/reserved */
3038 + (conn->server_info->utok.ngroups * 8)
3040 + (conn->server_info->ptok->num_sids *
3044 SIVAL(pdata, 0, flags);
3045 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3047 (uint64_t)conn->server_info->utok.uid);
3048 SBIG_UINT(pdata, 16,
3049 (uint64_t)conn->server_info->utok.gid);
3052 if (data_len >= max_data_bytes) {
3053 /* Potential overflow, skip the GIDs and SIDs. */
3055 SIVAL(pdata, 24, 0); /* num_groups */
3056 SIVAL(pdata, 28, 0); /* num_sids */
3057 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3058 SIVAL(pdata, 36, 0); /* reserved */
3064 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3065 SIVAL(pdata, 28, conn->server_info->num_sids);
3067 /* We walk the SID list twice, but this call is fairly
3068 * infrequent, and I don't expect that it's performance
3069 * sensitive -- jpeach
3071 for (i = 0, sid_bytes = 0;
3072 i < conn->server_info->ptok->num_sids; ++i) {
3073 sid_bytes += ndr_size_dom_sid(
3074 &conn->server_info->ptok->user_sids[i],
3079 /* SID list byte count */
3080 SIVAL(pdata, 32, sid_bytes);
3082 /* 4 bytes pad/reserved - must be zero */
3083 SIVAL(pdata, 36, 0);
3087 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3088 SBIG_UINT(pdata, data_len,
3089 (uint64_t)conn->server_info->utok.groups[i]);
3095 i < conn->server_info->ptok->num_sids; ++i) {
3096 int sid_len = ndr_size_dom_sid(
3097 &conn->server_info->ptok->user_sids[i],
3101 sid_linearize(pdata + data_len, sid_len,
3102 &conn->server_info->ptok->user_sids[i]);
3103 data_len += sid_len;
3109 case SMB_MAC_QUERY_FS_INFO:
3111 * Thursby MAC extension... ONLY on NTFS filesystems
3112 * once we do streams then we don't need this
3114 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3116 SIVAL(pdata,84,0x100); /* Don't support mac... */
3121 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3126 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3129 DEBUG( 4, ( "%s info_level = %d\n",
3130 smb_fn_name(req->cmd), info_level) );
3135 /****************************************************************************
3136 Reply to a TRANS2_SETFSINFO (set filesystem info).
3137 ****************************************************************************/
3139 static void call_trans2setfsinfo(connection_struct *conn,
3140 struct smb_request *req,
3141 char **pparams, int total_params,
3142 char **ppdata, int total_data,
3143 unsigned int max_data_bytes)
3145 char *pdata = *ppdata;
3146 char *params = *pparams;
3149 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3152 if (total_params < 4) {
3153 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3155 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3159 info_level = SVAL(params,2);
3162 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3163 info_level != SMB_SET_CIFS_UNIX_INFO) {
3164 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3165 "info level (0x%x) on IPC$.\n",
3166 (unsigned int)info_level));
3167 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3172 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3173 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3174 DEBUG(0,("call_trans2setfsinfo: encryption required "
3175 "and info level 0x%x sent.\n",
3176 (unsigned int)info_level));
3177 exit_server_cleanly("encryption required "
3183 switch(info_level) {
3184 case SMB_SET_CIFS_UNIX_INFO:
3186 uint16 client_unix_major;
3187 uint16 client_unix_minor;
3188 uint32 client_unix_cap_low;
3189 uint32 client_unix_cap_high;
3191 if (!lp_unix_extensions()) {
3193 NT_STATUS_INVALID_LEVEL);
3197 /* There should be 12 bytes of capabilities set. */
3198 if (total_data < 8) {
3201 NT_STATUS_INVALID_PARAMETER);
3204 client_unix_major = SVAL(pdata,0);
3205 client_unix_minor = SVAL(pdata,2);
3206 client_unix_cap_low = IVAL(pdata,4);
3207 client_unix_cap_high = IVAL(pdata,8);
3208 /* Just print these values for now. */
3209 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3210 cap_low = 0x%x, cap_high = 0x%x\n",
3211 (unsigned int)client_unix_major,
3212 (unsigned int)client_unix_minor,
3213 (unsigned int)client_unix_cap_low,
3214 (unsigned int)client_unix_cap_high ));
3216 /* Here is where we must switch to posix pathname processing... */
3217 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3218 lp_set_posix_pathnames();
3219 mangle_change_to_posix();
3222 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3223 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3224 /* Client that knows how to do posix locks,
3225 * but not posix open/mkdir operations. Set a
3226 * default type for read/write checks. */
3228 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3234 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3237 size_t param_len = 0;
3238 size_t data_len = total_data;
3240 if (!lp_unix_extensions()) {
3243 NT_STATUS_INVALID_LEVEL);
3247 if (lp_smb_encrypt(SNUM(conn)) == false) {
3250 NT_STATUS_NOT_SUPPORTED);
3254 DEBUG( 4,("call_trans2setfsinfo: "
3255 "request transport encryption.\n"));
3257 status = srv_request_encryption_setup(conn,
3258 (unsigned char **)ppdata,
3260 (unsigned char **)pparams,
3263 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3264 !NT_STATUS_IS_OK(status)) {
3265 reply_nterror(req, status);
3269 send_trans2_replies(conn, req,
3276 if (NT_STATUS_IS_OK(status)) {
3277 /* Server-side transport
3278 * encryption is now *on*. */
3279 status = srv_encryption_start(conn);
3280 if (!NT_STATUS_IS_OK(status)) {
3281 exit_server_cleanly(
3282 "Failure in setting "
3283 "up encrypted transport");
3289 case SMB_FS_QUOTA_INFORMATION:
3291 files_struct *fsp = NULL;
3292 SMB_NTQUOTA_STRUCT quotas;
3294 ZERO_STRUCT(quotas);
3297 if ((conn->server_info->utok.uid != 0)
3298 ||!CAN_WRITE(conn)) {
3299 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3300 lp_servicename(SNUM(conn)),
3301 conn->server_info->unix_name));
3302 reply_doserror(req, ERRSRV, ERRaccess);
3306 /* note: normaly there're 48 bytes,
3307 * but we didn't use the last 6 bytes for now
3310 fsp = file_fsp(req, SVAL(params,0));
3312 if (!check_fsp_ntquota_handle(conn, req,
3314 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3316 req, NT_STATUS_INVALID_HANDLE);
3320 if (total_data < 42) {
3321 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3325 NT_STATUS_INVALID_PARAMETER);
3329 /* unknown_1 24 NULL bytes in pdata*/
3331 /* the soft quotas 8 bytes (uint64_t)*/
3332 quotas.softlim = (uint64_t)IVAL(pdata,24);
3333 #ifdef LARGE_SMB_OFF_T
3334 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3335 #else /* LARGE_SMB_OFF_T */
3336 if ((IVAL(pdata,28) != 0)&&
3337 ((quotas.softlim != 0xFFFFFFFF)||
3338 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3339 /* more than 32 bits? */
3342 NT_STATUS_INVALID_PARAMETER);
3345 #endif /* LARGE_SMB_OFF_T */
3347 /* the hard quotas 8 bytes (uint64_t)*/
3348 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3349 #ifdef LARGE_SMB_OFF_T
3350 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3351 #else /* LARGE_SMB_OFF_T */
3352 if ((IVAL(pdata,36) != 0)&&
3353 ((quotas.hardlim != 0xFFFFFFFF)||
3354 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3355 /* more than 32 bits? */
3358 NT_STATUS_INVALID_PARAMETER);
3361 #endif /* LARGE_SMB_OFF_T */
3363 /* quota_flags 2 bytes **/
3364 quotas.qflags = SVAL(pdata,40);
3366 /* unknown_2 6 NULL bytes follow*/
3368 /* now set the quotas */
3369 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3370 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3371 reply_doserror(req, ERRSRV, ERRerror);
3378 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3380 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3386 * sending this reply works fine,
3387 * but I'm not sure it's the same
3388 * like windows do...
3391 reply_outbuf(req, 10, 0);
3394 #if defined(HAVE_POSIX_ACLS)
3395 /****************************************************************************
3396 Utility function to count the number of entries in a POSIX acl.
3397 ****************************************************************************/
3399 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3401 unsigned int ace_count = 0;
3402 int entry_id = SMB_ACL_FIRST_ENTRY;
3403 SMB_ACL_ENTRY_T entry;
3405 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3407 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3408 entry_id = SMB_ACL_NEXT_ENTRY;
3415 /****************************************************************************
3416 Utility function to marshall a POSIX acl into wire format.
3417 ****************************************************************************/
3419 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3421 int entry_id = SMB_ACL_FIRST_ENTRY;
3422 SMB_ACL_ENTRY_T entry;
3424 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3425 SMB_ACL_TAG_T tagtype;
3426 SMB_ACL_PERMSET_T permset;
3427 unsigned char perms = 0;
3428 unsigned int own_grp;
3431 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3432 entry_id = SMB_ACL_NEXT_ENTRY;
3435 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3436 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3440 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3441 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3445 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3446 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3447 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3449 SCVAL(pdata,1,perms);
3452 case SMB_ACL_USER_OBJ:
3453 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3454 own_grp = (unsigned int)pst->st_uid;
3455 SIVAL(pdata,2,own_grp);
3460 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3462 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3465 own_grp = (unsigned int)*puid;
3466 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3467 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3468 SIVAL(pdata,2,own_grp);
3472 case SMB_ACL_GROUP_OBJ:
3473 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3474 own_grp = (unsigned int)pst->st_gid;
3475 SIVAL(pdata,2,own_grp);
3480 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3482 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3485 own_grp = (unsigned int)*pgid;
3486 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3487 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3488 SIVAL(pdata,2,own_grp);
3493 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3494 SIVAL(pdata,2,0xFFFFFFFF);
3495 SIVAL(pdata,6,0xFFFFFFFF);
3498 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3499 SIVAL(pdata,2,0xFFFFFFFF);
3500 SIVAL(pdata,6,0xFFFFFFFF);
3503 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3506 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3513 /****************************************************************************
3514 Store the FILE_UNIX_BASIC info.
3515 ****************************************************************************/
3517 static char *store_file_unix_basic(connection_struct *conn,
3520 const SMB_STRUCT_STAT *psbuf)
3522 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3523 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3525 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3528 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3531 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3532 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3533 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3536 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3540 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3544 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3547 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3551 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3555 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3558 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3562 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3569 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3570 * the chflags(2) (or equivalent) flags.
3572 * XXX: this really should be behind the VFS interface. To do this, we would
3573 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3574 * Each VFS module could then implement its own mapping as appropriate for the
3575 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3577 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3581 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3585 { UF_IMMUTABLE, EXT_IMMUTABLE },
3589 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3593 { UF_HIDDEN, EXT_HIDDEN },
3596 /* Do not remove. We need to guarantee that this array has at least one
3597 * entry to build on HP-UX.
3603 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3604 uint32 *smb_fflags, uint32 *smb_fmask)
3606 #ifdef HAVE_STAT_ST_FLAGS
3609 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3610 *smb_fmask |= info2_flags_map[i].smb_fflag;
3611 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3612 *smb_fflags |= info2_flags_map[i].smb_fflag;
3615 #endif /* HAVE_STAT_ST_FLAGS */
3618 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3619 const uint32 smb_fflags,
3620 const uint32 smb_fmask,
3623 #ifdef HAVE_STAT_ST_FLAGS
3624 uint32 max_fmask = 0;
3627 *stat_fflags = psbuf->st_flags;
3629 /* For each flags requested in smb_fmask, check the state of the
3630 * corresponding flag in smb_fflags and set or clear the matching
3634 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3635 max_fmask |= info2_flags_map[i].smb_fflag;
3636 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3637 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3638 *stat_fflags |= info2_flags_map[i].stat_fflag;
3640 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3645 /* If smb_fmask is asking to set any bits that are not supported by
3646 * our flag mappings, we should fail.
3648 if ((smb_fmask & max_fmask) != smb_fmask) {
3655 #endif /* HAVE_STAT_ST_FLAGS */
3659 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3660 * of file flags and birth (create) time.
3662 static char *store_file_unix_basic_info2(connection_struct *conn,
3665 const SMB_STRUCT_STAT *psbuf)
3667 uint32 file_flags = 0;
3668 uint32 flags_mask = 0;
3670 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3672 /* Create (birth) time 64 bit */
3673 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3676 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3677 SIVAL(pdata, 0, file_flags); /* flags */
3678 SIVAL(pdata, 4, flags_mask); /* mask */
3684 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3685 const struct stream_struct *streams,
3687 unsigned int max_data_bytes,
3688 unsigned int *data_size)
3691 unsigned int ofs = 0;
3693 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3694 unsigned int next_offset;
3696 smb_ucs2_t *namebuf;
3698 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3699 streams[i].name, &namelen) ||
3702 return NT_STATUS_INVALID_PARAMETER;
3706 * name_buf is now null-terminated, we need to marshall as not
3712 SIVAL(data, ofs+4, namelen);
3713 SOFF_T(data, ofs+8, streams[i].size);
3714 SOFF_T(data, ofs+16, streams[i].alloc_size);
3715 memcpy(data+ofs+24, namebuf, namelen);
3716 TALLOC_FREE(namebuf);
3718 next_offset = ofs + 24 + namelen;
3720 if (i == num_streams-1) {
3721 SIVAL(data, ofs, 0);
3724 unsigned int align = ndr_align_size(next_offset, 8);
3726 memset(data+next_offset, 0, align);
3727 next_offset += align;
3729 SIVAL(data, ofs, next_offset - ofs);
3738 return NT_STATUS_OK;
3741 /****************************************************************************
3742 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3743 ****************************************************************************/
3745 static void call_trans2qpipeinfo(connection_struct *conn,
3746 struct smb_request *req,
3747 unsigned int tran_call,
3748 char **pparams, int total_params,
3749 char **ppdata, int total_data,
3750 unsigned int max_data_bytes)
3752 char *params = *pparams;
3753 char *pdata = *ppdata;
3754 unsigned int data_size = 0;
3755 unsigned int param_size = 2;
3760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3764 if (total_params < 4) {
3765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3769 fsp = file_fsp(req, SVAL(params,0));
3770 if (!fsp_is_np(fsp)) {
3771 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3775 info_level = SVAL(params,2);
3777 *pparams = (char *)SMB_REALLOC(*pparams,2);
3778 if (*pparams == NULL) {
3779 reply_nterror(req, NT_STATUS_NO_MEMORY);
3784 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3785 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3786 if (*ppdata == NULL ) {
3787 reply_nterror(req, NT_STATUS_NO_MEMORY);
3792 switch (info_level) {
3793 case SMB_FILE_STANDARD_INFORMATION:
3795 SOFF_T(pdata,0,4096LL);
3802 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3806 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3812 /****************************************************************************
3813 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3814 file name or file id).
3815 ****************************************************************************/
3817 static void call_trans2qfilepathinfo(connection_struct *conn,
3818 struct smb_request *req,
3819 unsigned int tran_call,
3820 char **pparams, int total_params,
3821 char **ppdata, int total_data,
3822 unsigned int max_data_bytes)
3824 char *params = *pparams;
3825 char *pdata = *ppdata;
3826 char *dstart, *dend;
3830 SMB_OFF_T file_size=0;
3831 uint64_t allocation_size=0;
3832 unsigned int data_size = 0;
3833 unsigned int param_size = 2;
3834 SMB_STRUCT_STAT sbuf;
3835 char *dos_fname = NULL;
3841 bool delete_pending = False;
3843 time_t create_time, mtime, atime;
3844 struct timespec create_time_ts, mtime_ts, atime_ts;
3845 struct timespec write_time_ts;
3846 files_struct *fsp = NULL;
3847 struct file_id fileid;
3848 struct ea_list *ea_list = NULL;
3849 char *lock_data = NULL;
3850 bool ms_dfs_link = false;
3851 TALLOC_CTX *ctx = talloc_tos();
3854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3859 ZERO_STRUCT(write_time_ts);
3861 if (tran_call == TRANSACT2_QFILEINFO) {
3862 if (total_params < 4) {
3863 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3868 call_trans2qpipeinfo(conn, req, tran_call,
3869 pparams, total_params,
3875 fsp = file_fsp(req, SVAL(params,0));
3876 info_level = SVAL(params,2);
3878 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3880 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3881 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3885 /* Initial check for valid fsp ptr. */
3886 if (!check_fsp_open(conn, req, fsp)) {
3890 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3892 reply_nterror(req, NT_STATUS_NO_MEMORY);
3896 if(fsp->fake_file_handle) {
3898 * This is actually for the QUOTA_FAKE_FILE --metze
3901 /* We know this name is ok, it's already passed the checks. */
3903 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3905 * This is actually a QFILEINFO on a directory
3906 * handle (returned from an NT SMB). NT5.0 seems
3907 * to do this call. JRA.
3910 if (INFO_LEVEL_IS_UNIX(info_level)) {
3911 /* Always do lstat for UNIX calls. */
3912 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3913 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3914 reply_unixerror(req,ERRDOS,ERRbadpath);
3917 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3918 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3919 reply_unixerror(req, ERRDOS, ERRbadpath);
3923 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3924 get_file_infos(fileid, &delete_pending, &write_time_ts);
3927 * Original code - this is an open file.
3929 if (!check_fsp(conn, req, fsp)) {
3933 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3934 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3935 reply_unixerror(req, ERRDOS, ERRbadfid);
3938 pos = fsp->fh->position_information;
3939 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3940 get_file_infos(fileid, &delete_pending, &write_time_ts);
3944 NTSTATUS status = NT_STATUS_OK;
3947 if (total_params < 7) {
3948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3952 info_level = SVAL(params,0);
3954 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3956 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3957 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3961 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3963 STR_TERMINATE, &status);
3964 if (!NT_STATUS_IS_OK(status)) {
3965 reply_nterror(req, status);
3969 status = resolve_dfspath(ctx,
3971 req->flags2 & FLAGS2_DFS_PATHNAMES,
3974 if (!NT_STATUS_IS_OK(status)) {
3975 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3976 reply_botherror(req,
3977 NT_STATUS_PATH_NOT_COVERED,
3978 ERRSRV, ERRbadpath);
3980 reply_nterror(req, status);
3984 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3985 if (!NT_STATUS_IS_OK(status)) {
3986 reply_nterror(req, status);
3989 status = check_name(conn, fname);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3992 reply_nterror(req, status);
3996 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3997 && is_ntfs_stream_name(fname)) {
3999 SMB_STRUCT_STAT bsbuf;
4001 status = split_ntfs_stream_name(talloc_tos(), fname,
4003 if (!NT_STATUS_IS_OK(status)) {
4004 DEBUG(10, ("create_file_unixpath: "
4005 "split_ntfs_stream_name failed: %s\n",
4006 nt_errstr(status)));
4007 reply_nterror(req, status);
4011 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4013 if (INFO_LEVEL_IS_UNIX(info_level)) {
4014 /* Always do lstat for UNIX calls. */
4015 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4016 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4017 reply_unixerror(req,ERRDOS,ERRbadpath);
4021 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4022 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4023 reply_unixerror(req,ERRDOS,ERRbadpath);
4028 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4029 get_file_infos(fileid, &delete_pending, NULL);
4030 if (delete_pending) {
4031 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4036 if (INFO_LEVEL_IS_UNIX(info_level)) {
4037 /* Always do lstat for UNIX calls. */
4038 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4039 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4040 reply_unixerror(req, ERRDOS, ERRbadpath);
4044 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4045 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4048 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4049 reply_unixerror(req, ERRDOS, ERRbadpath);
4054 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4055 get_file_infos(fileid, &delete_pending, &write_time_ts);
4056 if (delete_pending) {
4057 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4062 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4063 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4067 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4068 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4070 p = strrchr_m(fname,'/');
4077 mode = dos_mode_msdfs(conn,fname,&sbuf);
4079 mode = dos_mode(conn,fname,&sbuf);
4082 mode = FILE_ATTRIBUTE_NORMAL;
4084 nlink = sbuf.st_nlink;
4086 if (nlink && (mode&aDIR)) {
4090 if ((nlink > 0) && delete_pending) {
4094 fullpathname = fname;
4096 file_size = get_file_size_stat(&sbuf);
4098 /* Pull out any data sent here before we realloc. */
4099 switch (info_level) {
4100 case SMB_INFO_QUERY_EAS_FROM_LIST:
4102 /* Pull any EA list from the data portion. */
4105 if (total_data < 4) {
4107 req, NT_STATUS_INVALID_PARAMETER);
4110 ea_size = IVAL(pdata,0);
4112 if (total_data > 0 && ea_size != total_data) {
4113 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4114 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4116 req, NT_STATUS_INVALID_PARAMETER);
4120 if (!lp_ea_support(SNUM(conn))) {
4121 reply_doserror(req, ERRDOS,
4122 ERReasnotsupported);
4126 /* Pull out the list of names. */
4127 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4130 req, NT_STATUS_INVALID_PARAMETER);
4136 case SMB_QUERY_POSIX_LOCK:
4138 if (fsp == NULL || fsp->fh->fd == -1) {
4139 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4143 if (total_data != POSIX_LOCK_DATA_SIZE) {
4145 req, NT_STATUS_INVALID_PARAMETER);
4149 /* Copy the lock range data. */
4150 lock_data = (char *)TALLOC_MEMDUP(
4151 ctx, pdata, total_data);
4153 reply_nterror(req, NT_STATUS_NO_MEMORY);
4161 *pparams = (char *)SMB_REALLOC(*pparams,2);
4162 if (*pparams == NULL) {
4163 reply_nterror(req, NT_STATUS_NO_MEMORY);
4168 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4169 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4170 if (*ppdata == NULL ) {
4171 reply_nterror(req, NT_STATUS_NO_MEMORY);
4176 dend = dstart + data_size - 1;
4178 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4179 mtime_ts = get_mtimespec(&sbuf);
4180 atime_ts = get_atimespec(&sbuf);
4182 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4185 /* Do we have this path open ? */
4187 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4188 fsp1 = file_find_di_first(fileid);
4189 if (fsp1 && fsp1->initial_allocation_size) {
4190 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4194 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4195 mtime_ts = write_time_ts;
4198 if (lp_dos_filetime_resolution(SNUM(conn))) {
4199 dos_filetime_timespec(&create_time_ts);
4200 dos_filetime_timespec(&mtime_ts);
4201 dos_filetime_timespec(&atime_ts);
4204 create_time = convert_timespec_to_time_t(create_time_ts);
4205 mtime = convert_timespec_to_time_t(mtime_ts);
4206 atime = convert_timespec_to_time_t(atime_ts);
4208 /* NT expects the name to be in an exact form of the *full*
4209 filename. See the trans2 torture test */
4210 if (ISDOT(base_name)) {
4211 dos_fname = talloc_strdup(ctx, "\\");
4213 reply_nterror(req, NT_STATUS_NO_MEMORY);
4217 dos_fname = talloc_asprintf(ctx,
4221 reply_nterror(req, NT_STATUS_NO_MEMORY);
4224 string_replace(dos_fname, '/', '\\');
4227 switch (info_level) {
4228 case SMB_INFO_STANDARD:
4229 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4231 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4232 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4233 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4234 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4235 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4236 SSVAL(pdata,l1_attrFile,mode);
4239 case SMB_INFO_QUERY_EA_SIZE:
4241 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4242 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4244 srv_put_dos_date2(pdata,0,create_time);
4245 srv_put_dos_date2(pdata,4,atime);
4246 srv_put_dos_date2(pdata,8,mtime); /* write time */
4247 SIVAL(pdata,12,(uint32)file_size);
4248 SIVAL(pdata,16,(uint32)allocation_size);
4249 SSVAL(pdata,20,mode);
4250 SIVAL(pdata,22,ea_size);
4254 case SMB_INFO_IS_NAME_VALID:
4255 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4256 if (tran_call == TRANSACT2_QFILEINFO) {
4257 /* os/2 needs this ? really ?*/
4258 reply_doserror(req, ERRDOS, ERRbadfunc);
4265 case SMB_INFO_QUERY_EAS_FROM_LIST:
4267 size_t total_ea_len = 0;
4268 struct ea_list *ea_file_list = NULL;
4270 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4272 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4273 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4275 if (!ea_list || (total_ea_len > data_size)) {
4277 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4281 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4285 case SMB_INFO_QUERY_ALL_EAS:
4287 /* We have data_size bytes to put EA's into. */
4288 size_t total_ea_len = 0;
4290 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4292 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4293 if (!ea_list || (total_ea_len > data_size)) {
4295 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4299 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4303 case SMB_FILE_BASIC_INFORMATION:
4304 case SMB_QUERY_FILE_BASIC_INFO:
4306 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4307 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4308 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4310 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4314 put_long_date_timespec(pdata,create_time_ts);
4315 put_long_date_timespec(pdata+8,atime_ts);
4316 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4317 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4318 SIVAL(pdata,32,mode);
4320 DEBUG(5,("SMB_QFBI - "));
4321 DEBUG(5,("create: %s ", ctime(&create_time)));
4322 DEBUG(5,("access: %s ", ctime(&atime)));
4323 DEBUG(5,("write: %s ", ctime(&mtime)));
4324 DEBUG(5,("change: %s ", ctime(&mtime)));
4325 DEBUG(5,("mode: %x\n", mode));
4328 case SMB_FILE_STANDARD_INFORMATION:
4329 case SMB_QUERY_FILE_STANDARD_INFO:
4331 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4333 SOFF_T(pdata,0,allocation_size);
4334 SOFF_T(pdata,8,file_size);
4335 SIVAL(pdata,16,nlink);
4336 SCVAL(pdata,20,delete_pending?1:0);
4337 SCVAL(pdata,21,(mode&aDIR)?1:0);
4338 SSVAL(pdata,22,0); /* Padding. */
4341 case SMB_FILE_EA_INFORMATION:
4342 case SMB_QUERY_FILE_EA_INFO:
4344 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4345 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4347 SIVAL(pdata,0,ea_size);
4351 /* Get the 8.3 name - used if NT SMB was negotiated. */
4352 case SMB_QUERY_FILE_ALT_NAME_INFO:
4353 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4355 char mangled_name[13];
4356 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4357 if (!name_to_8_3(base_name,mangled_name,
4358 True,conn->params)) {
4361 NT_STATUS_NO_MEMORY);
4363 len = srvstr_push(dstart, req->flags2,
4364 pdata+4, mangled_name,
4365 PTR_DIFF(dend, pdata+4),
4367 data_size = 4 + len;
4372 case SMB_QUERY_FILE_NAME_INFO:
4374 this must be *exactly* right for ACLs on mapped drives to work
4376 len = srvstr_push(dstart, req->flags2,
4378 PTR_DIFF(dend, pdata+4),
4380 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4381 data_size = 4 + len;
4385 case SMB_FILE_ALLOCATION_INFORMATION:
4386 case SMB_QUERY_FILE_ALLOCATION_INFO:
4387 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4389 SOFF_T(pdata,0,allocation_size);
4392 case SMB_FILE_END_OF_FILE_INFORMATION:
4393 case SMB_QUERY_FILE_END_OF_FILEINFO:
4394 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4396 SOFF_T(pdata,0,file_size);
4399 case SMB_QUERY_FILE_ALL_INFO:
4400 case SMB_FILE_ALL_INFORMATION:
4402 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4403 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4404 put_long_date_timespec(pdata,create_time_ts);
4405 put_long_date_timespec(pdata+8,atime_ts);
4406 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4407 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4408 SIVAL(pdata,32,mode);
4409 SIVAL(pdata,36,0); /* padding. */
4411 SOFF_T(pdata,0,allocation_size);
4412 SOFF_T(pdata,8,file_size);
4413 SIVAL(pdata,16,nlink);
4414 SCVAL(pdata,20,delete_pending);
4415 SCVAL(pdata,21,(mode&aDIR)?1:0);
4418 SIVAL(pdata,0,ea_size);
4419 pdata += 4; /* EA info */
4420 len = srvstr_push(dstart, req->flags2,
4422 PTR_DIFF(dend, pdata+4),
4426 data_size = PTR_DIFF(pdata,(*ppdata));
4429 case SMB_FILE_INTERNAL_INFORMATION:
4430 /* This should be an index number - looks like
4433 I think this causes us to fail the IFSKIT
4434 BasicFileInformationTest. -tpot */
4436 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4437 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4438 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4442 case SMB_FILE_ACCESS_INFORMATION:
4443 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4445 SIVAL(pdata,0,fsp->access_mask);
4447 /* GENERIC_EXECUTE mapping from Windows */
4448 SIVAL(pdata,0,0x12019F);
4453 case SMB_FILE_NAME_INFORMATION:
4454 /* Pathname with leading '\'. */
4457 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4458 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4459 SIVAL(pdata,0,byte_len);
4460 data_size = 4 + byte_len;
4464 case SMB_FILE_DISPOSITION_INFORMATION:
4465 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4467 SCVAL(pdata,0,delete_pending);
4470 case SMB_FILE_POSITION_INFORMATION:
4471 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4473 SOFF_T(pdata,0,pos);
4476 case SMB_FILE_MODE_INFORMATION:
4477 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4478 SIVAL(pdata,0,mode);
4482 case SMB_FILE_ALIGNMENT_INFORMATION:
4483 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4484 SIVAL(pdata,0,0); /* No alignment needed. */
4489 * NT4 server just returns "invalid query" to this - if we try
4490 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4493 /* The first statement above is false - verified using Thursby
4494 * client against NT4 -- gcolley.
4496 case SMB_QUERY_FILE_STREAM_INFO:
4497 case SMB_FILE_STREAM_INFORMATION: {
4498 unsigned int num_streams;
4499 struct stream_struct *streams;
4502 DEBUG(10,("call_trans2qfilepathinfo: "
4503 "SMB_FILE_STREAM_INFORMATION\n"));
4505 status = SMB_VFS_STREAMINFO(
4506 conn, fsp, fname, talloc_tos(),
4507 &num_streams, &streams);
4509 if (!NT_STATUS_IS_OK(status)) {
4510 DEBUG(10, ("could not get stream info: %s\n",
4511 nt_errstr(status)));
4512 reply_nterror(req, status);
4516 status = marshall_stream_info(num_streams, streams,
4517 pdata, max_data_bytes,
4520 if (!NT_STATUS_IS_OK(status)) {
4521 DEBUG(10, ("marshall_stream_info failed: %s\n",
4522 nt_errstr(status)));
4523 reply_nterror(req, status);
4527 TALLOC_FREE(streams);
4531 case SMB_QUERY_COMPRESSION_INFO:
4532 case SMB_FILE_COMPRESSION_INFORMATION:
4533 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4534 SOFF_T(pdata,0,file_size);
4535 SIVAL(pdata,8,0); /* ??? */
4536 SIVAL(pdata,12,0); /* ??? */
4540 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4541 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4542 put_long_date_timespec(pdata,create_time_ts);
4543 put_long_date_timespec(pdata+8,atime_ts);
4544 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4545 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4546 SOFF_T(pdata,32,allocation_size);
4547 SOFF_T(pdata,40,file_size);
4548 SIVAL(pdata,48,mode);
4549 SIVAL(pdata,52,0); /* ??? */
4553 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4554 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4555 SIVAL(pdata,0,mode);
4561 * CIFS UNIX Extensions.
4564 case SMB_QUERY_FILE_UNIX_BASIC:
4566 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4567 data_size = PTR_DIFF(pdata,(*ppdata));
4571 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4573 for (i=0; i<100; i++)
4574 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4580 case SMB_QUERY_FILE_UNIX_INFO2:
4582 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4583 data_size = PTR_DIFF(pdata,(*ppdata));
4587 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4589 for (i=0; i<100; i++)
4590 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4596 case SMB_QUERY_FILE_UNIX_LINK:
4598 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4601 reply_nterror(req, NT_STATUS_NO_MEMORY);
4605 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4607 if(!S_ISLNK(sbuf.st_mode)) {
4608 reply_unixerror(req, ERRSRV,
4613 reply_unixerror(req, ERRDOS, ERRbadlink);
4616 len = SMB_VFS_READLINK(conn,fullpathname,
4619 reply_unixerror(req, ERRDOS,
4624 len = srvstr_push(dstart, req->flags2,
4626 PTR_DIFF(dend, pdata),
4629 data_size = PTR_DIFF(pdata,(*ppdata));
4634 #if defined(HAVE_POSIX_ACLS)
4635 case SMB_QUERY_POSIX_ACL:
4637 SMB_ACL_T file_acl = NULL;
4638 SMB_ACL_T def_acl = NULL;
4639 uint16 num_file_acls = 0;
4640 uint16 num_def_acls = 0;
4642 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4643 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4645 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4648 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4649 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4653 NT_STATUS_NOT_IMPLEMENTED);
4657 if (S_ISDIR(sbuf.st_mode)) {
4658 if (fsp && fsp->is_directory) {
4659 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4661 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4663 def_acl = free_empty_sys_acl(conn, def_acl);
4666 num_file_acls = count_acl_entries(conn, file_acl);
4667 num_def_acls = count_acl_entries(conn, def_acl);
4669 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4670 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4672 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4673 SMB_POSIX_ACL_HEADER_SIZE) ));
4675 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4678 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4682 NT_STATUS_BUFFER_TOO_SMALL);
4686 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4687 SSVAL(pdata,2,num_file_acls);
4688 SSVAL(pdata,4,num_def_acls);
4689 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4691 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4694 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4697 req, NT_STATUS_INTERNAL_ERROR);
4700 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4702 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4705 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4709 NT_STATUS_INTERNAL_ERROR);
4714 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4717 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4719 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4725 case SMB_QUERY_POSIX_LOCK:
4727 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4731 enum brl_type lock_type;
4733 if (total_data != POSIX_LOCK_DATA_SIZE) {
4735 req, NT_STATUS_INVALID_PARAMETER);
4739 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4740 case POSIX_LOCK_TYPE_READ:
4741 lock_type = READ_LOCK;
4743 case POSIX_LOCK_TYPE_WRITE:
4744 lock_type = WRITE_LOCK;
4746 case POSIX_LOCK_TYPE_UNLOCK:
4748 /* There's no point in asking for an unlock... */
4751 NT_STATUS_INVALID_PARAMETER);
4755 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4756 #if defined(HAVE_LONGLONG)
4757 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4758 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4759 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4760 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4761 #else /* HAVE_LONGLONG */
4762 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4763 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4764 #endif /* HAVE_LONGLONG */
4766 status = query_lock(fsp,
4773 if (ERROR_WAS_LOCK_DENIED(status)) {
4774 /* Here we need to report who has it locked... */
4775 data_size = POSIX_LOCK_DATA_SIZE;
4777 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4778 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4779 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4780 #if defined(HAVE_LONGLONG)
4781 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4782 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4783 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4784 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4785 #else /* HAVE_LONGLONG */
4786 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4787 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4788 #endif /* HAVE_LONGLONG */
4790 } else if (NT_STATUS_IS_OK(status)) {
4791 /* For success we just return a copy of what we sent
4792 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4793 data_size = POSIX_LOCK_DATA_SIZE;
4794 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4795 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4797 reply_nterror(req, status);
4804 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4808 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4814 /****************************************************************************
4815 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4817 ****************************************************************************/
4819 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4820 connection_struct *conn,
4821 const char *oldname_in,
4822 const char *newname_in)
4824 SMB_STRUCT_STAT sbuf1, sbuf2;
4825 char *last_component_oldname = NULL;
4826 char *last_component_newname = NULL;
4827 char *oldname = NULL;
4828 char *newname = NULL;
4829 NTSTATUS status = NT_STATUS_OK;
4834 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4835 &last_component_oldname, &sbuf1);
4836 if (!NT_STATUS_IS_OK(status)) {
4840 status = check_name(conn, oldname);
4841 if (!NT_STATUS_IS_OK(status)) {
4845 /* source must already exist. */
4846 if (!VALID_STAT(sbuf1)) {
4847 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4850 status = unix_convert(ctx, conn, newname_in, False, &newname,
4851 &last_component_newname, &sbuf2);
4852 if (!NT_STATUS_IS_OK(status)) {
4856 status = check_name(conn, newname);
4857 if (!NT_STATUS_IS_OK(status)) {
4861 /* Disallow if newname already exists. */
4862 if (VALID_STAT(sbuf2)) {
4863 return NT_STATUS_OBJECT_NAME_COLLISION;
4866 /* No links from a directory. */
4867 if (S_ISDIR(sbuf1.st_mode)) {
4868 return NT_STATUS_FILE_IS_A_DIRECTORY;
4871 /* Ensure this is within the share. */
4872 status = check_reduced_name(conn, oldname);
4873 if (!NT_STATUS_IS_OK(status)) {
4877 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4879 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4880 status = map_nt_error_from_unix(errno);
4881 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4882 nt_errstr(status), newname, oldname));
4888 /****************************************************************************
4889 Deal with setting the time from any of the setfilepathinfo functions.
4890 ****************************************************************************/
4892 NTSTATUS smb_set_file_time(connection_struct *conn,
4895 const SMB_STRUCT_STAT *psbuf,
4896 struct smb_file_time *ft,
4897 bool setting_write_time)
4900 FILE_NOTIFY_CHANGE_LAST_ACCESS
4901 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4903 if (!VALID_STAT(*psbuf)) {
4904 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4907 /* get some defaults (no modifications) if any info is zero or -1. */
4908 if (null_timespec(ft->atime)) {
4909 ft->atime= get_atimespec(psbuf);
4910 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4913 if (null_timespec(ft->mtime)) {
4914 ft->mtime = get_mtimespec(psbuf);
4915 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4918 if (!setting_write_time) {
4919 /* ft->mtime comes from change time, not write time. */
4920 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4923 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4924 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4925 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4926 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4927 if (!null_timespec(ft->create_time)) {
4928 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4929 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4933 * Try and set the times of this file if
4934 * they are different from the current values.
4938 struct timespec mts = get_mtimespec(psbuf);
4939 struct timespec ats = get_atimespec(psbuf);
4940 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4941 (timespec_compare(&ft->mtime, &mts) == 0)) {
4942 return NT_STATUS_OK;
4946 if (setting_write_time) {
4948 * This was a setfileinfo on an open file.
4949 * NT does this a lot. We also need to
4950 * set the time here, as it can be read by
4951 * FindFirst/FindNext and with the patch for bug #2045
4952 * in smbd/fileio.c it ensures that this timestamp is
4953 * kept sticky even after a write. We save the request
4954 * away and will set it on file close and after a write. JRA.
4957 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4958 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4961 if (fsp->base_fsp) {
4962 set_sticky_write_time_fsp(fsp->base_fsp,
4965 set_sticky_write_time_fsp(fsp, ft->mtime);
4968 set_sticky_write_time_path(conn, fname,
4969 vfs_file_id_from_sbuf(conn, psbuf),
4974 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4976 if (fsp && fsp->base_fsp) {
4977 fname = fsp->base_fsp->fsp_name;
4980 if(file_ntimes(conn, fname, ft)!=0) {
4981 return map_nt_error_from_unix(errno);
4983 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4985 return NT_STATUS_OK;
4988 /****************************************************************************
4989 Deal with setting the dosmode from any of the setfilepathinfo functions.
4990 ****************************************************************************/
4992 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4995 SMB_STRUCT_STAT *psbuf,
4998 if (!VALID_STAT(*psbuf)) {
4999 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5003 if (fsp->base_fsp) {
5004 fname = fsp->base_fsp->fsp_name;
5006 fname = fsp->fsp_name;
5011 if (S_ISDIR(psbuf->st_mode)) {
5018 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5020 /* check the mode isn't different, before changing it */
5021 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5023 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5024 fname, (unsigned int)dosmode ));
5026 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5027 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5028 fname, strerror(errno)));
5029 return map_nt_error_from_unix(errno);
5032 return NT_STATUS_OK;
5035 /****************************************************************************
5036 Deal with setting the size from any of the setfilepathinfo functions.
5037 ****************************************************************************/
5039 static NTSTATUS smb_set_file_size(connection_struct *conn,
5040 struct smb_request *req,
5043 SMB_STRUCT_STAT *psbuf,
5046 NTSTATUS status = NT_STATUS_OK;
5047 files_struct *new_fsp = NULL;
5049 if (!VALID_STAT(*psbuf)) {
5050 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5053 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5055 if (size == get_file_size_stat(psbuf)) {
5056 return NT_STATUS_OK;
5059 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5060 fname, (double)size ));
5062 if (fsp && fsp->fh->fd != -1) {
5063 /* Handle based call. */
5064 if (vfs_set_filelen(fsp, size) == -1) {
5065 return map_nt_error_from_unix(errno);
5067 trigger_write_time_update_immediate(fsp);
5068 return NT_STATUS_OK;
5071 status = SMB_VFS_CREATE_FILE(
5074 0, /* root_dir_fid */
5076 0, /* create_file_flags */
5077 FILE_WRITE_ATTRIBUTES, /* access_mask */
5078 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5080 FILE_OPEN, /* create_disposition*/
5081 0, /* create_options */
5082 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5083 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5084 0, /* allocation_size */
5087 &new_fsp, /* result */
5091 if (!NT_STATUS_IS_OK(status)) {
5092 /* NB. We check for open_was_deferred in the caller. */
5096 if (vfs_set_filelen(new_fsp, size) == -1) {
5097 status = map_nt_error_from_unix(errno);
5098 close_file(req, new_fsp,NORMAL_CLOSE);
5102 trigger_write_time_update_immediate(new_fsp);
5103 close_file(req, new_fsp,NORMAL_CLOSE);
5104 return NT_STATUS_OK;
5107 /****************************************************************************
5108 Deal with SMB_INFO_SET_EA.
5109 ****************************************************************************/
5111 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5117 struct ea_list *ea_list = NULL;
5118 TALLOC_CTX *ctx = NULL;
5119 NTSTATUS status = NT_STATUS_OK;
5121 if (total_data < 10) {
5123 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5124 length. They seem to have no effect. Bug #3212. JRA */
5126 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5127 /* We're done. We only get EA info in this call. */
5128 return NT_STATUS_OK;
5131 return NT_STATUS_INVALID_PARAMETER;
5134 if (IVAL(pdata,0) > total_data) {
5135 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5136 IVAL(pdata,0), (unsigned int)total_data));
5137 return NT_STATUS_INVALID_PARAMETER;
5141 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5143 return NT_STATUS_INVALID_PARAMETER;
5145 status = set_ea(conn, fsp, fname, ea_list);
5150 /****************************************************************************
5151 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5152 ****************************************************************************/
5154 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5159 SMB_STRUCT_STAT *psbuf)
5161 NTSTATUS status = NT_STATUS_OK;
5162 bool delete_on_close;
5165 if (total_data < 1) {
5166 return NT_STATUS_INVALID_PARAMETER;
5170 return NT_STATUS_INVALID_HANDLE;
5173 delete_on_close = (CVAL(pdata,0) ? True : False);
5174 dosmode = dos_mode(conn, fname, psbuf);
5176 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5177 "delete_on_close = %u\n",
5179 (unsigned int)dosmode,
5180 (unsigned int)delete_on_close ));
5182 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5184 if (!NT_STATUS_IS_OK(status)) {
5188 /* The set is across all open files on this dev/inode pair. */
5189 if (!set_delete_on_close(fsp, delete_on_close,
5190 &conn->server_info->utok)) {
5191 return NT_STATUS_ACCESS_DENIED;
5193 return NT_STATUS_OK;
5196 /****************************************************************************
5197 Deal with SMB_FILE_POSITION_INFORMATION.
5198 ****************************************************************************/
5200 static NTSTATUS smb_file_position_information(connection_struct *conn,
5205 uint64_t position_information;
5207 if (total_data < 8) {
5208 return NT_STATUS_INVALID_PARAMETER;
5212 /* Ignore on pathname based set. */
5213 return NT_STATUS_OK;
5216 position_information = (uint64_t)IVAL(pdata,0);
5217 #ifdef LARGE_SMB_OFF_T
5218 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5219 #else /* LARGE_SMB_OFF_T */
5220 if (IVAL(pdata,4) != 0) {
5221 /* more than 32 bits? */
5222 return NT_STATUS_INVALID_PARAMETER;
5224 #endif /* LARGE_SMB_OFF_T */
5226 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5227 fsp->fsp_name, (double)position_information ));
5228 fsp->fh->position_information = position_information;
5229 return NT_STATUS_OK;
5232 /****************************************************************************
5233 Deal with SMB_FILE_MODE_INFORMATION.
5234 ****************************************************************************/
5236 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5242 if (total_data < 4) {
5243 return NT_STATUS_INVALID_PARAMETER;
5245 mode = IVAL(pdata,0);
5246 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5247 return NT_STATUS_INVALID_PARAMETER;
5249 return NT_STATUS_OK;
5252 /****************************************************************************
5253 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5254 ****************************************************************************/
5256 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5257 struct smb_request *req,
5262 char *link_target = NULL;
5263 const char *newname = fname;
5264 NTSTATUS status = NT_STATUS_OK;
5265 TALLOC_CTX *ctx = talloc_tos();
5267 /* Set a symbolic link. */
5268 /* Don't allow this if follow links is false. */
5270 if (total_data == 0) {
5271 return NT_STATUS_INVALID_PARAMETER;
5274 if (!lp_symlinks(SNUM(conn))) {
5275 return NT_STATUS_ACCESS_DENIED;
5278 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5279 total_data, STR_TERMINATE);
5282 return NT_STATUS_INVALID_PARAMETER;
5285 /* !widelinks forces the target path to be within the share. */
5286 /* This means we can interpret the target as a pathname. */
5287 if (!lp_widelinks(SNUM(conn))) {
5288 char *rel_name = NULL;
5289 char *last_dirp = NULL;
5291 if (*link_target == '/') {
5292 /* No absolute paths allowed. */
5293 return NT_STATUS_ACCESS_DENIED;
5295 rel_name = talloc_strdup(ctx,newname);
5297 return NT_STATUS_NO_MEMORY;
5299 last_dirp = strrchr_m(rel_name, '/');
5301 last_dirp[1] = '\0';
5303 rel_name = talloc_strdup(ctx,"./");
5305 return NT_STATUS_NO_MEMORY;
5308 rel_name = talloc_asprintf_append(rel_name,
5312 return NT_STATUS_NO_MEMORY;
5315 status = check_name(conn, rel_name);
5316 if (!NT_STATUS_IS_OK(status)) {
5321 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5322 newname, link_target ));
5324 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5325 return map_nt_error_from_unix(errno);
5328 return NT_STATUS_OK;
5331 /****************************************************************************
5332 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5333 ****************************************************************************/
5335 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5336 struct smb_request *req,
5337 const char *pdata, int total_data,
5340 char *oldname = NULL;
5341 TALLOC_CTX *ctx = talloc_tos();
5342 NTSTATUS status = NT_STATUS_OK;
5344 /* Set a hard link. */
5345 if (total_data == 0) {
5346 return NT_STATUS_INVALID_PARAMETER;
5349 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5350 total_data, STR_TERMINATE, &status);
5351 if (!NT_STATUS_IS_OK(status)) {
5355 status = resolve_dfspath(ctx, conn,
5356 req->flags2 & FLAGS2_DFS_PATHNAMES,
5359 if (!NT_STATUS_IS_OK(status)) {
5363 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5366 return hardlink_internals(ctx, conn, oldname, fname);
5369 /****************************************************************************
5370 Deal with SMB_FILE_RENAME_INFORMATION.
5371 ****************************************************************************/
5373 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5374 struct smb_request *req,
5383 char *newname = NULL;
5384 char *base_name = NULL;
5385 bool dest_has_wcard = False;
5386 SMB_STRUCT_STAT sbuf;
5387 char *newname_last_component = NULL;
5388 NTSTATUS status = NT_STATUS_OK;
5390 TALLOC_CTX *ctx = talloc_tos();
5392 if (total_data < 13) {
5393 return NT_STATUS_INVALID_PARAMETER;
5398 overwrite = (CVAL(pdata,0) ? True : False);
5399 root_fid = IVAL(pdata,4);
5400 len = IVAL(pdata,8);
5402 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5403 return NT_STATUS_INVALID_PARAMETER;
5406 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5409 if (!NT_STATUS_IS_OK(status)) {
5413 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5416 status = resolve_dfspath_wcard(ctx, conn,
5417 req->flags2 & FLAGS2_DFS_PATHNAMES,
5421 if (!NT_STATUS_IS_OK(status)) {
5425 /* Check the new name has no '/' characters. */
5426 if (strchr_m(newname, '/')) {
5427 return NT_STATUS_NOT_SUPPORTED;
5430 if (fsp && fsp->base_fsp) {
5431 /* newname must be a stream name. */
5432 if (newname[0] != ':') {
5433 return NT_STATUS_NOT_SUPPORTED;
5435 base_name = talloc_asprintf(ctx, "%s%s",
5436 fsp->base_fsp->fsp_name,
5439 return NT_STATUS_NO_MEMORY;
5442 /* newname must *not* be a stream name. */
5443 if (is_ntfs_stream_name(newname)) {
5444 return NT_STATUS_NOT_SUPPORTED;
5447 /* Create the base directory. */
5448 base_name = talloc_strdup(ctx, fname);
5450 return NT_STATUS_NO_MEMORY;
5452 p = strrchr_m(base_name, '/');
5456 base_name = talloc_strdup(ctx, "./");
5458 return NT_STATUS_NO_MEMORY;
5461 /* Append the new name. */
5462 base_name = talloc_asprintf_append(base_name,
5466 return NT_STATUS_NO_MEMORY;
5469 status = unix_convert(ctx, conn, newname, False,
5471 &newname_last_component,
5474 /* If an error we expect this to be
5475 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5477 if (!NT_STATUS_IS_OK(status)
5478 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5485 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5486 fsp->fnum, fsp->fsp_name, base_name ));
5487 status = rename_internals_fsp(conn, fsp, base_name,
5488 newname_last_component, 0,
5491 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5492 fname, base_name ));
5493 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5494 overwrite, False, dest_has_wcard,
5495 FILE_WRITE_ATTRIBUTES);
5501 /****************************************************************************
5502 Deal with SMB_SET_POSIX_ACL.
5503 ****************************************************************************/
5505 #if defined(HAVE_POSIX_ACLS)
5506 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5511 SMB_STRUCT_STAT *psbuf)
5513 uint16 posix_acl_version;
5514 uint16 num_file_acls;
5515 uint16 num_def_acls;
5516 bool valid_file_acls = True;
5517 bool valid_def_acls = True;
5519 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5520 return NT_STATUS_INVALID_PARAMETER;
5522 posix_acl_version = SVAL(pdata,0);
5523 num_file_acls = SVAL(pdata,2);
5524 num_def_acls = SVAL(pdata,4);
5526 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5527 valid_file_acls = False;
5531 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5532 valid_def_acls = False;
5536 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5537 return NT_STATUS_INVALID_PARAMETER;
5540 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5541 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5542 return NT_STATUS_INVALID_PARAMETER;
5545 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5546 fname ? fname : fsp->fsp_name,
5547 (unsigned int)num_file_acls,
5548 (unsigned int)num_def_acls));
5550 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5551 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5552 return map_nt_error_from_unix(errno);
5555 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5556 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5557 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5558 return map_nt_error_from_unix(errno);
5560 return NT_STATUS_OK;
5564 /****************************************************************************
5565 Deal with SMB_SET_POSIX_LOCK.
5566 ****************************************************************************/
5568 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5569 struct smb_request *req,
5577 bool blocking_lock = False;
5578 enum brl_type lock_type;
5580 NTSTATUS status = NT_STATUS_OK;
5582 if (fsp == NULL || fsp->fh->fd == -1) {
5583 return NT_STATUS_INVALID_HANDLE;
5586 if (total_data != POSIX_LOCK_DATA_SIZE) {
5587 return NT_STATUS_INVALID_PARAMETER;
5590 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5591 case POSIX_LOCK_TYPE_READ:
5592 lock_type = READ_LOCK;
5594 case POSIX_LOCK_TYPE_WRITE:
5595 /* Return the right POSIX-mappable error code for files opened read-only. */
5596 if (!fsp->can_write) {
5597 return NT_STATUS_INVALID_HANDLE;
5599 lock_type = WRITE_LOCK;
5601 case POSIX_LOCK_TYPE_UNLOCK:
5602 lock_type = UNLOCK_LOCK;
5605 return NT_STATUS_INVALID_PARAMETER;
5608 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5609 blocking_lock = False;
5610 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5611 blocking_lock = True;
5613 return NT_STATUS_INVALID_PARAMETER;
5616 if (!lp_blocking_locks(SNUM(conn))) {
5617 blocking_lock = False;
5620 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5621 #if defined(HAVE_LONGLONG)
5622 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5623 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5624 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5625 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5626 #else /* HAVE_LONGLONG */
5627 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5628 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5629 #endif /* HAVE_LONGLONG */
5631 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5632 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5634 (unsigned int)lock_type,
5635 (unsigned int)lock_pid,
5639 if (lock_type == UNLOCK_LOCK) {
5640 status = do_unlock(smbd_messaging_context(),
5647 uint32 block_smbpid;
5649 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5661 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5663 * A blocking lock was requested. Package up
5664 * this smb into a queued request and push it
5665 * onto the blocking lock queue.
5667 if(push_blocking_lock_request(br_lck,
5670 -1, /* infinite timeout. */
5678 TALLOC_FREE(br_lck);
5682 TALLOC_FREE(br_lck);
5688 /****************************************************************************
5689 Deal with SMB_INFO_STANDARD.
5690 ****************************************************************************/
5692 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5697 const SMB_STRUCT_STAT *psbuf)
5699 struct smb_file_time ft;
5702 if (total_data < 12) {
5703 return NT_STATUS_INVALID_PARAMETER;
5707 ft.create_time = interpret_long_date(pdata);
5710 ft.atime = interpret_long_date(pdata + 8);
5713 ft.mtime = interpret_long_date(pdata + 16);
5715 DEBUG(10,("smb_set_info_standard: file %s\n",
5716 fname ? fname : fsp->fsp_name ));
5718 return smb_set_file_time(conn,
5726 /****************************************************************************
5727 Deal with SMB_SET_FILE_BASIC_INFO.
5728 ****************************************************************************/
5730 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5735 SMB_STRUCT_STAT *psbuf)
5737 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5738 struct timespec write_time;
5739 struct timespec changed_time;
5740 struct smb_file_time ft;
5742 NTSTATUS status = NT_STATUS_OK;
5743 bool setting_write_time = true;
5747 if (total_data < 36) {
5748 return NT_STATUS_INVALID_PARAMETER;
5751 /* Set the attributes */
5752 dosmode = IVAL(pdata,32);
5753 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5754 if (!NT_STATUS_IS_OK(status)) {
5759 ft.atime = interpret_long_date(pdata+8);
5761 write_time = interpret_long_date(pdata+16);
5762 changed_time = interpret_long_date(pdata+24);
5765 ft.mtime = timespec_min(&write_time, &changed_time);
5768 ft.create_time = interpret_long_date(pdata);
5770 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5771 !null_timespec(write_time)) {
5772 ft.mtime = write_time;
5775 /* Prefer a defined time to an undefined one. */
5776 if (null_timespec(ft.mtime)) {
5777 if (null_timespec(write_time)) {
5778 ft.mtime = changed_time;
5779 setting_write_time = false;
5781 ft.mtime = write_time;
5785 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5786 fname ? fname : fsp->fsp_name ));
5788 return smb_set_file_time(conn,
5793 setting_write_time);
5796 /****************************************************************************
5797 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5798 ****************************************************************************/
5800 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5801 struct smb_request *req,
5806 SMB_STRUCT_STAT *psbuf)
5808 uint64_t allocation_size = 0;
5809 NTSTATUS status = NT_STATUS_OK;
5810 files_struct *new_fsp = NULL;
5812 if (!VALID_STAT(*psbuf)) {
5813 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5816 if (total_data < 8) {
5817 return NT_STATUS_INVALID_PARAMETER;
5820 allocation_size = (uint64_t)IVAL(pdata,0);
5821 #ifdef LARGE_SMB_OFF_T
5822 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5823 #else /* LARGE_SMB_OFF_T */
5824 if (IVAL(pdata,4) != 0) {
5825 /* more than 32 bits? */
5826 return NT_STATUS_INVALID_PARAMETER;
5828 #endif /* LARGE_SMB_OFF_T */
5830 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5831 fname, (double)allocation_size ));
5833 if (allocation_size) {
5834 allocation_size = smb_roundup(conn, allocation_size);
5837 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5838 fname, (double)allocation_size ));
5840 if (fsp && fsp->fh->fd != -1) {
5841 /* Open file handle. */
5842 /* Only change if needed. */
5843 if (allocation_size != get_file_size_stat(psbuf)) {
5844 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5845 return map_nt_error_from_unix(errno);
5848 /* But always update the time. */
5850 * This is equivalent to a write. Ensure it's seen immediately
5851 * if there are no pending writes.
5853 trigger_write_time_update_immediate(fsp);
5854 return NT_STATUS_OK;
5857 /* Pathname or stat or directory file. */
5859 status = SMB_VFS_CREATE_FILE(
5862 0, /* root_dir_fid */
5864 0, /* create_file_flags */
5865 FILE_WRITE_DATA, /* access_mask */
5866 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5868 FILE_OPEN, /* create_disposition*/
5869 0, /* create_options */
5870 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5871 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5872 0, /* allocation_size */
5875 &new_fsp, /* result */
5879 if (!NT_STATUS_IS_OK(status)) {
5880 /* NB. We check for open_was_deferred in the caller. */
5884 /* Only change if needed. */
5885 if (allocation_size != get_file_size_stat(psbuf)) {
5886 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5887 status = map_nt_error_from_unix(errno);
5888 close_file(req, new_fsp, NORMAL_CLOSE);
5893 /* Changing the allocation size should set the last mod time. */
5895 * This is equivalent to a write. Ensure it's seen immediately
5896 * if there are no pending writes.
5898 trigger_write_time_update_immediate(new_fsp);
5900 close_file(req, new_fsp, NORMAL_CLOSE);
5901 return NT_STATUS_OK;
5904 /****************************************************************************
5905 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5906 ****************************************************************************/
5908 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5909 struct smb_request *req,
5914 SMB_STRUCT_STAT *psbuf)
5918 if (total_data < 8) {
5919 return NT_STATUS_INVALID_PARAMETER;
5922 size = IVAL(pdata,0);
5923 #ifdef LARGE_SMB_OFF_T
5924 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5925 #else /* LARGE_SMB_OFF_T */
5926 if (IVAL(pdata,4) != 0) {
5927 /* more than 32 bits? */
5928 return NT_STATUS_INVALID_PARAMETER;
5930 #endif /* LARGE_SMB_OFF_T */
5931 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5932 "file %s to %.0f\n", fname, (double)size ));
5934 return smb_set_file_size(conn, req,
5941 /****************************************************************************
5942 Allow a UNIX info mknod.
5943 ****************************************************************************/
5945 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5949 SMB_STRUCT_STAT *psbuf)
5951 uint32 file_type = IVAL(pdata,56);
5952 #if defined(HAVE_MAKEDEV)
5953 uint32 dev_major = IVAL(pdata,60);
5954 uint32 dev_minor = IVAL(pdata,68);
5956 SMB_DEV_T dev = (SMB_DEV_T)0;
5957 uint32 raw_unixmode = IVAL(pdata,84);
5961 if (total_data < 100) {
5962 return NT_STATUS_INVALID_PARAMETER;
5965 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5966 if (!NT_STATUS_IS_OK(status)) {
5970 #if defined(HAVE_MAKEDEV)
5971 dev = makedev(dev_major, dev_minor);
5974 switch (file_type) {
5975 #if defined(S_IFIFO)
5976 case UNIX_TYPE_FIFO:
5977 unixmode |= S_IFIFO;
5980 #if defined(S_IFSOCK)
5981 case UNIX_TYPE_SOCKET:
5982 unixmode |= S_IFSOCK;
5985 #if defined(S_IFCHR)
5986 case UNIX_TYPE_CHARDEV:
5987 unixmode |= S_IFCHR;
5990 #if defined(S_IFBLK)
5991 case UNIX_TYPE_BLKDEV:
5992 unixmode |= S_IFBLK;
5996 return NT_STATUS_INVALID_PARAMETER;
5999 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6000 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6002 /* Ok - do the mknod. */
6003 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6004 return map_nt_error_from_unix(errno);
6007 /* If any of the other "set" calls fail we
6008 * don't want to end up with a half-constructed mknod.
6011 if (lp_inherit_perms(SNUM(conn))) {
6013 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6014 return NT_STATUS_NO_MEMORY;
6016 inherit_access_posix_acl(conn, parent, fname, unixmode);
6017 TALLOC_FREE(parent);
6020 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6021 status = map_nt_error_from_unix(errno);
6022 SMB_VFS_UNLINK(conn,fname);
6025 return NT_STATUS_OK;
6028 /****************************************************************************
6029 Deal with SMB_SET_FILE_UNIX_BASIC.
6030 ****************************************************************************/
6032 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6033 struct smb_request *req,
6038 SMB_STRUCT_STAT *psbuf)
6040 struct smb_file_time ft;
6041 uint32 raw_unixmode;
6044 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6045 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6046 NTSTATUS status = NT_STATUS_OK;
6047 bool delete_on_fail = False;
6048 enum perm_type ptype;
6052 if (total_data < 100) {
6053 return NT_STATUS_INVALID_PARAMETER;
6056 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6057 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6058 size=IVAL(pdata,0); /* first 8 Bytes are size */
6059 #ifdef LARGE_SMB_OFF_T
6060 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6061 #else /* LARGE_SMB_OFF_T */
6062 if (IVAL(pdata,4) != 0) {
6063 /* more than 32 bits? */
6064 return NT_STATUS_INVALID_PARAMETER;
6066 #endif /* LARGE_SMB_OFF_T */
6069 ft.atime = interpret_long_date(pdata+24); /* access_time */
6070 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6071 set_owner = (uid_t)IVAL(pdata,40);
6072 set_grp = (gid_t)IVAL(pdata,48);
6073 raw_unixmode = IVAL(pdata,84);
6075 if (VALID_STAT(*psbuf)) {
6076 if (S_ISDIR(psbuf->st_mode)) {
6077 ptype = PERM_EXISTING_DIR;
6079 ptype = PERM_EXISTING_FILE;
6082 ptype = PERM_NEW_FILE;
6085 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6086 if (!NT_STATUS_IS_OK(status)) {
6090 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6091 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6092 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6094 if (!VALID_STAT(*psbuf)) {
6096 * The only valid use of this is to create character and block
6097 * devices, and named pipes. This is deprecated (IMHO) and
6098 * a new info level should be used for mknod. JRA.
6101 status = smb_unix_mknod(conn,
6106 if (!NT_STATUS_IS_OK(status)) {
6110 /* Ensure we don't try and change anything else. */
6111 raw_unixmode = SMB_MODE_NO_CHANGE;
6112 size = get_file_size_stat(psbuf);
6113 ft.atime = get_atimespec(psbuf);
6114 ft.mtime = get_mtimespec(psbuf);
6116 * We continue here as we might want to change the
6119 delete_on_fail = True;
6123 /* Horrible backwards compatibility hack as an old server bug
6124 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6128 size = get_file_size_stat(psbuf);
6133 * Deal with the UNIX specific mode set.
6136 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6137 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6138 (unsigned int)unixmode, fname ));
6139 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6140 return map_nt_error_from_unix(errno);
6145 * Deal with the UNIX specific uid set.
6148 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6151 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6152 (unsigned int)set_owner, fname ));
6154 if (S_ISLNK(psbuf->st_mode)) {
6155 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6157 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6161 status = map_nt_error_from_unix(errno);
6162 if (delete_on_fail) {
6163 SMB_VFS_UNLINK(conn,fname);
6170 * Deal with the UNIX specific gid set.
6173 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6174 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6175 (unsigned int)set_owner, fname ));
6176 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6177 status = map_nt_error_from_unix(errno);
6178 if (delete_on_fail) {
6179 SMB_VFS_UNLINK(conn,fname);
6185 /* Deal with any size changes. */
6187 status = smb_set_file_size(conn, req,
6192 if (!NT_STATUS_IS_OK(status)) {
6196 /* Deal with any time changes. */
6198 return smb_set_file_time(conn,
6206 /****************************************************************************
6207 Deal with SMB_SET_FILE_UNIX_INFO2.
6208 ****************************************************************************/
6210 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6211 struct smb_request *req,
6216 SMB_STRUCT_STAT *psbuf)
6222 if (total_data < 116) {
6223 return NT_STATUS_INVALID_PARAMETER;
6226 /* Start by setting all the fields that are common between UNIX_BASIC
6229 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6231 if (!NT_STATUS_IS_OK(status)) {
6235 smb_fflags = IVAL(pdata, 108);
6236 smb_fmask = IVAL(pdata, 112);
6238 /* NB: We should only attempt to alter the file flags if the client
6239 * sends a non-zero mask.
6241 if (smb_fmask != 0) {
6242 int stat_fflags = 0;
6244 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6246 /* Client asked to alter a flag we don't understand. */
6247 return NT_STATUS_INVALID_PARAMETER;
6250 if (fsp && fsp->fh->fd != -1) {
6251 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6252 return NT_STATUS_NOT_SUPPORTED;
6254 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6255 return map_nt_error_from_unix(errno);
6260 /* XXX: need to add support for changing the create_time here. You
6261 * can do this for paths on Darwin with setattrlist(2). The right way
6262 * to hook this up is probably by extending the VFS utimes interface.
6265 return NT_STATUS_OK;
6268 /****************************************************************************
6269 Create a directory with POSIX semantics.
6270 ****************************************************************************/
6272 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6273 struct smb_request *req,
6277 SMB_STRUCT_STAT *psbuf,
6278 int *pdata_return_size)
6280 NTSTATUS status = NT_STATUS_OK;
6281 uint32 raw_unixmode = 0;
6282 uint32 mod_unixmode = 0;
6283 mode_t unixmode = (mode_t)0;
6284 files_struct *fsp = NULL;
6285 uint16 info_level_return = 0;
6287 char *pdata = *ppdata;
6289 if (total_data < 18) {
6290 return NT_STATUS_INVALID_PARAMETER;
6293 raw_unixmode = IVAL(pdata,8);
6294 /* Next 4 bytes are not yet defined. */
6296 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6297 if (!NT_STATUS_IS_OK(status)) {
6301 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6303 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6304 fname, (unsigned int)unixmode ));
6306 status = SMB_VFS_CREATE_FILE(
6309 0, /* root_dir_fid */
6311 0, /* create_file_flags */
6312 FILE_READ_ATTRIBUTES, /* access_mask */
6313 FILE_SHARE_NONE, /* share_access */
6314 FILE_CREATE, /* create_disposition*/
6315 FILE_DIRECTORY_FILE, /* create_options */
6316 mod_unixmode, /* file_attributes */
6317 0, /* oplock_request */
6318 0, /* allocation_size */
6325 if (NT_STATUS_IS_OK(status)) {
6326 close_file(req, fsp, NORMAL_CLOSE);
6329 info_level_return = SVAL(pdata,16);
6331 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6332 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6333 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6334 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6336 *pdata_return_size = 12;
6339 /* Realloc the data size */
6340 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6341 if (*ppdata == NULL) {
6342 *pdata_return_size = 0;
6343 return NT_STATUS_NO_MEMORY;
6347 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6348 SSVAL(pdata,2,0); /* No fnum. */
6349 SIVAL(pdata,4,info); /* Was directory created. */
6351 switch (info_level_return) {
6352 case SMB_QUERY_FILE_UNIX_BASIC:
6353 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6354 SSVAL(pdata,10,0); /* Padding. */
6355 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6357 case SMB_QUERY_FILE_UNIX_INFO2:
6358 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6359 SSVAL(pdata,10,0); /* Padding. */
6360 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6363 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6364 SSVAL(pdata,10,0); /* Padding. */
6371 /****************************************************************************
6372 Open/Create a file with POSIX semantics.
6373 ****************************************************************************/
6375 static NTSTATUS smb_posix_open(connection_struct *conn,
6376 struct smb_request *req,
6380 SMB_STRUCT_STAT *psbuf,
6381 int *pdata_return_size)
6383 bool extended_oplock_granted = False;
6384 char *pdata = *ppdata;
6386 uint32 wire_open_mode = 0;
6387 uint32 raw_unixmode = 0;
6388 uint32 mod_unixmode = 0;
6389 uint32 create_disp = 0;
6390 uint32 access_mask = 0;
6391 uint32 create_options = 0;
6392 NTSTATUS status = NT_STATUS_OK;
6393 mode_t unixmode = (mode_t)0;
6394 files_struct *fsp = NULL;
6395 int oplock_request = 0;
6397 uint16 info_level_return = 0;
6399 if (total_data < 18) {
6400 return NT_STATUS_INVALID_PARAMETER;
6403 flags = IVAL(pdata,0);
6404 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6405 if (oplock_request) {
6406 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6409 wire_open_mode = IVAL(pdata,4);
6411 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6412 return smb_posix_mkdir(conn, req,
6420 switch (wire_open_mode & SMB_ACCMODE) {
6422 access_mask = FILE_READ_DATA;
6425 access_mask = FILE_WRITE_DATA;
6428 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6431 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6432 (unsigned int)wire_open_mode ));
6433 return NT_STATUS_INVALID_PARAMETER;
6436 wire_open_mode &= ~SMB_ACCMODE;
6438 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6439 create_disp = FILE_CREATE;
6440 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6441 create_disp = FILE_OVERWRITE_IF;
6442 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6443 create_disp = FILE_OPEN_IF;
6444 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6445 create_disp = FILE_OPEN;
6447 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6448 (unsigned int)wire_open_mode ));
6449 return NT_STATUS_INVALID_PARAMETER;
6452 raw_unixmode = IVAL(pdata,8);
6453 /* Next 4 bytes are not yet defined. */
6455 status = unix_perms_from_wire(conn,
6458 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6461 if (!NT_STATUS_IS_OK(status)) {
6465 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6467 if (wire_open_mode & SMB_O_SYNC) {
6468 create_options |= FILE_WRITE_THROUGH;
6470 if (wire_open_mode & SMB_O_APPEND) {
6471 access_mask |= FILE_APPEND_DATA;
6473 if (wire_open_mode & SMB_O_DIRECT) {
6474 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6477 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6479 (unsigned int)wire_open_mode,
6480 (unsigned int)unixmode ));
6482 status = SMB_VFS_CREATE_FILE(
6485 0, /* root_dir_fid */
6487 0, /* create_file_flags */
6488 access_mask, /* access_mask */
6489 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6491 create_disp, /* create_disposition*/
6492 0, /* create_options */
6493 mod_unixmode, /* file_attributes */
6494 oplock_request, /* oplock_request */
6495 0, /* allocation_size */
6502 if (!NT_STATUS_IS_OK(status)) {
6506 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6507 extended_oplock_granted = True;
6510 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6511 extended_oplock_granted = True;
6514 info_level_return = SVAL(pdata,16);
6516 /* Allocate the correct return size. */
6518 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6519 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6520 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6521 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6523 *pdata_return_size = 12;
6526 /* Realloc the data size */
6527 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6528 if (*ppdata == NULL) {
6529 close_file(req, fsp, ERROR_CLOSE);
6530 *pdata_return_size = 0;
6531 return NT_STATUS_NO_MEMORY;
6535 if (extended_oplock_granted) {
6536 if (flags & REQUEST_BATCH_OPLOCK) {
6537 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6539 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6541 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6542 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6544 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6547 SSVAL(pdata,2,fsp->fnum);
6548 SIVAL(pdata,4,info); /* Was file created etc. */
6550 switch (info_level_return) {
6551 case SMB_QUERY_FILE_UNIX_BASIC:
6552 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6553 SSVAL(pdata,10,0); /* padding. */
6554 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6556 case SMB_QUERY_FILE_UNIX_INFO2:
6557 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6558 SSVAL(pdata,10,0); /* padding. */
6559 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6562 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6563 SSVAL(pdata,10,0); /* padding. */
6566 return NT_STATUS_OK;
6569 /****************************************************************************
6570 Delete a file with POSIX semantics.
6571 ****************************************************************************/
6573 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6574 struct smb_request *req,
6578 SMB_STRUCT_STAT *psbuf)
6580 NTSTATUS status = NT_STATUS_OK;
6581 files_struct *fsp = NULL;
6585 int create_options = 0;
6587 struct share_mode_lock *lck = NULL;
6589 if (total_data < 2) {
6590 return NT_STATUS_INVALID_PARAMETER;
6593 flags = SVAL(pdata,0);
6595 if (!VALID_STAT(*psbuf)) {
6596 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6599 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6600 !VALID_STAT_OF_DIR(*psbuf)) {
6601 return NT_STATUS_NOT_A_DIRECTORY;
6604 DEBUG(10,("smb_posix_unlink: %s %s\n",
6605 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6608 if (VALID_STAT_OF_DIR(*psbuf)) {
6609 create_options |= FILE_DIRECTORY_FILE;
6612 status = SMB_VFS_CREATE_FILE(
6615 0, /* root_dir_fid */
6617 0, /* create_file_flags */
6618 DELETE_ACCESS, /* access_mask */
6619 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6621 FILE_OPEN, /* create_disposition*/
6622 create_options, /* create_options */
6623 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6624 0, /* oplock_request */
6625 0, /* allocation_size */
6632 if (!NT_STATUS_IS_OK(status)) {
6637 * Don't lie to client. If we can't really delete due to
6638 * non-POSIX opens return SHARING_VIOLATION.
6641 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6644 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6645 "lock for file %s\n", fsp->fsp_name));
6646 close_file(req, fsp, NORMAL_CLOSE);
6647 return NT_STATUS_INVALID_PARAMETER;
6651 * See if others still have the file open. If this is the case, then
6652 * don't delete. If all opens are POSIX delete we can set the delete
6653 * on close disposition.
6655 for (i=0; i<lck->num_share_modes; i++) {
6656 struct share_mode_entry *e = &lck->share_modes[i];
6657 if (is_valid_share_mode_entry(e)) {
6658 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6661 /* Fail with sharing violation. */
6662 close_file(req, fsp, NORMAL_CLOSE);
6664 return NT_STATUS_SHARING_VIOLATION;
6669 * Set the delete on close.
6671 status = smb_set_file_disposition_info(conn,
6678 if (!NT_STATUS_IS_OK(status)) {
6679 close_file(req, fsp, NORMAL_CLOSE);
6684 return close_file(req, fsp, NORMAL_CLOSE);
6687 /****************************************************************************
6688 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6689 ****************************************************************************/
6691 static void call_trans2setfilepathinfo(connection_struct *conn,
6692 struct smb_request *req,
6693 unsigned int tran_call,
6694 char **pparams, int total_params,
6695 char **ppdata, int total_data,
6696 unsigned int max_data_bytes)
6698 char *params = *pparams;
6699 char *pdata = *ppdata;
6701 SMB_STRUCT_STAT sbuf;
6703 files_struct *fsp = NULL;
6704 NTSTATUS status = NT_STATUS_OK;
6705 int data_return_size = 0;
6706 TALLOC_CTX *ctx = talloc_tos();
6709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6715 if (tran_call == TRANSACT2_SETFILEINFO) {
6716 if (total_params < 4) {
6717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6721 fsp = file_fsp(req, SVAL(params,0));
6722 /* Basic check for non-null fsp. */
6723 if (!check_fsp_open(conn, req, fsp)) {
6726 info_level = SVAL(params,2);
6728 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6730 reply_nterror(req, NT_STATUS_NO_MEMORY);
6734 if(fsp->is_directory || fsp->fh->fd == -1) {
6736 * This is actually a SETFILEINFO on a directory
6737 * handle (returned from an NT SMB). NT5.0 seems
6738 * to do this call. JRA.
6740 if (INFO_LEVEL_IS_UNIX(info_level)) {
6741 /* Always do lstat for UNIX calls. */
6742 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6743 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6744 reply_unixerror(req,ERRDOS,ERRbadpath);
6748 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6749 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6750 reply_unixerror(req,ERRDOS,ERRbadpath);
6754 } else if (fsp->print_file) {
6756 * Doing a DELETE_ON_CLOSE should cancel a print job.
6758 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6759 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6761 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6764 send_trans2_replies(conn, req, params, 2,
6769 reply_unixerror(req, ERRDOS, ERRbadpath);
6774 * Original code - this is an open file.
6776 if (!check_fsp(conn, req, fsp)) {
6780 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6781 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6782 reply_unixerror(req, ERRDOS, ERRbadfid);
6788 if (total_params < 7) {
6789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6793 info_level = SVAL(params,0);
6794 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6795 total_params - 6, STR_TERMINATE,
6797 if (!NT_STATUS_IS_OK(status)) {
6798 reply_nterror(req, status);
6802 status = resolve_dfspath(ctx, conn,
6803 req->flags2 & FLAGS2_DFS_PATHNAMES,
6806 if (!NT_STATUS_IS_OK(status)) {
6807 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6808 reply_botherror(req,
6809 NT_STATUS_PATH_NOT_COVERED,
6810 ERRSRV, ERRbadpath);
6813 reply_nterror(req, status);
6817 status = unix_convert(ctx, conn, fname, False,
6818 &fname, NULL, &sbuf);
6819 if (!NT_STATUS_IS_OK(status)) {
6820 reply_nterror(req, status);
6824 status = check_name(conn, fname);
6825 if (!NT_STATUS_IS_OK(status)) {
6826 reply_nterror(req, status);
6830 if (INFO_LEVEL_IS_UNIX(info_level)) {
6832 * For CIFS UNIX extensions the target name may not exist.
6835 /* Always do lstat for UNIX calls. */
6836 SMB_VFS_LSTAT(conn,fname,&sbuf);
6838 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6839 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6840 reply_unixerror(req, ERRDOS, ERRbadpath);
6845 if (!CAN_WRITE(conn)) {
6846 reply_doserror(req, ERRSRV, ERRaccess);
6850 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6851 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6855 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6856 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6858 /* Realloc the parameter size */
6859 *pparams = (char *)SMB_REALLOC(*pparams,2);
6860 if (*pparams == NULL) {
6861 reply_nterror(req, NT_STATUS_NO_MEMORY);
6868 switch (info_level) {
6870 case SMB_INFO_STANDARD:
6872 status = smb_set_info_standard(conn,
6881 case SMB_INFO_SET_EA:
6883 status = smb_info_set_ea(conn,
6891 case SMB_SET_FILE_BASIC_INFO:
6892 case SMB_FILE_BASIC_INFORMATION:
6894 status = smb_set_file_basic_info(conn,
6903 case SMB_FILE_ALLOCATION_INFORMATION:
6904 case SMB_SET_FILE_ALLOCATION_INFO:
6906 status = smb_set_file_allocation_info(conn, req,
6915 case SMB_FILE_END_OF_FILE_INFORMATION:
6916 case SMB_SET_FILE_END_OF_FILE_INFO:
6918 status = smb_set_file_end_of_file_info(conn, req,
6927 case SMB_FILE_DISPOSITION_INFORMATION:
6928 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6931 /* JRA - We used to just ignore this on a path ?
6932 * Shouldn't this be invalid level on a pathname
6935 if (tran_call != TRANSACT2_SETFILEINFO) {
6936 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6939 status = smb_set_file_disposition_info(conn,
6948 case SMB_FILE_POSITION_INFORMATION:
6950 status = smb_file_position_information(conn,
6957 /* From tridge Samba4 :
6958 * MODE_INFORMATION in setfileinfo (I have no
6959 * idea what "mode information" on a file is - it takes a value of 0,
6960 * 2, 4 or 6. What could it be?).
6963 case SMB_FILE_MODE_INFORMATION:
6965 status = smb_file_mode_information(conn,
6972 * CIFS UNIX extensions.
6975 case SMB_SET_FILE_UNIX_BASIC:
6977 status = smb_set_file_unix_basic(conn, req,
6986 case SMB_SET_FILE_UNIX_INFO2:
6988 status = smb_set_file_unix_info2(conn, req,
6997 case SMB_SET_FILE_UNIX_LINK:
6999 if (tran_call != TRANSACT2_SETPATHINFO) {
7000 /* We must have a pathname for this. */
7001 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7004 status = smb_set_file_unix_link(conn, req, pdata,
7009 case SMB_SET_FILE_UNIX_HLINK:
7011 if (tran_call != TRANSACT2_SETPATHINFO) {
7012 /* We must have a pathname for this. */
7013 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7016 status = smb_set_file_unix_hlink(conn, req,
7022 case SMB_FILE_RENAME_INFORMATION:
7024 status = smb_file_rename_information(conn, req,
7030 #if defined(HAVE_POSIX_ACLS)
7031 case SMB_SET_POSIX_ACL:
7033 status = smb_set_posix_acl(conn,
7043 case SMB_SET_POSIX_LOCK:
7045 if (tran_call != TRANSACT2_SETFILEINFO) {
7046 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7049 status = smb_set_posix_lock(conn, req,
7050 pdata, total_data, fsp);
7054 case SMB_POSIX_PATH_OPEN:
7056 if (tran_call != TRANSACT2_SETPATHINFO) {
7057 /* We must have a pathname for this. */
7058 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7062 status = smb_posix_open(conn, req,
7071 case SMB_POSIX_PATH_UNLINK:
7073 if (tran_call != TRANSACT2_SETPATHINFO) {
7074 /* We must have a pathname for this. */
7075 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7079 status = smb_posix_unlink(conn, req,
7088 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7093 if (!NT_STATUS_IS_OK(status)) {
7094 if (open_was_deferred(req->mid)) {
7095 /* We have re-scheduled this call. */
7098 if (blocking_lock_was_deferred(req->mid)) {
7099 /* We have re-scheduled this call. */
7102 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7103 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7104 ERRSRV, ERRbadpath);
7107 if (info_level == SMB_POSIX_PATH_OPEN) {
7108 reply_openerror(req, status);
7112 reply_nterror(req, status);
7117 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7123 /****************************************************************************
7124 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7125 ****************************************************************************/
7127 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7128 char **pparams, int total_params,
7129 char **ppdata, int total_data,
7130 unsigned int max_data_bytes)
7132 char *params = *pparams;
7133 char *pdata = *ppdata;
7134 char *directory = NULL;
7135 SMB_STRUCT_STAT sbuf;
7136 NTSTATUS status = NT_STATUS_OK;
7137 struct ea_list *ea_list = NULL;
7138 TALLOC_CTX *ctx = talloc_tos();
7140 if (!CAN_WRITE(conn)) {
7141 reply_doserror(req, ERRSRV, ERRaccess);
7145 if (total_params < 5) {
7146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7150 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7151 total_params - 4, STR_TERMINATE,
7153 if (!NT_STATUS_IS_OK(status)) {
7154 reply_nterror(req, status);
7158 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7160 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7161 if (!NT_STATUS_IS_OK(status)) {
7162 reply_nterror(req, status);
7166 status = check_name(conn, directory);
7167 if (!NT_STATUS_IS_OK(status)) {
7168 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7169 reply_nterror(req, status);
7173 /* Any data in this call is an EA list. */
7174 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7175 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7180 * OS/2 workplace shell seems to send SET_EA requests of "null"
7181 * length (4 bytes containing IVAL 4).
7182 * They seem to have no effect. Bug #3212. JRA.
7185 if (total_data != 4) {
7186 if (total_data < 10) {
7187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7191 if (IVAL(pdata,0) > total_data) {
7192 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7193 IVAL(pdata,0), (unsigned int)total_data));
7194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7198 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7205 /* If total_data == 4 Windows doesn't care what values
7206 * are placed in that field, it just ignores them.
7207 * The System i QNTC IBM SMB client puts bad values here,
7208 * so ignore them. */
7210 status = create_directory(conn, req, directory);
7212 if (!NT_STATUS_IS_OK(status)) {
7213 reply_nterror(req, status);
7217 /* Try and set any given EA. */
7219 status = set_ea(conn, NULL, directory, ea_list);
7220 if (!NT_STATUS_IS_OK(status)) {
7221 reply_nterror(req, status);
7226 /* Realloc the parameter and data sizes */
7227 *pparams = (char *)SMB_REALLOC(*pparams,2);
7228 if(*pparams == NULL) {
7229 reply_nterror(req, NT_STATUS_NO_MEMORY);
7236 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7241 /****************************************************************************
7242 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7243 We don't actually do this - we just send a null response.
7244 ****************************************************************************/
7246 static void call_trans2findnotifyfirst(connection_struct *conn,
7247 struct smb_request *req,
7248 char **pparams, int total_params,
7249 char **ppdata, int total_data,
7250 unsigned int max_data_bytes)
7252 char *params = *pparams;
7255 if (total_params < 6) {
7256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7260 info_level = SVAL(params,4);
7261 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7263 switch (info_level) {
7268 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7272 /* Realloc the parameter and data sizes */
7273 *pparams = (char *)SMB_REALLOC(*pparams,6);
7274 if (*pparams == NULL) {
7275 reply_nterror(req, NT_STATUS_NO_MEMORY);
7280 SSVAL(params,0,fnf_handle);
7281 SSVAL(params,2,0); /* No changes */
7282 SSVAL(params,4,0); /* No EA errors */
7289 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7294 /****************************************************************************
7295 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7296 changes). Currently this does nothing.
7297 ****************************************************************************/
7299 static void call_trans2findnotifynext(connection_struct *conn,
7300 struct smb_request *req,
7301 char **pparams, int total_params,
7302 char **ppdata, int total_data,
7303 unsigned int max_data_bytes)
7305 char *params = *pparams;
7307 DEBUG(3,("call_trans2findnotifynext\n"));
7309 /* Realloc the parameter and data sizes */
7310 *pparams = (char *)SMB_REALLOC(*pparams,4);
7311 if (*pparams == NULL) {
7312 reply_nterror(req, NT_STATUS_NO_MEMORY);
7317 SSVAL(params,0,0); /* No changes */
7318 SSVAL(params,2,0); /* No EA errors */
7320 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7325 /****************************************************************************
7326 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7327 ****************************************************************************/
7329 static void call_trans2getdfsreferral(connection_struct *conn,
7330 struct smb_request *req,
7331 char **pparams, int total_params,
7332 char **ppdata, int total_data,
7333 unsigned int max_data_bytes)
7335 char *params = *pparams;
7336 char *pathname = NULL;
7338 int max_referral_level;
7339 NTSTATUS status = NT_STATUS_OK;
7340 TALLOC_CTX *ctx = talloc_tos();
7342 DEBUG(10,("call_trans2getdfsreferral\n"));
7344 if (total_params < 3) {
7345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7349 max_referral_level = SVAL(params,0);
7351 if(!lp_host_msdfs()) {
7352 reply_doserror(req, ERRDOS, ERRbadfunc);
7356 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7357 total_params - 2, STR_TERMINATE);
7359 reply_nterror(req, NT_STATUS_NOT_FOUND);
7362 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7363 ppdata,&status)) < 0) {
7364 reply_nterror(req, status);
7368 SSVAL(req->inbuf, smb_flg2,
7369 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7370 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7375 #define LMCAT_SPL 0x53
7376 #define LMFUNC_GETJOBID 0x60
7378 /****************************************************************************
7379 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7380 ****************************************************************************/
7382 static void call_trans2ioctl(connection_struct *conn,
7383 struct smb_request *req,
7384 char **pparams, int total_params,
7385 char **ppdata, int total_data,
7386 unsigned int max_data_bytes)
7388 char *pdata = *ppdata;
7389 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7391 /* check for an invalid fid before proceeding */
7394 reply_doserror(req, ERRDOS, ERRbadfid);
7398 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7399 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7400 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7401 if (*ppdata == NULL) {
7402 reply_nterror(req, NT_STATUS_NO_MEMORY);
7407 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7408 CAN ACCEPT THIS IN UNICODE. JRA. */
7410 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7411 srvstr_push(pdata, req->flags2, pdata + 2,
7412 global_myname(), 15,
7413 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7414 srvstr_push(pdata, req->flags2, pdata+18,
7415 lp_servicename(SNUM(conn)), 13,
7416 STR_ASCII|STR_TERMINATE); /* Service name */
7417 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7422 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7423 reply_doserror(req, ERRSRV, ERRerror);
7426 /****************************************************************************
7427 Reply to a SMBfindclose (stop trans2 directory search).
7428 ****************************************************************************/
7430 void reply_findclose(struct smb_request *req)
7434 START_PROFILE(SMBfindclose);
7437 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7438 END_PROFILE(SMBfindclose);
7442 dptr_num = SVALS(req->vwv+0, 0);
7444 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7446 dptr_close(&dptr_num);
7448 reply_outbuf(req, 0, 0);
7450 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7452 END_PROFILE(SMBfindclose);
7456 /****************************************************************************
7457 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7458 ****************************************************************************/
7460 void reply_findnclose(struct smb_request *req)
7464 START_PROFILE(SMBfindnclose);
7467 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7468 END_PROFILE(SMBfindnclose);
7472 dptr_num = SVAL(req->vwv+0, 0);
7474 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7476 /* We never give out valid handles for a
7477 findnotifyfirst - so any dptr_num is ok here.
7480 reply_outbuf(req, 0, 0);
7482 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7484 END_PROFILE(SMBfindnclose);
7488 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7489 struct trans_state *state)
7491 if (Protocol >= PROTOCOL_NT1) {
7492 req->flags2 |= 0x40; /* IS_LONG_NAME */
7493 SSVAL(req->inbuf,smb_flg2,req->flags2);
7496 if (conn->encrypt_level == Required && !req->encrypted) {
7497 if (state->call != TRANSACT2_QFSINFO &&
7498 state->call != TRANSACT2_SETFSINFO) {
7499 DEBUG(0,("handle_trans2: encryption required "
7501 (unsigned int)state->call));
7502 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7507 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7509 /* Now we must call the relevant TRANS2 function */
7510 switch(state->call) {
7511 case TRANSACT2_OPEN:
7513 START_PROFILE(Trans2_open);
7514 call_trans2open(conn, req,
7515 &state->param, state->total_param,
7516 &state->data, state->total_data,
7517 state->max_data_return);
7518 END_PROFILE(Trans2_open);
7522 case TRANSACT2_FINDFIRST:
7524 START_PROFILE(Trans2_findfirst);
7525 call_trans2findfirst(conn, req,
7526 &state->param, state->total_param,
7527 &state->data, state->total_data,
7528 state->max_data_return);
7529 END_PROFILE(Trans2_findfirst);
7533 case TRANSACT2_FINDNEXT:
7535 START_PROFILE(Trans2_findnext);
7536 call_trans2findnext(conn, req,
7537 &state->param, state->total_param,
7538 &state->data, state->total_data,
7539 state->max_data_return);
7540 END_PROFILE(Trans2_findnext);
7544 case TRANSACT2_QFSINFO:
7546 START_PROFILE(Trans2_qfsinfo);
7547 call_trans2qfsinfo(conn, req,
7548 &state->param, state->total_param,
7549 &state->data, state->total_data,
7550 state->max_data_return);
7551 END_PROFILE(Trans2_qfsinfo);
7555 case TRANSACT2_SETFSINFO:
7557 START_PROFILE(Trans2_setfsinfo);
7558 call_trans2setfsinfo(conn, req,
7559 &state->param, state->total_param,
7560 &state->data, state->total_data,
7561 state->max_data_return);
7562 END_PROFILE(Trans2_setfsinfo);
7566 case TRANSACT2_QPATHINFO:
7567 case TRANSACT2_QFILEINFO:
7569 START_PROFILE(Trans2_qpathinfo);
7570 call_trans2qfilepathinfo(conn, req, state->call,
7571 &state->param, state->total_param,
7572 &state->data, state->total_data,
7573 state->max_data_return);
7574 END_PROFILE(Trans2_qpathinfo);
7578 case TRANSACT2_SETPATHINFO:
7579 case TRANSACT2_SETFILEINFO:
7581 START_PROFILE(Trans2_setpathinfo);
7582 call_trans2setfilepathinfo(conn, req, state->call,
7583 &state->param, state->total_param,
7584 &state->data, state->total_data,
7585 state->max_data_return);
7586 END_PROFILE(Trans2_setpathinfo);
7590 case TRANSACT2_FINDNOTIFYFIRST:
7592 START_PROFILE(Trans2_findnotifyfirst);
7593 call_trans2findnotifyfirst(conn, req,
7594 &state->param, state->total_param,
7595 &state->data, state->total_data,
7596 state->max_data_return);
7597 END_PROFILE(Trans2_findnotifyfirst);
7601 case TRANSACT2_FINDNOTIFYNEXT:
7603 START_PROFILE(Trans2_findnotifynext);
7604 call_trans2findnotifynext(conn, req,
7605 &state->param, state->total_param,
7606 &state->data, state->total_data,
7607 state->max_data_return);
7608 END_PROFILE(Trans2_findnotifynext);
7612 case TRANSACT2_MKDIR:
7614 START_PROFILE(Trans2_mkdir);
7615 call_trans2mkdir(conn, req,
7616 &state->param, state->total_param,
7617 &state->data, state->total_data,
7618 state->max_data_return);
7619 END_PROFILE(Trans2_mkdir);
7623 case TRANSACT2_GET_DFS_REFERRAL:
7625 START_PROFILE(Trans2_get_dfs_referral);
7626 call_trans2getdfsreferral(conn, req,
7627 &state->param, state->total_param,
7628 &state->data, state->total_data,
7629 state->max_data_return);
7630 END_PROFILE(Trans2_get_dfs_referral);
7634 case TRANSACT2_IOCTL:
7636 START_PROFILE(Trans2_ioctl);
7637 call_trans2ioctl(conn, req,
7638 &state->param, state->total_param,
7639 &state->data, state->total_data,
7640 state->max_data_return);
7641 END_PROFILE(Trans2_ioctl);
7646 /* Error in request */
7647 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7648 reply_doserror(req, ERRSRV,ERRerror);
7652 /****************************************************************************
7653 Reply to a SMBtrans2.
7654 ****************************************************************************/
7656 void reply_trans2(struct smb_request *req)
7658 connection_struct *conn = req->conn;
7663 unsigned int tran_call;
7664 struct trans_state *state;
7667 START_PROFILE(SMBtrans2);
7669 if (req->wct < 14) {
7670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7671 END_PROFILE(SMBtrans2);
7675 dsoff = SVAL(req->vwv+12, 0);
7676 dscnt = SVAL(req->vwv+11, 0);
7677 psoff = SVAL(req->vwv+10, 0);
7678 pscnt = SVAL(req->vwv+9, 0);
7679 tran_call = SVAL(req->vwv+14, 0);
7681 result = allow_new_trans(conn->pending_trans, req->mid);
7682 if (!NT_STATUS_IS_OK(result)) {
7683 DEBUG(2, ("Got invalid trans2 request: %s\n",
7684 nt_errstr(result)));
7685 reply_nterror(req, result);
7686 END_PROFILE(SMBtrans2);
7691 switch (tran_call) {
7692 /* List the allowed trans2 calls on IPC$ */
7693 case TRANSACT2_OPEN:
7694 case TRANSACT2_GET_DFS_REFERRAL:
7695 case TRANSACT2_QFILEINFO:
7696 case TRANSACT2_QFSINFO:
7697 case TRANSACT2_SETFSINFO:
7700 reply_doserror(req, ERRSRV, ERRaccess);
7701 END_PROFILE(SMBtrans2);
7706 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7707 DEBUG(0, ("talloc failed\n"));
7708 reply_nterror(req, NT_STATUS_NO_MEMORY);
7709 END_PROFILE(SMBtrans2);
7713 state->cmd = SMBtrans2;
7715 state->mid = req->mid;
7716 state->vuid = req->vuid;
7717 state->setup_count = SVAL(req->vwv+13, 0);
7718 state->setup = NULL;
7719 state->total_param = SVAL(req->vwv+0, 0);
7720 state->param = NULL;
7721 state->total_data = SVAL(req->vwv+1, 0);
7723 state->max_param_return = SVAL(req->vwv+2, 0);
7724 state->max_data_return = SVAL(req->vwv+3, 0);
7725 state->max_setup_return = SVAL(req->vwv+4, 0);
7726 state->close_on_completion = BITSETW(req->vwv+5, 0);
7727 state->one_way = BITSETW(req->vwv+5, 1);
7729 state->call = tran_call;
7731 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7732 is so as a sanity check */
7733 if (state->setup_count != 1) {
7735 * Need to have rc=0 for ioctl to get job id for OS/2.
7736 * Network printing will fail if function is not successful.
7737 * Similar function in reply.c will be used if protocol
7738 * is LANMAN1.0 instead of LM1.2X002.
7739 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7740 * outbuf doesn't have to be set(only job id is used).
7742 if ( (state->setup_count == 4)
7743 && (tran_call == TRANSACT2_IOCTL)
7744 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7745 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7746 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7748 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7749 DEBUG(2,("Transaction is %d\n",tran_call));
7751 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7752 END_PROFILE(SMBtrans2);
7757 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7760 if (state->total_data) {
7762 if (trans_oob(state->total_data, 0, dscnt)
7763 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7767 /* Can't use talloc here, the core routines do realloc on the
7768 * params and data. */
7769 state->data = (char *)SMB_MALLOC(state->total_data);
7770 if (state->data == NULL) {
7771 DEBUG(0,("reply_trans2: data malloc fail for %u "
7772 "bytes !\n", (unsigned int)state->total_data));
7774 reply_nterror(req, NT_STATUS_NO_MEMORY);
7775 END_PROFILE(SMBtrans2);
7779 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7782 if (state->total_param) {
7784 if (trans_oob(state->total_param, 0, pscnt)
7785 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7789 /* Can't use talloc here, the core routines do realloc on the
7790 * params and data. */
7791 state->param = (char *)SMB_MALLOC(state->total_param);
7792 if (state->param == NULL) {
7793 DEBUG(0,("reply_trans: param malloc fail for %u "
7794 "bytes !\n", (unsigned int)state->total_param));
7795 SAFE_FREE(state->data);
7797 reply_nterror(req, NT_STATUS_NO_MEMORY);
7798 END_PROFILE(SMBtrans2);
7802 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7805 state->received_data = dscnt;
7806 state->received_param = pscnt;
7808 if ((state->received_param == state->total_param) &&
7809 (state->received_data == state->total_data)) {
7811 handle_trans2(conn, req, state);
7813 SAFE_FREE(state->data);
7814 SAFE_FREE(state->param);
7816 END_PROFILE(SMBtrans2);
7820 DLIST_ADD(conn->pending_trans, state);
7822 /* We need to send an interim response then receive the rest
7823 of the parameter/data bytes */
7824 reply_outbuf(req, 0, 0);
7825 show_msg((char *)req->outbuf);
7826 END_PROFILE(SMBtrans2);
7831 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7832 SAFE_FREE(state->data);
7833 SAFE_FREE(state->param);
7835 END_PROFILE(SMBtrans2);
7836 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7840 /****************************************************************************
7841 Reply to a SMBtranss2
7842 ****************************************************************************/
7844 void reply_transs2(struct smb_request *req)
7846 connection_struct *conn = req->conn;
7847 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7848 struct trans_state *state;
7850 START_PROFILE(SMBtranss2);
7852 show_msg((char *)req->inbuf);
7855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7856 END_PROFILE(SMBtranss2);
7860 for (state = conn->pending_trans; state != NULL;
7861 state = state->next) {
7862 if (state->mid == req->mid) {
7867 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7869 END_PROFILE(SMBtranss2);
7873 /* Revise state->total_param and state->total_data in case they have
7874 changed downwards */
7876 if (SVAL(req->vwv+0, 0) < state->total_param)
7877 state->total_param = SVAL(req->vwv+0, 0);
7878 if (SVAL(req->vwv+1, 0) < state->total_data)
7879 state->total_data = SVAL(req->vwv+1, 0);
7881 pcnt = SVAL(req->vwv+2, 0);
7882 poff = SVAL(req->vwv+3, 0);
7883 pdisp = SVAL(req->vwv+4, 0);
7885 dcnt = SVAL(req->vwv+5, 0);
7886 doff = SVAL(req->vwv+6, 0);
7887 ddisp = SVAL(req->vwv+7, 0);
7889 state->received_param += pcnt;
7890 state->received_data += dcnt;
7892 if ((state->received_data > state->total_data) ||
7893 (state->received_param > state->total_param))
7897 if (trans_oob(state->total_param, pdisp, pcnt)
7898 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7901 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7905 if (trans_oob(state->total_data, ddisp, dcnt)
7906 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7909 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7912 if ((state->received_param < state->total_param) ||
7913 (state->received_data < state->total_data)) {
7914 END_PROFILE(SMBtranss2);
7918 handle_trans2(conn, req, state);
7920 DLIST_REMOVE(conn->pending_trans, state);
7921 SAFE_FREE(state->data);
7922 SAFE_FREE(state->param);
7925 END_PROFILE(SMBtranss2);
7930 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7931 DLIST_REMOVE(conn->pending_trans, state);
7932 SAFE_FREE(state->data);
7933 SAFE_FREE(state->param);
7935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7936 END_PROFILE(SMBtranss2);