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/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "libcli/security/security.h"
37 #include "smbprofile.h"
38 #include "rpc_server/srv_pipe_hnd.h"
40 #define DIR_ENTRY_SAFETY_MARGIN 4096
42 static char *store_file_unix_basic(connection_struct *conn,
45 const SMB_STRUCT_STAT *psbuf);
47 static char *store_file_unix_basic_info2(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 /********************************************************************
53 Roundup a value to the nearest allocation roundup size boundary.
54 Only do this for Windows clients.
55 ********************************************************************/
57 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
59 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
61 /* Only roundup for Windows clients. */
62 enum remote_arch_types ra_type = get_remote_arch();
63 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
64 val = SMB_ROUNDUP(val,rval);
69 /********************************************************************
70 Create a 64 bit FileIndex. If the file is on the same device as
71 the root of the share, just return the 64-bit inode. If it isn't,
72 mangle as we used to do.
73 ********************************************************************/
75 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
78 if (conn->base_share_dev == psbuf->st_ex_dev) {
79 return (uint64_t)psbuf->st_ex_ino;
81 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
82 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
86 /****************************************************************************
87 Utility functions for dealing with extended attributes.
88 ****************************************************************************/
90 /****************************************************************************
91 Refuse to allow clients to overwrite our private xattrs.
92 ****************************************************************************/
94 static bool samba_private_attr_name(const char *unix_ea_name)
96 static const char * const prohibited_ea_names[] = {
97 SAMBA_POSIX_INHERITANCE_EA_NAME,
98 SAMBA_XATTR_DOS_ATTRIB,
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
110 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
111 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
117 /****************************************************************************
118 Get one EA value. Fill in a struct ea_struct.
119 ****************************************************************************/
121 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
122 files_struct *fsp, const char *fname,
123 const char *ea_name, struct ea_struct *pea)
125 /* Get the value of this xattr. Max size is 64k. */
126 size_t attr_size = 256;
132 val = talloc_realloc(mem_ctx, val, char, attr_size);
134 return NT_STATUS_NO_MEMORY;
137 if (fsp && fsp->fh->fd != -1) {
138 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
140 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
143 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
149 return map_nt_error_from_unix(errno);
152 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
153 dump_data(10, (uint8 *)val, sizeret);
156 if (strnequal(ea_name, "user.", 5)) {
157 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
159 pea->name = talloc_strdup(mem_ctx, ea_name);
161 if (pea->name == NULL) {
163 return NT_STATUS_NO_MEMORY;
165 pea->value.data = (unsigned char *)val;
166 pea->value.length = (size_t)sizeret;
170 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
171 files_struct *fsp, const char *fname,
172 char ***pnames, size_t *pnum_names)
174 /* Get a list of all xattrs. Max namesize is 64k. */
175 size_t ea_namelist_size = 1024;
176 char *ea_namelist = NULL;
181 ssize_t sizeret = -1;
183 if (!lp_ea_support(SNUM(conn))) {
192 * TALLOC the result early to get the talloc hierarchy right.
195 names = talloc_array(mem_ctx, char *, 1);
197 DEBUG(0, ("talloc failed\n"));
198 return NT_STATUS_NO_MEMORY;
201 while (ea_namelist_size <= 65536) {
203 ea_namelist = talloc_realloc(
204 names, ea_namelist, char, ea_namelist_size);
205 if (ea_namelist == NULL) {
206 DEBUG(0, ("talloc failed\n"));
208 return NT_STATUS_NO_MEMORY;
211 if (fsp && fsp->fh->fd != -1) {
212 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
215 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
219 if ((sizeret == -1) && (errno == ERANGE)) {
220 ea_namelist_size *= 2;
229 return map_nt_error_from_unix(errno);
232 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
233 (unsigned int)sizeret));
245 * Ensure the result is 0-terminated
248 if (ea_namelist[sizeret-1] != '\0') {
250 return NT_STATUS_INTERNAL_ERROR;
258 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
262 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
264 DEBUG(0, ("talloc failed\n"));
266 return NT_STATUS_NO_MEMORY;
272 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
273 names[num_names++] = p;
281 *pnum_names = num_names;
285 /****************************************************************************
286 Return a linked list of the total EA's. Plus the total size
287 ****************************************************************************/
289 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
290 const char *fname, size_t *pea_total_len)
292 /* Get a list of all xattrs. Max namesize is 64k. */
295 struct ea_list *ea_list_head = NULL;
300 if (!lp_ea_support(SNUM(conn))) {
304 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
307 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
311 for (i=0; i<num_names; i++) {
312 struct ea_list *listp;
315 if (strnequal(names[i], "system.", 7)
316 || samba_private_attr_name(names[i]))
319 listp = talloc(mem_ctx, struct ea_list);
324 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
330 push_ascii_fstring(dos_ea_name, listp->ea.name);
333 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
335 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
336 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
337 (unsigned int)listp->ea.value.length));
339 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
343 /* Add on 4 for total length. */
344 if (*pea_total_len) {
348 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
349 (unsigned int)*pea_total_len));
354 /****************************************************************************
355 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
357 ****************************************************************************/
359 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
360 connection_struct *conn, struct ea_list *ea_list)
362 unsigned int ret_data_size = 4;
365 SMB_ASSERT(total_data_size >= 4);
367 if (!lp_ea_support(SNUM(conn))) {
372 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
375 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
376 dos_namelen = strlen(dos_ea_name);
377 if (dos_namelen > 255 || dos_namelen == 0) {
380 if (ea_list->ea.value.length > 65535) {
383 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
387 /* We know we have room. */
388 SCVAL(p,0,ea_list->ea.flags);
389 SCVAL(p,1,dos_namelen);
390 SSVAL(p,2,ea_list->ea.value.length);
391 strlcpy(p+4, dos_ea_name, dos_namelen+1);
392 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
394 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
395 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
398 ret_data_size = PTR_DIFF(p, pdata);
399 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
400 SIVAL(pdata,0,ret_data_size);
401 return ret_data_size;
404 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
406 unsigned int total_data_size,
407 unsigned int *ret_data_size,
408 connection_struct *conn,
409 struct ea_list *ea_list)
411 uint8_t *p = (uint8_t *)pdata;
412 uint8_t *last_start = NULL;
416 if (!lp_ea_support(SNUM(conn))) {
417 return NT_STATUS_NO_EAS_ON_FILE;
420 for (; ea_list; ea_list = ea_list->next) {
426 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
430 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
431 dos_namelen = strlen(dos_ea_name);
432 if (dos_namelen > 255 || dos_namelen == 0) {
433 return NT_STATUS_INTERNAL_ERROR;
435 if (ea_list->ea.value.length > 65535) {
436 return NT_STATUS_INTERNAL_ERROR;
439 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
442 size_t pad = 4 - (this_size % 4);
446 if (this_size > total_data_size) {
447 return NT_STATUS_INFO_LENGTH_MISMATCH;
450 /* We know we have room. */
451 SIVAL(p, 0x00, 0); /* next offset */
452 SCVAL(p, 0x04, ea_list->ea.flags);
453 SCVAL(p, 0x05, dos_namelen);
454 SSVAL(p, 0x06, ea_list->ea.value.length);
455 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
456 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
458 total_data_size -= this_size;
462 *ret_data_size = PTR_DIFF(p, pdata);
463 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
467 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
469 size_t total_ea_len = 0;
470 TALLOC_CTX *mem_ctx = NULL;
472 if (!lp_ea_support(SNUM(conn))) {
475 mem_ctx = talloc_tos();
476 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
480 /****************************************************************************
481 Ensure the EA name is case insensitive by matching any existing EA name.
482 ****************************************************************************/
484 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
487 TALLOC_CTX *mem_ctx = talloc_tos();
488 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
490 for (; ea_list; ea_list = ea_list->next) {
491 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
492 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
493 &unix_ea_name[5], ea_list->ea.name));
494 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
500 /****************************************************************************
501 Set or delete an extended attribute.
502 ****************************************************************************/
504 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
505 const struct smb_filename *smb_fname, struct ea_list *ea_list)
509 if (!lp_ea_support(SNUM(conn))) {
510 return NT_STATUS_EAS_NOT_SUPPORTED;
513 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
514 return NT_STATUS_ACCESS_DENIED;
517 /* For now setting EAs on streams isn't supported. */
518 fname = smb_fname->base_name;
520 for (;ea_list; ea_list = ea_list->next) {
522 fstring unix_ea_name;
524 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
525 fstrcat(unix_ea_name, ea_list->ea.name);
527 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
529 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
531 if (samba_private_attr_name(unix_ea_name)) {
532 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
533 return NT_STATUS_ACCESS_DENIED;
536 if (ea_list->ea.value.length == 0) {
537 /* Remove the attribute. */
538 if (fsp && (fsp->fh->fd != -1)) {
539 DEBUG(10,("set_ea: deleting ea name %s on "
540 "file %s by file descriptor.\n",
541 unix_ea_name, fsp_str_dbg(fsp)));
542 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
544 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
545 unix_ea_name, fname));
546 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
549 /* Removing a non existent attribute always succeeds. */
550 if (ret == -1 && errno == ENOATTR) {
551 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
557 if (fsp && (fsp->fh->fd != -1)) {
558 DEBUG(10,("set_ea: setting ea name %s on file "
559 "%s by file descriptor.\n",
560 unix_ea_name, fsp_str_dbg(fsp)));
561 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
562 ea_list->ea.value.data, ea_list->ea.value.length, 0);
564 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
565 unix_ea_name, fname));
566 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
567 ea_list->ea.value.data, ea_list->ea.value.length, 0);
573 if (errno == ENOTSUP) {
574 return NT_STATUS_EAS_NOT_SUPPORTED;
577 return map_nt_error_from_unix(errno);
583 /****************************************************************************
584 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
585 ****************************************************************************/
587 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
589 struct ea_list *ea_list_head = NULL;
590 size_t converted_size, offset = 0;
592 while (offset + 2 < data_size) {
593 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
594 unsigned int namelen = CVAL(pdata,offset);
596 offset++; /* Go past the namelen byte. */
598 /* integer wrap paranioa. */
599 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
600 (offset > data_size) || (namelen > data_size) ||
601 (offset + namelen >= data_size)) {
604 /* Ensure the name is null terminated. */
605 if (pdata[offset + namelen] != '\0') {
608 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
610 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
611 "failed: %s", strerror(errno)));
617 offset += (namelen + 1); /* Go past the name + terminating zero. */
618 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
619 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
625 /****************************************************************************
626 Read one EA list entry from the buffer.
627 ****************************************************************************/
629 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
631 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
633 unsigned int namelen;
634 size_t converted_size;
644 eal->ea.flags = CVAL(pdata,0);
645 namelen = CVAL(pdata,1);
646 val_len = SVAL(pdata,2);
648 if (4 + namelen + 1 + val_len > data_size) {
652 /* Ensure the name is null terminated. */
653 if (pdata[namelen + 4] != '\0') {
656 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
657 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
664 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
665 if (!eal->ea.value.data) {
669 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
671 /* Ensure we're null terminated just in case we print the value. */
672 eal->ea.value.data[val_len] = '\0';
673 /* But don't count the null. */
674 eal->ea.value.length--;
677 *pbytes_used = 4 + namelen + 1 + val_len;
680 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
681 dump_data(10, eal->ea.value.data, eal->ea.value.length);
686 /****************************************************************************
687 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
688 ****************************************************************************/
690 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
692 struct ea_list *ea_list_head = NULL;
694 size_t bytes_used = 0;
696 while (offset < data_size) {
697 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
703 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
704 offset += bytes_used;
710 /****************************************************************************
711 Count the total EA size needed.
712 ****************************************************************************/
714 static size_t ea_list_size(struct ea_list *ealist)
717 struct ea_list *listp;
720 for (listp = ealist; listp; listp = listp->next) {
721 push_ascii_fstring(dos_ea_name, listp->ea.name);
722 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
724 /* Add on 4 for total length. */
732 /****************************************************************************
733 Return a union of EA's from a file list and a list of names.
734 The TALLOC context for the two lists *MUST* be identical as we steal
735 memory from one list to add to another. JRA.
736 ****************************************************************************/
738 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
740 struct ea_list *nlistp, *flistp;
742 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
743 for (flistp = file_list; flistp; flistp = flistp->next) {
744 if (strequal(nlistp->ea.name, flistp->ea.name)) {
750 /* Copy the data from this entry. */
751 nlistp->ea.flags = flistp->ea.flags;
752 nlistp->ea.value = flistp->ea.value;
755 nlistp->ea.flags = 0;
756 ZERO_STRUCT(nlistp->ea.value);
760 *total_ea_len = ea_list_size(name_list);
764 /****************************************************************************
765 Send the required number of replies back.
766 We assume all fields other than the data fields are
767 set correctly for the type of call.
768 HACK ! Always assumes smb_setup field is zero.
769 ****************************************************************************/
771 void send_trans2_replies(connection_struct *conn,
772 struct smb_request *req,
779 /* As we are using a protocol > LANMAN1 then the max_send
780 variable must have been set in the sessetupX call.
781 This takes precedence over the max_xmit field in the
782 global struct. These different max_xmit variables should
783 be merged as this is now too confusing */
785 int data_to_send = datasize;
786 int params_to_send = paramsize;
788 const char *pp = params;
789 const char *pd = pdata;
790 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
791 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
792 int data_alignment_offset = 0;
793 bool overflow = False;
794 struct smbd_server_connection *sconn = req->sconn;
795 int max_send = sconn->smb1.sessions.max_send;
797 /* Modify the data_to_send and datasize and set the error if
798 we're trying to send more than max_data_bytes. We still send
799 the part of the packet(s) that fit. Strange, but needed
802 if (max_data_bytes > 0 && datasize > max_data_bytes) {
803 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
804 max_data_bytes, datasize ));
805 datasize = data_to_send = max_data_bytes;
809 /* If there genuinely are no parameters or data to send just send the empty packet */
811 if(params_to_send == 0 && data_to_send == 0) {
812 reply_outbuf(req, 10, 0);
813 show_msg((char *)req->outbuf);
814 if (!srv_send_smb(sconn,
817 IS_CONN_ENCRYPTED(conn),
819 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
821 TALLOC_FREE(req->outbuf);
825 /* When sending params and data ensure that both are nicely aligned */
826 /* Only do this alignment when there is also data to send - else
827 can cause NT redirector problems. */
829 if (((params_to_send % 4) != 0) && (data_to_send != 0))
830 data_alignment_offset = 4 - (params_to_send % 4);
832 /* Space is bufsize minus Netbios over TCP header minus SMB header */
833 /* The alignment_offset is to align the param bytes on an even byte
834 boundary. NT 4.0 Beta needs this to work correctly. */
836 useable_space = max_send - (smb_size
839 + data_alignment_offset);
841 if (useable_space < 0) {
842 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
843 "= %d!!!", useable_space));
844 exit_server_cleanly("send_trans2_replies: Not enough space");
847 while (params_to_send || data_to_send) {
848 /* Calculate whether we will totally or partially fill this packet */
850 total_sent_thistime = params_to_send + data_to_send;
852 /* We can never send more than useable_space */
854 * Note that 'useable_space' does not include the alignment offsets,
855 * but we must include the alignment offsets in the calculation of
856 * the length of the data we send over the wire, as the alignment offsets
857 * are sent here. Fix from Marc_Jacobsen@hp.com.
860 total_sent_thistime = MIN(total_sent_thistime, useable_space);
862 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
863 + data_alignment_offset);
866 * We might have SMBtrans2s in req which was transferred to
867 * the outbuf, fix that.
869 SCVAL(req->outbuf, smb_com, SMBtrans2);
871 /* Set total params and data to be sent */
872 SSVAL(req->outbuf,smb_tprcnt,paramsize);
873 SSVAL(req->outbuf,smb_tdrcnt,datasize);
875 /* Calculate how many parameters and data we can fit into
876 * this packet. Parameters get precedence
879 params_sent_thistime = MIN(params_to_send,useable_space);
880 data_sent_thistime = useable_space - params_sent_thistime;
881 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
883 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
885 /* smb_proff is the offset from the start of the SMB header to the
886 parameter bytes, however the first 4 bytes of outbuf are
887 the Netbios over TCP header. Thus use smb_base() to subtract
888 them from the calculation */
890 SSVAL(req->outbuf,smb_proff,
891 ((smb_buf(req->outbuf)+alignment_offset)
892 - smb_base(req->outbuf)));
894 if(params_sent_thistime == 0)
895 SSVAL(req->outbuf,smb_prdisp,0);
897 /* Absolute displacement of param bytes sent in this packet */
898 SSVAL(req->outbuf,smb_prdisp,pp - params);
900 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
901 if(data_sent_thistime == 0) {
902 SSVAL(req->outbuf,smb_droff,0);
903 SSVAL(req->outbuf,smb_drdisp, 0);
905 /* The offset of the data bytes is the offset of the
906 parameter bytes plus the number of parameters being sent this time */
907 SSVAL(req->outbuf, smb_droff,
908 ((smb_buf(req->outbuf)+alignment_offset)
909 - smb_base(req->outbuf))
910 + params_sent_thistime + data_alignment_offset);
911 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
914 /* Initialize the padding for alignment */
916 if (alignment_offset != 0) {
917 memset(smb_buf(req->outbuf), 0, alignment_offset);
920 /* Copy the param bytes into the packet */
922 if(params_sent_thistime) {
923 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
924 params_sent_thistime);
927 /* Copy in the data bytes */
928 if(data_sent_thistime) {
929 if (data_alignment_offset != 0) {
930 memset((smb_buf(req->outbuf)+alignment_offset+
931 params_sent_thistime), 0,
932 data_alignment_offset);
934 memcpy(smb_buf(req->outbuf)+alignment_offset
935 +params_sent_thistime+data_alignment_offset,
936 pd,data_sent_thistime);
939 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
940 params_sent_thistime, data_sent_thistime, useable_space));
941 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
942 params_to_send, data_to_send, paramsize, datasize));
945 error_packet_set((char *)req->outbuf,
946 ERRDOS,ERRbufferoverflow,
947 STATUS_BUFFER_OVERFLOW,
951 /* Send the packet */
952 show_msg((char *)req->outbuf);
953 if (!srv_send_smb(sconn,
956 IS_CONN_ENCRYPTED(conn),
958 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
960 TALLOC_FREE(req->outbuf);
962 pp += params_sent_thistime;
963 pd += data_sent_thistime;
965 params_to_send -= params_sent_thistime;
966 data_to_send -= data_sent_thistime;
969 if(params_to_send < 0 || data_to_send < 0) {
970 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
971 params_to_send, data_to_send));
979 /****************************************************************************
980 Reply to a TRANSACT2_OPEN.
981 ****************************************************************************/
983 static void call_trans2open(connection_struct *conn,
984 struct smb_request *req,
985 char **pparams, int total_params,
986 char **ppdata, int total_data,
987 unsigned int max_data_bytes)
989 struct smb_filename *smb_fname = NULL;
990 char *params = *pparams;
991 char *pdata = *ppdata;
996 bool return_additional_info;
1005 int fattr=0,mtime=0;
1006 SMB_INO_T inode = 0;
1009 struct ea_list *ea_list = NULL;
1014 uint32 create_disposition;
1015 uint32 create_options = 0;
1016 uint32_t private_flags = 0;
1017 TALLOC_CTX *ctx = talloc_tos();
1020 * Ensure we have enough parameters to perform the operation.
1023 if (total_params < 29) {
1024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1028 flags = SVAL(params, 0);
1029 deny_mode = SVAL(params, 2);
1030 open_attr = SVAL(params,6);
1031 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1032 if (oplock_request) {
1033 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1037 return_additional_info = BITSETW(params,0);
1038 open_sattr = SVAL(params, 4);
1039 open_time = make_unix_date3(params+8);
1041 open_ofun = SVAL(params,12);
1042 open_size = IVAL(params,14);
1043 pname = ¶ms[28];
1046 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1050 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1051 total_params - 28, STR_TERMINATE,
1053 if (!NT_STATUS_IS_OK(status)) {
1054 reply_nterror(req, status);
1058 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1059 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1060 (unsigned int)open_ofun, open_size));
1062 status = filename_convert(ctx,
1064 req->flags2 & FLAGS2_DFS_PATHNAMES,
1069 if (!NT_STATUS_IS_OK(status)) {
1070 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1071 reply_botherror(req,
1072 NT_STATUS_PATH_NOT_COVERED,
1073 ERRSRV, ERRbadpath);
1076 reply_nterror(req, status);
1080 if (open_ofun == 0) {
1081 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1085 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1087 &access_mask, &share_mode,
1088 &create_disposition,
1091 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1095 /* Any data in this call is an EA list. */
1096 if (total_data && (total_data != 4)) {
1097 if (total_data < 10) {
1098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1102 if (IVAL(pdata,0) > total_data) {
1103 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1104 IVAL(pdata,0), (unsigned int)total_data));
1105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1109 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1116 if (!lp_ea_support(SNUM(conn))) {
1117 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1122 status = SMB_VFS_CREATE_FILE(
1125 0, /* root_dir_fid */
1126 smb_fname, /* fname */
1127 access_mask, /* access_mask */
1128 share_mode, /* share_access */
1129 create_disposition, /* create_disposition*/
1130 create_options, /* create_options */
1131 open_attr, /* file_attributes */
1132 oplock_request, /* oplock_request */
1133 open_size, /* allocation_size */
1136 ea_list, /* ea_list */
1138 &smb_action); /* psbuf */
1140 if (!NT_STATUS_IS_OK(status)) {
1141 if (open_was_deferred(req->sconn, req->mid)) {
1142 /* We have re-scheduled this call. */
1145 reply_openerror(req, status);
1149 size = get_file_size_stat(&smb_fname->st);
1150 fattr = dos_mode(conn, smb_fname);
1151 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1152 inode = smb_fname->st.st_ex_ino;
1153 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1154 close_file(req, fsp, ERROR_CLOSE);
1155 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1159 /* Realloc the size of parameters and data we will return */
1160 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1161 if(*pparams == NULL ) {
1162 reply_nterror(req, NT_STATUS_NO_MEMORY);
1167 SSVAL(params,0,fsp->fnum);
1168 SSVAL(params,2,fattr);
1169 srv_put_dos_date2(params,4, mtime);
1170 SIVAL(params,8, (uint32)size);
1171 SSVAL(params,12,deny_mode);
1172 SSVAL(params,14,0); /* open_type - file or directory. */
1173 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1175 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1176 smb_action |= EXTENDED_OPLOCK_GRANTED;
1179 SSVAL(params,18,smb_action);
1182 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1184 SIVAL(params,20,inode);
1185 SSVAL(params,24,0); /* Padding. */
1187 uint32 ea_size = estimate_ea_size(conn, fsp,
1188 fsp->fsp_name->base_name);
1189 SIVAL(params, 26, ea_size);
1191 SIVAL(params, 26, 0);
1194 /* Send the required number of replies */
1195 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1197 TALLOC_FREE(smb_fname);
1200 /*********************************************************
1201 Routine to check if a given string matches exactly.
1202 as a special case a mask of "." does NOT match. That
1203 is required for correct wildcard semantics
1204 Case can be significant or not.
1205 **********************************************************/
1207 static bool exact_match(bool has_wild,
1208 bool case_sensitive,
1212 if (mask[0] == '.' && mask[1] == 0) {
1220 if (case_sensitive) {
1221 return strcmp(str,mask)==0;
1223 return strcasecmp_m(str,mask) == 0;
1227 /****************************************************************************
1228 Return the filetype for UNIX extensions.
1229 ****************************************************************************/
1231 static uint32 unix_filetype(mode_t mode)
1234 return UNIX_TYPE_FILE;
1235 else if(S_ISDIR(mode))
1236 return UNIX_TYPE_DIR;
1238 else if(S_ISLNK(mode))
1239 return UNIX_TYPE_SYMLINK;
1242 else if(S_ISCHR(mode))
1243 return UNIX_TYPE_CHARDEV;
1246 else if(S_ISBLK(mode))
1247 return UNIX_TYPE_BLKDEV;
1250 else if(S_ISFIFO(mode))
1251 return UNIX_TYPE_FIFO;
1254 else if(S_ISSOCK(mode))
1255 return UNIX_TYPE_SOCKET;
1258 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1259 return UNIX_TYPE_UNKNOWN;
1262 /****************************************************************************
1263 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1264 ****************************************************************************/
1266 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1268 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1269 const SMB_STRUCT_STAT *psbuf,
1271 enum perm_type ptype,
1276 if (perms == SMB_MODE_NO_CHANGE) {
1277 if (!VALID_STAT(*psbuf)) {
1278 return NT_STATUS_INVALID_PARAMETER;
1280 *ret_perms = psbuf->st_ex_mode;
1281 return NT_STATUS_OK;
1285 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1286 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1287 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1288 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1289 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1290 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1291 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1292 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1293 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1295 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1298 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1301 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1306 /* Apply mode mask */
1307 ret &= lp_create_mask(SNUM(conn));
1308 /* Add in force bits */
1309 ret |= lp_force_create_mode(SNUM(conn));
1312 ret &= lp_dir_mask(SNUM(conn));
1313 /* Add in force bits */
1314 ret |= lp_force_dir_mode(SNUM(conn));
1316 case PERM_EXISTING_FILE:
1317 /* Apply mode mask */
1318 ret &= lp_security_mask(SNUM(conn));
1319 /* Add in force bits */
1320 ret |= lp_force_security_mode(SNUM(conn));
1322 case PERM_EXISTING_DIR:
1323 /* Apply mode mask */
1324 ret &= lp_dir_security_mask(SNUM(conn));
1325 /* Add in force bits */
1326 ret |= lp_force_dir_security_mode(SNUM(conn));
1331 return NT_STATUS_OK;
1334 /****************************************************************************
1335 Needed to show the msdfs symlinks as directories. Modifies psbuf
1336 to be a directory if it's a msdfs link.
1337 ****************************************************************************/
1339 static bool check_msdfs_link(connection_struct *conn,
1340 const char *pathname,
1341 SMB_STRUCT_STAT *psbuf)
1343 int saved_errno = errno;
1344 if(lp_host_msdfs() &&
1345 lp_msdfs_root(SNUM(conn)) &&
1346 is_msdfs_link(conn, pathname, psbuf)) {
1348 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1351 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1352 errno = saved_errno;
1355 errno = saved_errno;
1360 /****************************************************************************
1361 Get a level dependent lanman2 dir entry.
1362 ****************************************************************************/
1364 struct smbd_dirptr_lanman2_state {
1365 connection_struct *conn;
1366 uint32_t info_level;
1367 bool check_mangled_names;
1369 bool got_exact_match;
1372 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1378 struct smbd_dirptr_lanman2_state *state =
1379 (struct smbd_dirptr_lanman2_state *)private_data;
1381 char mangled_name[13]; /* mangled 8.3 name. */
1385 /* Mangle fname if it's an illegal name. */
1386 if (mangle_must_mangle(dname, state->conn->params)) {
1387 ok = name_to_8_3(dname, mangled_name,
1388 true, state->conn->params);
1392 fname = mangled_name;
1397 got_match = exact_match(state->has_wild,
1398 state->conn->case_sensitive,
1400 state->got_exact_match = got_match;
1402 got_match = mask_match(fname, mask,
1403 state->conn->case_sensitive);
1406 if(!got_match && state->check_mangled_names &&
1407 !mangle_is_8_3(fname, false, state->conn->params)) {
1409 * It turns out that NT matches wildcards against
1410 * both long *and* short names. This may explain some
1411 * of the wildcard wierdness from old DOS clients
1412 * that some people have been seeing.... JRA.
1414 /* Force the mangling into 8.3. */
1415 ok = name_to_8_3(fname, mangled_name,
1416 false, state->conn->params);
1421 got_match = exact_match(state->has_wild,
1422 state->conn->case_sensitive,
1423 mangled_name, mask);
1424 state->got_exact_match = got_match;
1426 got_match = mask_match(mangled_name, mask,
1427 state->conn->case_sensitive);
1435 *_fname = talloc_strdup(ctx, fname);
1436 if (*_fname == NULL) {
1443 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1445 struct smb_filename *smb_fname,
1448 struct smbd_dirptr_lanman2_state *state =
1449 (struct smbd_dirptr_lanman2_state *)private_data;
1450 bool ms_dfs_link = false;
1453 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1454 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1455 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1456 "Couldn't lstat [%s] (%s)\n",
1457 smb_fname_str_dbg(smb_fname),
1461 } else if (!VALID_STAT(smb_fname->st) &&
1462 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1463 /* Needed to show the msdfs symlinks as
1466 ms_dfs_link = check_msdfs_link(state->conn,
1467 smb_fname->base_name,
1470 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1471 "Couldn't stat [%s] (%s)\n",
1472 smb_fname_str_dbg(smb_fname),
1479 mode = dos_mode_msdfs(state->conn, smb_fname);
1481 mode = dos_mode(state->conn, smb_fname);
1488 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1489 connection_struct *conn,
1491 uint32_t info_level,
1492 struct ea_list *name_list,
1493 bool check_mangled_names,
1494 bool requires_resume_key,
1497 const struct smb_filename *smb_fname,
1498 int space_remaining,
1505 uint64_t *last_entry_off)
1507 char *p, *q, *pdata = *ppdata;
1509 uint64_t file_size = 0;
1510 uint64_t allocation_size = 0;
1511 uint64_t file_index = 0;
1513 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1514 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1515 time_t c_date = (time_t)0;
1517 char *last_entry_ptr;
1522 *out_of_space = false;
1524 ZERO_STRUCT(mdate_ts);
1525 ZERO_STRUCT(adate_ts);
1526 ZERO_STRUCT(create_date_ts);
1527 ZERO_STRUCT(cdate_ts);
1529 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1530 file_size = get_file_size_stat(&smb_fname->st);
1532 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1534 file_index = get_FileIndex(conn, &smb_fname->st);
1536 mdate_ts = smb_fname->st.st_ex_mtime;
1537 adate_ts = smb_fname->st.st_ex_atime;
1538 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1539 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1541 if (lp_dos_filetime_resolution(SNUM(conn))) {
1542 dos_filetime_timespec(&create_date_ts);
1543 dos_filetime_timespec(&mdate_ts);
1544 dos_filetime_timespec(&adate_ts);
1545 dos_filetime_timespec(&cdate_ts);
1548 create_date = convert_timespec_to_time_t(create_date_ts);
1549 mdate = convert_timespec_to_time_t(mdate_ts);
1550 adate = convert_timespec_to_time_t(adate_ts);
1551 c_date = convert_timespec_to_time_t(cdate_ts);
1553 /* align the record */
1554 SMB_ASSERT(align >= 1);
1556 off = (int)PTR_DIFF(pdata, base_data);
1557 pad = (off + (align-1)) & ~(align-1);
1560 if (pad && pad > space_remaining) {
1561 *out_of_space = true;
1562 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1563 "for padding (wanted %u, had %d)\n",
1566 return false; /* Not finished - just out of space */
1570 /* initialize padding to 0 */
1572 memset(pdata, 0, pad);
1574 space_remaining -= pad;
1576 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1586 switch (info_level) {
1587 case SMB_FIND_INFO_STANDARD:
1588 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1589 if(requires_resume_key) {
1593 srv_put_dos_date2(p,0,create_date);
1594 srv_put_dos_date2(p,4,adate);
1595 srv_put_dos_date2(p,8,mdate);
1596 SIVAL(p,12,(uint32)file_size);
1597 SIVAL(p,16,(uint32)allocation_size);
1601 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1602 p += ucs2_align(base_data, p, 0);
1604 len = srvstr_push(base_data, flags2, p,
1605 fname, PTR_DIFF(end_data, p),
1607 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1609 SCVAL(nameptr, -1, len - 2);
1611 SCVAL(nameptr, -1, 0);
1615 SCVAL(nameptr, -1, len - 1);
1617 SCVAL(nameptr, -1, 0);
1623 case SMB_FIND_EA_SIZE:
1624 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1625 if (requires_resume_key) {
1629 srv_put_dos_date2(p,0,create_date);
1630 srv_put_dos_date2(p,4,adate);
1631 srv_put_dos_date2(p,8,mdate);
1632 SIVAL(p,12,(uint32)file_size);
1633 SIVAL(p,16,(uint32)allocation_size);
1636 unsigned int ea_size = estimate_ea_size(conn, NULL,
1637 smb_fname->base_name);
1638 SIVAL(p,22,ea_size); /* Extended attributes */
1642 len = srvstr_push(base_data, flags2,
1643 p, fname, PTR_DIFF(end_data, p),
1644 STR_TERMINATE | STR_NOALIGN);
1645 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1658 SCVAL(nameptr,0,len);
1660 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1663 case SMB_FIND_EA_LIST:
1665 struct ea_list *file_list = NULL;
1668 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1672 if (requires_resume_key) {
1676 srv_put_dos_date2(p,0,create_date);
1677 srv_put_dos_date2(p,4,adate);
1678 srv_put_dos_date2(p,8,mdate);
1679 SIVAL(p,12,(uint32)file_size);
1680 SIVAL(p,16,(uint32)allocation_size);
1682 p += 22; /* p now points to the EA area. */
1684 file_list = get_ea_list_from_file(ctx, conn, NULL,
1685 smb_fname->base_name,
1687 name_list = ea_list_union(name_list, file_list, &ea_len);
1689 /* We need to determine if this entry will fit in the space available. */
1690 /* Max string size is 255 bytes. */
1691 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1692 *out_of_space = true;
1693 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1694 "(wanted %u, had %d)\n",
1695 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1697 return False; /* Not finished - just out of space */
1700 /* Push the ea_data followed by the name. */
1701 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1703 len = srvstr_push(base_data, flags2,
1704 p + 1, fname, PTR_DIFF(end_data, p+1),
1705 STR_TERMINATE | STR_NOALIGN);
1706 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1719 SCVAL(nameptr,0,len);
1721 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1725 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1726 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1727 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1729 SIVAL(p,0,reskey); p += 4;
1730 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1731 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1732 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1733 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1734 SOFF_T(p,0,file_size); p += 8;
1735 SOFF_T(p,0,allocation_size); p += 8;
1736 SIVAL(p,0,mode); p += 4;
1737 q = p; p += 4; /* q is placeholder for name length. */
1739 unsigned int ea_size = estimate_ea_size(conn, NULL,
1740 smb_fname->base_name);
1741 SIVAL(p,0,ea_size); /* Extended attributes */
1744 /* Clear the short name buffer. This is
1745 * IMPORTANT as not doing so will trigger
1746 * a Win2k client bug. JRA.
1748 if (!was_8_3 && check_mangled_names) {
1749 char mangled_name[13]; /* mangled 8.3 name. */
1750 if (!name_to_8_3(fname,mangled_name,True,
1752 /* Error - mangle failed ! */
1753 memset(mangled_name,'\0',12);
1755 mangled_name[12] = 0;
1756 len = srvstr_push(base_data, flags2,
1757 p+2, mangled_name, 24,
1758 STR_UPPER|STR_UNICODE);
1760 memset(p + 2 + len,'\0',24 - len);
1767 len = srvstr_push(base_data, flags2, p,
1768 fname, PTR_DIFF(end_data, p),
1769 STR_TERMINATE_ASCII);
1773 len = PTR_DIFF(p, pdata);
1774 pad = (len + (align-1)) & ~(align-1);
1776 * offset to the next entry, the caller
1777 * will overwrite it for the last entry
1778 * that's why we always include the padding
1782 * set padding to zero
1785 memset(p, 0, pad - len);
1792 case SMB_FIND_FILE_DIRECTORY_INFO:
1793 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1795 SIVAL(p,0,reskey); p += 4;
1796 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1797 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1798 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1799 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1800 SOFF_T(p,0,file_size); p += 8;
1801 SOFF_T(p,0,allocation_size); p += 8;
1802 SIVAL(p,0,mode); p += 4;
1803 len = srvstr_push(base_data, flags2,
1804 p + 4, fname, PTR_DIFF(end_data, p+4),
1805 STR_TERMINATE_ASCII);
1809 len = PTR_DIFF(p, pdata);
1810 pad = (len + (align-1)) & ~(align-1);
1812 * offset to the next entry, the caller
1813 * will overwrite it for the last entry
1814 * that's why we always include the padding
1818 * set padding to zero
1821 memset(p, 0, pad - len);
1828 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1829 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1831 SIVAL(p,0,reskey); p += 4;
1832 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1833 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1834 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1835 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1836 SOFF_T(p,0,file_size); p += 8;
1837 SOFF_T(p,0,allocation_size); p += 8;
1838 SIVAL(p,0,mode); p += 4;
1839 q = p; p += 4; /* q is placeholder for name length. */
1841 unsigned int ea_size = estimate_ea_size(conn, NULL,
1842 smb_fname->base_name);
1843 SIVAL(p,0,ea_size); /* Extended attributes */
1846 len = srvstr_push(base_data, flags2, p,
1847 fname, PTR_DIFF(end_data, p),
1848 STR_TERMINATE_ASCII);
1852 len = PTR_DIFF(p, pdata);
1853 pad = (len + (align-1)) & ~(align-1);
1855 * offset to the next entry, the caller
1856 * will overwrite it for the last entry
1857 * that's why we always include the padding
1861 * set padding to zero
1864 memset(p, 0, pad - len);
1871 case SMB_FIND_FILE_NAMES_INFO:
1872 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1874 SIVAL(p,0,reskey); p += 4;
1876 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1877 acl on a dir (tridge) */
1878 len = srvstr_push(base_data, flags2, p,
1879 fname, PTR_DIFF(end_data, p),
1880 STR_TERMINATE_ASCII);
1884 len = PTR_DIFF(p, pdata);
1885 pad = (len + (align-1)) & ~(align-1);
1887 * offset to the next entry, the caller
1888 * will overwrite it for the last entry
1889 * that's why we always include the padding
1893 * set padding to zero
1896 memset(p, 0, pad - len);
1903 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1906 SIVAL(p,0,reskey); p += 4;
1907 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1910 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1911 SOFF_T(p,0,file_size); p += 8;
1912 SOFF_T(p,0,allocation_size); p += 8;
1913 SIVAL(p,0,mode); p += 4;
1914 q = p; p += 4; /* q is placeholder for name length. */
1916 unsigned int ea_size = estimate_ea_size(conn, NULL,
1917 smb_fname->base_name);
1918 SIVAL(p,0,ea_size); /* Extended attributes */
1921 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1922 SBVAL(p,0,file_index); p += 8;
1923 len = srvstr_push(base_data, flags2, p,
1924 fname, PTR_DIFF(end_data, p),
1925 STR_TERMINATE_ASCII);
1929 len = PTR_DIFF(p, pdata);
1930 pad = (len + (align-1)) & ~(align-1);
1932 * offset to the next entry, the caller
1933 * will overwrite it for the last entry
1934 * that's why we always include the padding
1938 * set padding to zero
1941 memset(p, 0, pad - len);
1948 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1949 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1950 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1952 SIVAL(p,0,reskey); p += 4;
1953 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1954 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1955 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1956 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1957 SOFF_T(p,0,file_size); p += 8;
1958 SOFF_T(p,0,allocation_size); p += 8;
1959 SIVAL(p,0,mode); p += 4;
1960 q = p; p += 4; /* q is placeholder for name length */
1962 unsigned int ea_size = estimate_ea_size(conn, NULL,
1963 smb_fname->base_name);
1964 SIVAL(p,0,ea_size); /* Extended attributes */
1967 /* Clear the short name buffer. This is
1968 * IMPORTANT as not doing so will trigger
1969 * a Win2k client bug. JRA.
1971 if (!was_8_3 && check_mangled_names) {
1972 char mangled_name[13]; /* mangled 8.3 name. */
1973 if (!name_to_8_3(fname,mangled_name,True,
1975 /* Error - mangle failed ! */
1976 memset(mangled_name,'\0',12);
1978 mangled_name[12] = 0;
1979 len = srvstr_push(base_data, flags2,
1980 p+2, mangled_name, 24,
1981 STR_UPPER|STR_UNICODE);
1984 memset(p + 2 + len,'\0',24 - len);
1991 SSVAL(p,0,0); p += 2; /* Reserved ? */
1992 SBVAL(p,0,file_index); p += 8;
1993 len = srvstr_push(base_data, flags2, p,
1994 fname, PTR_DIFF(end_data, p),
1995 STR_TERMINATE_ASCII);
1999 len = PTR_DIFF(p, pdata);
2000 pad = (len + (align-1)) & ~(align-1);
2002 * offset to the next entry, the caller
2003 * will overwrite it for the last entry
2004 * that's why we always include the padding
2008 * set padding to zero
2011 memset(p, 0, pad - len);
2018 /* CIFS UNIX Extension. */
2020 case SMB_FIND_FILE_UNIX:
2021 case SMB_FIND_FILE_UNIX_INFO2:
2023 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2025 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2027 if (info_level == SMB_FIND_FILE_UNIX) {
2028 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2029 p = store_file_unix_basic(conn, p,
2030 NULL, &smb_fname->st);
2031 len = srvstr_push(base_data, flags2, p,
2032 fname, PTR_DIFF(end_data, p),
2035 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2036 p = store_file_unix_basic_info2(conn, p,
2037 NULL, &smb_fname->st);
2040 len = srvstr_push(base_data, flags2, p, fname,
2041 PTR_DIFF(end_data, p), 0);
2042 SIVAL(nameptr, 0, len);
2047 len = PTR_DIFF(p, pdata);
2048 pad = (len + (align-1)) & ~(align-1);
2050 * offset to the next entry, the caller
2051 * will overwrite it for the last entry
2052 * that's why we always include the padding
2056 * set padding to zero
2059 memset(p, 0, pad - len);
2064 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2072 if (PTR_DIFF(p,pdata) > space_remaining) {
2073 *out_of_space = true;
2074 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2075 "(wanted %u, had %d)\n",
2076 (unsigned int)PTR_DIFF(p,pdata),
2078 return false; /* Not finished - just out of space */
2081 /* Setup the last entry pointer, as an offset from base_data */
2082 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2083 /* Advance the data pointer to the next slot */
2089 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2090 connection_struct *conn,
2091 struct dptr_struct *dirptr,
2093 const char *path_mask,
2096 int requires_resume_key,
2104 int space_remaining,
2106 bool *got_exact_match,
2107 int *_last_entry_off,
2108 struct ea_list *name_list)
2111 const char *mask = NULL;
2112 long prev_dirpos = 0;
2115 struct smb_filename *smb_fname = NULL;
2116 struct smbd_dirptr_lanman2_state state;
2118 uint64_t last_entry_off = 0;
2122 state.info_level = info_level;
2123 state.check_mangled_names = lp_manglednames(conn->params);
2124 state.has_wild = dptr_has_wild(dirptr);
2125 state.got_exact_match = false;
2127 *out_of_space = false;
2128 *got_exact_match = false;
2130 p = strrchr_m(path_mask,'/');
2141 ok = smbd_dirptr_get_entry(ctx,
2147 smbd_dirptr_lanman2_match_fn,
2148 smbd_dirptr_lanman2_mode_fn,
2158 *got_exact_match = state.got_exact_match;
2160 ok = smbd_marshall_dir_entry(ctx,
2165 state.check_mangled_names,
2166 requires_resume_key,
2179 TALLOC_FREE(smb_fname);
2180 if (*out_of_space) {
2181 dptr_SeekDir(dirptr, prev_dirpos);
2188 *_last_entry_off = last_entry_off;
2192 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2193 connection_struct *conn,
2194 struct dptr_struct *dirptr,
2196 const char *path_mask,
2199 bool requires_resume_key,
2205 int space_remaining,
2207 bool *got_exact_match,
2208 int *last_entry_off,
2209 struct ea_list *name_list)
2212 const bool do_pad = true;
2214 if (info_level >= 1 && info_level <= 3) {
2215 /* No alignment on earlier info levels. */
2219 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2220 path_mask, dirtype, info_level,
2221 requires_resume_key, dont_descend, ask_sharemode,
2223 ppdata, base_data, end_data,
2225 out_of_space, got_exact_match,
2226 last_entry_off, name_list);
2229 /****************************************************************************
2230 Reply to a TRANS2_FINDFIRST.
2231 ****************************************************************************/
2233 static void call_trans2findfirst(connection_struct *conn,
2234 struct smb_request *req,
2235 char **pparams, int total_params,
2236 char **ppdata, int total_data,
2237 unsigned int max_data_bytes)
2239 /* We must be careful here that we don't return more than the
2240 allowed number of data bytes. If this means returning fewer than
2241 maxentries then so be it. We assume that the redirector has
2242 enough room for the fixed number of parameter bytes it has
2244 struct smb_filename *smb_dname = NULL;
2245 char *params = *pparams;
2246 char *pdata = *ppdata;
2250 uint16 findfirst_flags;
2251 bool close_after_first;
2253 bool requires_resume_key;
2255 char *directory = NULL;
2258 int last_entry_off=0;
2262 bool finished = False;
2263 bool dont_descend = False;
2264 bool out_of_space = False;
2265 int space_remaining;
2266 bool mask_contains_wcard = False;
2267 struct ea_list *ea_list = NULL;
2268 NTSTATUS ntstatus = NT_STATUS_OK;
2269 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2270 TALLOC_CTX *ctx = talloc_tos();
2271 struct dptr_struct *dirptr = NULL;
2272 struct smbd_server_connection *sconn = req->sconn;
2274 if (total_params < 13) {
2275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2279 dirtype = SVAL(params,0);
2280 maxentries = SVAL(params,2);
2281 findfirst_flags = SVAL(params,4);
2282 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2283 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2284 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2285 info_level = SVAL(params,6);
2287 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2288 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2289 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2290 info_level, max_data_bytes));
2293 /* W2K3 seems to treat zero as 1. */
2297 switch (info_level) {
2298 case SMB_FIND_INFO_STANDARD:
2299 case SMB_FIND_EA_SIZE:
2300 case SMB_FIND_EA_LIST:
2301 case SMB_FIND_FILE_DIRECTORY_INFO:
2302 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_NAMES_INFO:
2304 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2305 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2306 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2308 case SMB_FIND_FILE_UNIX:
2309 case SMB_FIND_FILE_UNIX_INFO2:
2310 /* Always use filesystem for UNIX mtime query. */
2311 ask_sharemode = false;
2312 if (!lp_unix_extensions()) {
2313 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2322 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2323 params+12, total_params - 12,
2324 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2325 if (!NT_STATUS_IS_OK(ntstatus)) {
2326 reply_nterror(req, ntstatus);
2330 ntstatus = filename_convert(ctx, conn,
2331 req->flags2 & FLAGS2_DFS_PATHNAMES,
2334 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2335 &mask_contains_wcard,
2337 if (!NT_STATUS_IS_OK(ntstatus)) {
2338 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2339 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2340 ERRSRV, ERRbadpath);
2343 reply_nterror(req, ntstatus);
2347 mask = smb_dname->original_lcomp;
2349 directory = smb_dname->base_name;
2351 p = strrchr_m(directory,'/');
2353 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2354 if((directory[0] == '.') && (directory[1] == '\0')) {
2355 mask = talloc_strdup(ctx,"*");
2357 reply_nterror(req, NT_STATUS_NO_MEMORY);
2360 mask_contains_wcard = True;
2366 if (p == NULL || p == directory) {
2367 /* Ensure we don't have a directory name of "". */
2368 directory = talloc_strdup(talloc_tos(), ".");
2370 reply_nterror(req, NT_STATUS_NO_MEMORY);
2375 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2377 if (info_level == SMB_FIND_EA_LIST) {
2380 if (total_data < 4) {
2381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2385 ea_size = IVAL(pdata,0);
2386 if (ea_size != total_data) {
2387 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2388 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2393 if (!lp_ea_support(SNUM(conn))) {
2394 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2398 /* Pull out the list of names. */
2399 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2406 *ppdata = (char *)SMB_REALLOC(
2407 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2408 if(*ppdata == NULL ) {
2409 reply_nterror(req, NT_STATUS_NO_MEMORY);
2413 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2415 /* Realloc the params space */
2416 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2417 if (*pparams == NULL) {
2418 reply_nterror(req, NT_STATUS_NO_MEMORY);
2423 /* Save the wildcard match and attribs we are using on this directory -
2424 needed as lanman2 assumes these are being saved between calls */
2426 ntstatus = dptr_create(conn,
2433 mask_contains_wcard,
2437 if (!NT_STATUS_IS_OK(ntstatus)) {
2438 reply_nterror(req, ntstatus);
2442 dptr_num = dptr_dnum(dirptr);
2443 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2445 /* Initialize per TRANS2_FIND_FIRST operation data */
2446 dptr_init_search_op(dirptr);
2448 /* We don't need to check for VOL here as this is returned by
2449 a different TRANS2 call. */
2451 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2452 directory,lp_dontdescend(SNUM(conn))));
2453 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2454 dont_descend = True;
2457 space_remaining = max_data_bytes;
2458 out_of_space = False;
2460 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2461 bool got_exact_match = False;
2463 /* this is a heuristic to avoid seeking the dirptr except when
2464 absolutely necessary. It allows for a filename of about 40 chars */
2465 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2466 out_of_space = True;
2469 finished = !get_lanman2_dir_entry(ctx,
2473 mask,dirtype,info_level,
2474 requires_resume_key,dont_descend,
2477 space_remaining, &out_of_space,
2479 &last_entry_off, ea_list);
2482 if (finished && out_of_space)
2485 if (!finished && !out_of_space)
2489 * As an optimisation if we know we aren't looking
2490 * for a wildcard name (ie. the name matches the wildcard exactly)
2491 * then we can finish on any (first) match.
2492 * This speeds up large directory searches. JRA.
2498 /* Ensure space_remaining never goes -ve. */
2499 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2500 space_remaining = 0;
2501 out_of_space = true;
2503 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2507 /* Check if we can close the dirptr */
2508 if(close_after_first || (finished && close_if_end)) {
2509 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2510 dptr_close(sconn, &dptr_num);
2514 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2515 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2516 * the protocol level is less than NT1. Tested with smbclient. JRA.
2517 * This should fix the OS/2 client bug #2335.
2520 if(numentries == 0) {
2521 dptr_close(sconn, &dptr_num);
2522 if (get_Protocol() < PROTOCOL_NT1) {
2523 reply_force_doserror(req, ERRDOS, ERRnofiles);
2526 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2527 ERRDOS, ERRbadfile);
2532 /* At this point pdata points to numentries directory entries. */
2534 /* Set up the return parameter block */
2535 SSVAL(params,0,dptr_num);
2536 SSVAL(params,2,numentries);
2537 SSVAL(params,4,finished);
2538 SSVAL(params,6,0); /* Never an EA error */
2539 SSVAL(params,8,last_entry_off);
2541 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2544 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2545 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2547 reply_nterror(req, NT_STATUS_NO_MEMORY);
2551 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2552 smb_fn_name(req->cmd),
2553 mask, directory, dirtype, numentries ) );
2556 * Force a name mangle here to ensure that the
2557 * mask as an 8.3 name is top of the mangled cache.
2558 * The reasons for this are subtle. Don't remove
2559 * this code unless you know what you are doing
2560 * (see PR#13758). JRA.
2563 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2564 char mangled_name[13];
2565 name_to_8_3(mask, mangled_name, True, conn->params);
2568 TALLOC_FREE(smb_dname);
2572 /****************************************************************************
2573 Reply to a TRANS2_FINDNEXT.
2574 ****************************************************************************/
2576 static void call_trans2findnext(connection_struct *conn,
2577 struct smb_request *req,
2578 char **pparams, int total_params,
2579 char **ppdata, int total_data,
2580 unsigned int max_data_bytes)
2582 /* We must be careful here that we don't return more than the
2583 allowed number of data bytes. If this means returning fewer than
2584 maxentries then so be it. We assume that the redirector has
2585 enough room for the fixed number of parameter bytes it has
2587 char *params = *pparams;
2588 char *pdata = *ppdata;
2594 uint16 findnext_flags;
2595 bool close_after_request;
2597 bool requires_resume_key;
2599 bool mask_contains_wcard = False;
2600 char *resume_name = NULL;
2601 const char *mask = NULL;
2602 const char *directory = NULL;
2606 int i, last_entry_off=0;
2607 bool finished = False;
2608 bool dont_descend = False;
2609 bool out_of_space = False;
2610 int space_remaining;
2611 struct ea_list *ea_list = NULL;
2612 NTSTATUS ntstatus = NT_STATUS_OK;
2613 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2614 TALLOC_CTX *ctx = talloc_tos();
2615 struct dptr_struct *dirptr;
2616 struct smbd_server_connection *sconn = req->sconn;
2618 if (total_params < 13) {
2619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2623 dptr_num = SVAL(params,0);
2624 maxentries = SVAL(params,2);
2625 info_level = SVAL(params,4);
2626 resume_key = IVAL(params,6);
2627 findnext_flags = SVAL(params,10);
2628 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2629 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2630 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2631 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2633 if (!continue_bit) {
2634 /* We only need resume_name if continue_bit is zero. */
2635 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2637 total_params - 12, STR_TERMINATE, &ntstatus,
2638 &mask_contains_wcard);
2639 if (!NT_STATUS_IS_OK(ntstatus)) {
2640 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2641 complain (it thinks we're asking for the directory above the shared
2642 path or an invalid name). Catch this as the resume name is only compared, never used in
2643 a file access. JRA. */
2644 srvstr_pull_talloc(ctx, params, req->flags2,
2645 &resume_name, params+12,
2649 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2650 reply_nterror(req, ntstatus);
2656 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2657 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2658 resume_key = %d resume name = %s continue=%d level = %d\n",
2659 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2660 requires_resume_key, resume_key,
2661 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2664 /* W2K3 seems to treat zero as 1. */
2668 switch (info_level) {
2669 case SMB_FIND_INFO_STANDARD:
2670 case SMB_FIND_EA_SIZE:
2671 case SMB_FIND_EA_LIST:
2672 case SMB_FIND_FILE_DIRECTORY_INFO:
2673 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2674 case SMB_FIND_FILE_NAMES_INFO:
2675 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2676 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2677 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2679 case SMB_FIND_FILE_UNIX:
2680 case SMB_FIND_FILE_UNIX_INFO2:
2681 /* Always use filesystem for UNIX mtime query. */
2682 ask_sharemode = false;
2683 if (!lp_unix_extensions()) {
2684 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2689 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2693 if (info_level == SMB_FIND_EA_LIST) {
2696 if (total_data < 4) {
2697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2701 ea_size = IVAL(pdata,0);
2702 if (ea_size != total_data) {
2703 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2704 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2709 if (!lp_ea_support(SNUM(conn))) {
2710 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2714 /* Pull out the list of names. */
2715 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2722 *ppdata = (char *)SMB_REALLOC(
2723 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2724 if(*ppdata == NULL) {
2725 reply_nterror(req, NT_STATUS_NO_MEMORY);
2730 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2732 /* Realloc the params space */
2733 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2734 if(*pparams == NULL ) {
2735 reply_nterror(req, NT_STATUS_NO_MEMORY);
2741 /* Check that the dptr is valid */
2742 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2743 reply_nterror(req, STATUS_NO_MORE_FILES);
2747 directory = dptr_path(sconn, dptr_num);
2749 /* Get the wildcard mask from the dptr */
2750 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2751 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2752 reply_nterror(req, STATUS_NO_MORE_FILES);
2758 /* Get the attr mask from the dptr */
2759 dirtype = dptr_attr(sconn, dptr_num);
2761 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2762 dptr_num, mask, dirtype,
2764 dptr_TellDir(dirptr)));
2766 /* Initialize per TRANS2_FIND_NEXT operation data */
2767 dptr_init_search_op(dirptr);
2769 /* We don't need to check for VOL here as this is returned by
2770 a different TRANS2 call. */
2772 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2773 directory,lp_dontdescend(SNUM(conn))));
2774 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2775 dont_descend = True;
2778 space_remaining = max_data_bytes;
2779 out_of_space = False;
2782 * Seek to the correct position. We no longer use the resume key but
2783 * depend on the last file name instead.
2786 if(!continue_bit && resume_name && *resume_name) {
2789 long current_pos = 0;
2791 * Remember, name_to_8_3 is called by
2792 * get_lanman2_dir_entry(), so the resume name
2793 * could be mangled. Ensure we check the unmangled name.
2796 if (mangle_is_mangled(resume_name, conn->params)) {
2797 char *new_resume_name = NULL;
2798 mangle_lookup_name_from_8_3(ctx,
2802 if (new_resume_name) {
2803 resume_name = new_resume_name;
2808 * Fix for NT redirector problem triggered by resume key indexes
2809 * changing between directory scans. We now return a resume key of 0
2810 * and instead look for the filename to continue from (also given
2811 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2812 * findfirst/findnext (as is usual) then the directory pointer
2813 * should already be at the correct place.
2816 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2817 } /* end if resume_name && !continue_bit */
2819 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2820 bool got_exact_match = False;
2822 /* this is a heuristic to avoid seeking the dirptr except when
2823 absolutely necessary. It allows for a filename of about 40 chars */
2824 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2825 out_of_space = True;
2828 finished = !get_lanman2_dir_entry(ctx,
2832 mask,dirtype,info_level,
2833 requires_resume_key,dont_descend,
2836 space_remaining, &out_of_space,
2838 &last_entry_off, ea_list);
2841 if (finished && out_of_space)
2844 if (!finished && !out_of_space)
2848 * As an optimisation if we know we aren't looking
2849 * for a wildcard name (ie. the name matches the wildcard exactly)
2850 * then we can finish on any (first) match.
2851 * This speeds up large directory searches. JRA.
2857 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2860 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2861 smb_fn_name(req->cmd),
2862 mask, directory, dirtype, numentries ) );
2864 /* Check if we can close the dirptr */
2865 if(close_after_request || (finished && close_if_end)) {
2866 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2867 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2870 /* Set up the return parameter block */
2871 SSVAL(params,0,numentries);
2872 SSVAL(params,2,finished);
2873 SSVAL(params,4,0); /* Never an EA error */
2874 SSVAL(params,6,last_entry_off);
2876 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2882 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2884 E_md4hash(lp_servicename(SNUM(conn)),objid);
2888 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2890 SMB_ASSERT(extended_info != NULL);
2892 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2893 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2894 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2895 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2896 #ifdef SAMBA_VERSION_REVISION
2897 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2899 extended_info->samba_subversion = 0;
2900 #ifdef SAMBA_VERSION_RC_RELEASE
2901 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2903 #ifdef SAMBA_VERSION_PRE_RELEASE
2904 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2907 #ifdef SAMBA_VERSION_VENDOR_PATCH
2908 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2910 extended_info->samba_gitcommitdate = 0;
2911 #ifdef SAMBA_VERSION_COMMIT_TIME
2912 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2915 memset(extended_info->samba_version_string, 0,
2916 sizeof(extended_info->samba_version_string));
2918 snprintf (extended_info->samba_version_string,
2919 sizeof(extended_info->samba_version_string),
2920 "%s", samba_version_string());
2923 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2924 TALLOC_CTX *mem_ctx,
2925 uint16_t info_level,
2927 unsigned int max_data_bytes,
2931 char *pdata, *end_data;
2932 int data_len = 0, len;
2933 const char *vname = volume_label(SNUM(conn));
2934 int snum = SNUM(conn);
2935 char *fstype = lp_fstype(SNUM(conn));
2936 uint32 additional_flags = 0;
2937 struct smb_filename smb_fname_dot;
2941 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2942 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2943 "info level (0x%x) on IPC$.\n",
2944 (unsigned int)info_level));
2945 return NT_STATUS_ACCESS_DENIED;
2949 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2951 ZERO_STRUCT(smb_fname_dot);
2952 smb_fname_dot.base_name = discard_const_p(char, ".");
2954 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2955 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2956 return map_nt_error_from_unix(errno);
2959 st = smb_fname_dot.st;
2961 *ppdata = (char *)SMB_REALLOC(
2962 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2963 if (*ppdata == NULL) {
2964 return NT_STATUS_NO_MEMORY;
2968 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2969 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2971 switch (info_level) {
2972 case SMB_INFO_ALLOCATION:
2974 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2976 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2977 return map_nt_error_from_unix(errno);
2980 block_size = lp_block_size(snum);
2981 if (bsize < block_size) {
2982 uint64_t factor = block_size/bsize;
2987 if (bsize > block_size) {
2988 uint64_t factor = bsize/block_size;
2993 bytes_per_sector = 512;
2994 sectors_per_unit = bsize/bytes_per_sector;
2996 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2997 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2998 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3000 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3001 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3002 SIVAL(pdata,l1_cUnit,dsize);
3003 SIVAL(pdata,l1_cUnitAvail,dfree);
3004 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3008 case SMB_INFO_VOLUME:
3009 /* Return volume name */
3011 * Add volume serial number - hash of a combination of
3012 * the called hostname and the service name.
3014 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3016 * Win2k3 and previous mess this up by sending a name length
3017 * one byte short. I believe only older clients (OS/2 Win9x) use
3018 * this call so try fixing this by adding a terminating null to
3019 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3023 pdata+l2_vol_szVolLabel, vname,
3024 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3025 STR_NOALIGN|STR_TERMINATE);
3026 SCVAL(pdata,l2_vol_cch,len);
3027 data_len = l2_vol_szVolLabel + len;
3028 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3029 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3033 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3034 case SMB_FS_ATTRIBUTE_INFORMATION:
3036 additional_flags = 0;
3037 #if defined(HAVE_SYS_QUOTAS)
3038 additional_flags |= FILE_VOLUME_QUOTAS;
3041 if(lp_nt_acl_support(SNUM(conn))) {
3042 additional_flags |= FILE_PERSISTENT_ACLS;
3045 /* Capabilities are filled in at connection time through STATVFS call */
3046 additional_flags |= conn->fs_capabilities;
3047 additional_flags |= lp_parm_int(conn->params->service,
3048 "share", "fake_fscaps",
3051 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3052 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3053 additional_flags); /* FS ATTRIBUTES */
3055 SIVAL(pdata,4,255); /* Max filename component length */
3056 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3057 and will think we can't do long filenames */
3058 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3059 PTR_DIFF(end_data, pdata+12),
3062 data_len = 12 + len;
3065 case SMB_QUERY_FS_LABEL_INFO:
3066 case SMB_FS_LABEL_INFORMATION:
3067 len = srvstr_push(pdata, flags2, pdata+4, vname,
3068 PTR_DIFF(end_data, pdata+4), 0);
3073 case SMB_QUERY_FS_VOLUME_INFO:
3074 case SMB_FS_VOLUME_INFORMATION:
3077 * Add volume serial number - hash of a combination of
3078 * the called hostname and the service name.
3080 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3081 (str_checksum(get_local_machine_name())<<16));
3083 /* Max label len is 32 characters. */
3084 len = srvstr_push(pdata, flags2, pdata+18, vname,
3085 PTR_DIFF(end_data, pdata+18),
3087 SIVAL(pdata,12,len);
3090 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3091 (int)strlen(vname),vname, lp_servicename(snum)));
3094 case SMB_QUERY_FS_SIZE_INFO:
3095 case SMB_FS_SIZE_INFORMATION:
3097 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3099 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3100 return map_nt_error_from_unix(errno);
3102 block_size = lp_block_size(snum);
3103 if (bsize < block_size) {
3104 uint64_t factor = block_size/bsize;
3109 if (bsize > block_size) {
3110 uint64_t factor = bsize/block_size;
3115 bytes_per_sector = 512;
3116 sectors_per_unit = bsize/bytes_per_sector;
3117 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3118 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3119 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3120 SBIG_UINT(pdata,0,dsize);
3121 SBIG_UINT(pdata,8,dfree);
3122 SIVAL(pdata,16,sectors_per_unit);
3123 SIVAL(pdata,20,bytes_per_sector);
3127 case SMB_FS_FULL_SIZE_INFORMATION:
3129 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3131 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3132 return map_nt_error_from_unix(errno);
3134 block_size = lp_block_size(snum);
3135 if (bsize < block_size) {
3136 uint64_t factor = block_size/bsize;
3141 if (bsize > block_size) {
3142 uint64_t factor = bsize/block_size;
3147 bytes_per_sector = 512;
3148 sectors_per_unit = bsize/bytes_per_sector;
3149 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3150 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3151 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3152 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3153 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3154 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3155 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3156 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3160 case SMB_QUERY_FS_DEVICE_INFO:
3161 case SMB_FS_DEVICE_INFORMATION:
3163 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3165 if (!CAN_WRITE(conn)) {
3166 characteristics |= FILE_READ_ONLY_DEVICE;
3169 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3170 SIVAL(pdata,4,characteristics);
3174 #ifdef HAVE_SYS_QUOTAS
3175 case SMB_FS_QUOTA_INFORMATION:
3177 * what we have to send --metze:
3179 * Unknown1: 24 NULL bytes
3180 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3181 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3182 * Quota Flags: 2 byte :
3183 * Unknown3: 6 NULL bytes
3187 * details for Quota Flags:
3189 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3190 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3191 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3192 * 0x0001 Enable Quotas: enable quota for this fs
3196 /* we need to fake up a fsp here,
3197 * because its not send in this call
3200 SMB_NTQUOTA_STRUCT quotas;
3203 ZERO_STRUCT(quotas);
3209 if (get_current_uid(conn) != 0) {
3210 DEBUG(0,("set_user_quota: access_denied "
3211 "service [%s] user [%s]\n",
3212 lp_servicename(SNUM(conn)),
3213 conn->session_info->unix_info->unix_name));
3214 return NT_STATUS_ACCESS_DENIED;
3217 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3218 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3219 return map_nt_error_from_unix(errno);
3224 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3225 lp_servicename(SNUM(conn))));
3227 /* Unknown1 24 NULL bytes*/
3228 SBIG_UINT(pdata,0,(uint64_t)0);
3229 SBIG_UINT(pdata,8,(uint64_t)0);
3230 SBIG_UINT(pdata,16,(uint64_t)0);
3232 /* Default Soft Quota 8 bytes */
3233 SBIG_UINT(pdata,24,quotas.softlim);
3235 /* Default Hard Quota 8 bytes */
3236 SBIG_UINT(pdata,32,quotas.hardlim);
3238 /* Quota flag 2 bytes */
3239 SSVAL(pdata,40,quotas.qflags);
3241 /* Unknown3 6 NULL bytes */
3247 #endif /* HAVE_SYS_QUOTAS */
3248 case SMB_FS_OBJECTID_INFORMATION:
3250 unsigned char objid[16];
3251 struct smb_extended_info extended_info;
3252 memcpy(pdata,create_volume_objectid(conn, objid),16);
3253 samba_extended_info_version (&extended_info);
3254 SIVAL(pdata,16,extended_info.samba_magic);
3255 SIVAL(pdata,20,extended_info.samba_version);
3256 SIVAL(pdata,24,extended_info.samba_subversion);
3257 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3258 memcpy(pdata+36,extended_info.samba_version_string,28);
3264 * Query the version and capabilities of the CIFS UNIX extensions
3268 case SMB_QUERY_CIFS_UNIX_INFO:
3270 bool large_write = lp_min_receive_file_size() &&
3271 !srv_is_signing_active(conn->sconn);
3272 bool large_read = !srv_is_signing_active(conn->sconn);
3273 int encrypt_caps = 0;
3275 if (!lp_unix_extensions()) {
3276 return NT_STATUS_INVALID_LEVEL;
3279 switch (conn->encrypt_level) {
3285 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3288 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3289 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3290 large_write = false;
3296 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3297 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3299 /* We have POSIX ACLs, pathname, encryption,
3300 * large read/write, and locking capability. */
3302 SBIG_UINT(pdata,4,((uint64_t)(
3303 CIFS_UNIX_POSIX_ACLS_CAP|
3304 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3305 CIFS_UNIX_FCNTL_LOCKS_CAP|
3306 CIFS_UNIX_EXTATTR_CAP|
3307 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3309 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3311 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3315 case SMB_QUERY_POSIX_FS_INFO:
3318 vfs_statvfs_struct svfs;
3320 if (!lp_unix_extensions()) {
3321 return NT_STATUS_INVALID_LEVEL;
3324 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3328 SIVAL(pdata,0,svfs.OptimalTransferSize);
3329 SIVAL(pdata,4,svfs.BlockSize);
3330 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3331 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3332 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3333 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3334 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3335 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3336 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3338 } else if (rc == EOPNOTSUPP) {
3339 return NT_STATUS_INVALID_LEVEL;
3340 #endif /* EOPNOTSUPP */
3342 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3343 return NT_STATUS_DOS(ERRSRV, ERRerror);
3348 case SMB_QUERY_POSIX_WHOAMI:
3354 if (!lp_unix_extensions()) {
3355 return NT_STATUS_INVALID_LEVEL;
3358 if (max_data_bytes < 40) {
3359 return NT_STATUS_BUFFER_TOO_SMALL;
3362 /* We ARE guest if global_sid_Builtin_Guests is
3363 * in our list of SIDs.
3365 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3366 conn->session_info->security_token)) {
3367 flags |= SMB_WHOAMI_GUEST;
3370 /* We are NOT guest if global_sid_Authenticated_Users
3371 * is in our list of SIDs.
3373 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3374 conn->session_info->security_token)) {
3375 flags &= ~SMB_WHOAMI_GUEST;
3378 /* NOTE: 8 bytes for UID/GID, irrespective of native
3379 * platform size. This matches
3380 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3382 data_len = 4 /* flags */
3389 + 4 /* pad/reserved */
3390 + (conn->session_info->unix_token->ngroups * 8)
3392 + (conn->session_info->security_token->num_sids *
3396 SIVAL(pdata, 0, flags);
3397 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3399 (uint64_t)conn->session_info->unix_token->uid);
3400 SBIG_UINT(pdata, 16,
3401 (uint64_t)conn->session_info->unix_token->gid);
3404 if (data_len >= max_data_bytes) {
3405 /* Potential overflow, skip the GIDs and SIDs. */
3407 SIVAL(pdata, 24, 0); /* num_groups */
3408 SIVAL(pdata, 28, 0); /* num_sids */
3409 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3410 SIVAL(pdata, 36, 0); /* reserved */
3416 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3417 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3419 /* We walk the SID list twice, but this call is fairly
3420 * infrequent, and I don't expect that it's performance
3421 * sensitive -- jpeach
3423 for (i = 0, sid_bytes = 0;
3424 i < conn->session_info->security_token->num_sids; ++i) {
3425 sid_bytes += ndr_size_dom_sid(
3426 &conn->session_info->security_token->sids[i],
3430 /* SID list byte count */
3431 SIVAL(pdata, 32, sid_bytes);
3433 /* 4 bytes pad/reserved - must be zero */
3434 SIVAL(pdata, 36, 0);
3438 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3439 SBIG_UINT(pdata, data_len,
3440 (uint64_t)conn->session_info->unix_token->groups[i]);
3446 i < conn->session_info->security_token->num_sids; ++i) {
3447 int sid_len = ndr_size_dom_sid(
3448 &conn->session_info->security_token->sids[i],
3451 sid_linearize(pdata + data_len, sid_len,
3452 &conn->session_info->security_token->sids[i]);
3453 data_len += sid_len;
3459 case SMB_MAC_QUERY_FS_INFO:
3461 * Thursby MAC extension... ONLY on NTFS filesystems
3462 * once we do streams then we don't need this
3464 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3466 SIVAL(pdata,84,0x100); /* Don't support mac... */
3471 return NT_STATUS_INVALID_LEVEL;
3474 *ret_data_len = data_len;
3475 return NT_STATUS_OK;
3478 /****************************************************************************
3479 Reply to a TRANS2_QFSINFO (query filesystem info).
3480 ****************************************************************************/
3482 static void call_trans2qfsinfo(connection_struct *conn,
3483 struct smb_request *req,
3484 char **pparams, int total_params,
3485 char **ppdata, int total_data,
3486 unsigned int max_data_bytes)
3488 char *params = *pparams;
3489 uint16_t info_level;
3493 if (total_params < 2) {
3494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3498 info_level = SVAL(params,0);
3500 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3501 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3502 DEBUG(0,("call_trans2qfsinfo: encryption required "
3503 "and info level 0x%x sent.\n",
3504 (unsigned int)info_level));
3505 exit_server_cleanly("encryption required "
3511 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3513 status = smbd_do_qfsinfo(conn, req,
3518 if (!NT_STATUS_IS_OK(status)) {
3519 reply_nterror(req, status);
3523 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3526 DEBUG( 4, ( "%s info_level = %d\n",
3527 smb_fn_name(req->cmd), info_level) );
3532 /****************************************************************************
3533 Reply to a TRANS2_SETFSINFO (set filesystem info).
3534 ****************************************************************************/
3536 static void call_trans2setfsinfo(connection_struct *conn,
3537 struct smb_request *req,
3538 char **pparams, int total_params,
3539 char **ppdata, int total_data,
3540 unsigned int max_data_bytes)
3542 struct smbd_server_connection *sconn = req->sconn;
3543 char *pdata = *ppdata;
3544 char *params = *pparams;
3547 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3550 if (total_params < 4) {
3551 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3553 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3557 info_level = SVAL(params,2);
3560 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3561 info_level != SMB_SET_CIFS_UNIX_INFO) {
3562 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3563 "info level (0x%x) on IPC$.\n",
3564 (unsigned int)info_level));
3565 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3570 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3571 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3572 DEBUG(0,("call_trans2setfsinfo: encryption required "
3573 "and info level 0x%x sent.\n",
3574 (unsigned int)info_level));
3575 exit_server_cleanly("encryption required "
3581 switch(info_level) {
3582 case SMB_SET_CIFS_UNIX_INFO:
3583 if (!lp_unix_extensions()) {
3585 NT_STATUS_INVALID_LEVEL);
3589 /* There should be 12 bytes of capabilities set. */
3590 if (total_data < 8) {
3593 NT_STATUS_INVALID_PARAMETER);
3596 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3597 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3598 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3599 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3600 /* Just print these values for now. */
3601 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3602 "major = %u, minor = %u cap_low = 0x%x, "
3604 (unsigned int)sconn->
3605 smb1.unix_info.client_major,
3606 (unsigned int)sconn->
3607 smb1.unix_info.client_minor,
3608 (unsigned int)sconn->
3609 smb1.unix_info.client_cap_low,
3610 (unsigned int)sconn->
3611 smb1.unix_info.client_cap_high));
3613 /* Here is where we must switch to posix pathname processing... */
3614 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3615 lp_set_posix_pathnames();
3616 mangle_change_to_posix();
3619 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3620 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3621 /* Client that knows how to do posix locks,
3622 * but not posix open/mkdir operations. Set a
3623 * default type for read/write checks. */
3625 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3630 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3633 size_t param_len = 0;
3634 size_t data_len = total_data;
3636 if (!lp_unix_extensions()) {
3639 NT_STATUS_INVALID_LEVEL);
3643 if (lp_smb_encrypt(SNUM(conn)) == false) {
3646 NT_STATUS_NOT_SUPPORTED);
3650 if (req->sconn->smb1.echo_handler.trusted_fde) {
3651 DEBUG( 2,("call_trans2setfsinfo: "
3652 "request transport encryption disabled"
3653 "with 'fork echo handler = yes'\n"));
3656 NT_STATUS_NOT_SUPPORTED);
3660 DEBUG( 4,("call_trans2setfsinfo: "
3661 "request transport encryption.\n"));
3663 status = srv_request_encryption_setup(conn,
3664 (unsigned char **)ppdata,
3666 (unsigned char **)pparams,
3669 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3670 !NT_STATUS_IS_OK(status)) {
3671 reply_nterror(req, status);
3675 send_trans2_replies(conn, req,
3682 if (NT_STATUS_IS_OK(status)) {
3683 /* Server-side transport
3684 * encryption is now *on*. */
3685 status = srv_encryption_start(conn);
3686 if (!NT_STATUS_IS_OK(status)) {
3687 exit_server_cleanly(
3688 "Failure in setting "
3689 "up encrypted transport");
3695 case SMB_FS_QUOTA_INFORMATION:
3697 files_struct *fsp = NULL;
3698 SMB_NTQUOTA_STRUCT quotas;
3700 ZERO_STRUCT(quotas);
3703 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3704 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3705 lp_servicename(SNUM(conn)),
3706 conn->session_info->unix_info->unix_name));
3707 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3711 /* note: normaly there're 48 bytes,
3712 * but we didn't use the last 6 bytes for now
3715 fsp = file_fsp(req, SVAL(params,0));
3717 if (!check_fsp_ntquota_handle(conn, req,
3719 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3721 req, NT_STATUS_INVALID_HANDLE);
3725 if (total_data < 42) {
3726 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3730 NT_STATUS_INVALID_PARAMETER);
3734 /* unknown_1 24 NULL bytes in pdata*/
3736 /* the soft quotas 8 bytes (uint64_t)*/
3737 quotas.softlim = BVAL(pdata,24);
3739 /* the hard quotas 8 bytes (uint64_t)*/
3740 quotas.hardlim = BVAL(pdata,32);
3742 /* quota_flags 2 bytes **/
3743 quotas.qflags = SVAL(pdata,40);
3745 /* unknown_2 6 NULL bytes follow*/
3747 /* now set the quotas */
3748 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3749 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3750 reply_nterror(req, map_nt_error_from_unix(errno));
3757 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3759 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3765 * sending this reply works fine,
3766 * but I'm not sure it's the same
3767 * like windows do...
3770 reply_outbuf(req, 10, 0);
3773 #if defined(HAVE_POSIX_ACLS)
3774 /****************************************************************************
3775 Utility function to count the number of entries in a POSIX acl.
3776 ****************************************************************************/
3778 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3780 unsigned int ace_count = 0;
3781 int entry_id = SMB_ACL_FIRST_ENTRY;
3782 SMB_ACL_ENTRY_T entry;
3784 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3786 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3787 entry_id = SMB_ACL_NEXT_ENTRY;
3794 /****************************************************************************
3795 Utility function to marshall a POSIX acl into wire format.
3796 ****************************************************************************/
3798 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3800 int entry_id = SMB_ACL_FIRST_ENTRY;
3801 SMB_ACL_ENTRY_T entry;
3803 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3804 SMB_ACL_TAG_T tagtype;
3805 SMB_ACL_PERMSET_T permset;
3806 unsigned char perms = 0;
3807 unsigned int own_grp;
3810 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3811 entry_id = SMB_ACL_NEXT_ENTRY;
3814 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3815 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3819 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3820 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3824 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3825 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3826 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3828 SCVAL(pdata,1,perms);
3831 case SMB_ACL_USER_OBJ:
3832 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3833 own_grp = (unsigned int)pst->st_ex_uid;
3834 SIVAL(pdata,2,own_grp);
3839 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3841 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3844 own_grp = (unsigned int)*puid;
3845 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3846 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3847 SIVAL(pdata,2,own_grp);
3851 case SMB_ACL_GROUP_OBJ:
3852 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3853 own_grp = (unsigned int)pst->st_ex_gid;
3854 SIVAL(pdata,2,own_grp);
3859 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3861 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3864 own_grp = (unsigned int)*pgid;
3865 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3866 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3867 SIVAL(pdata,2,own_grp);
3872 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3873 SIVAL(pdata,2,0xFFFFFFFF);
3874 SIVAL(pdata,6,0xFFFFFFFF);
3877 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3878 SIVAL(pdata,2,0xFFFFFFFF);
3879 SIVAL(pdata,6,0xFFFFFFFF);
3882 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3885 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3892 /****************************************************************************
3893 Store the FILE_UNIX_BASIC info.
3894 ****************************************************************************/
3896 static char *store_file_unix_basic(connection_struct *conn,
3899 const SMB_STRUCT_STAT *psbuf)
3901 uint64_t file_index = get_FileIndex(conn, psbuf);
3903 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3904 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3906 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3909 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3912 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3913 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3914 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3917 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3921 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3925 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3928 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3932 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3936 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3939 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3943 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3950 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3951 * the chflags(2) (or equivalent) flags.
3953 * XXX: this really should be behind the VFS interface. To do this, we would
3954 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3955 * Each VFS module could then implement its own mapping as appropriate for the
3956 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3958 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3962 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3966 { UF_IMMUTABLE, EXT_IMMUTABLE },
3970 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3974 { UF_HIDDEN, EXT_HIDDEN },
3977 /* Do not remove. We need to guarantee that this array has at least one
3978 * entry to build on HP-UX.
3984 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3985 uint32 *smb_fflags, uint32 *smb_fmask)
3989 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3990 *smb_fmask |= info2_flags_map[i].smb_fflag;
3991 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3992 *smb_fflags |= info2_flags_map[i].smb_fflag;
3997 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3998 const uint32 smb_fflags,
3999 const uint32 smb_fmask,
4002 uint32 max_fmask = 0;
4005 *stat_fflags = psbuf->st_ex_flags;
4007 /* For each flags requested in smb_fmask, check the state of the
4008 * corresponding flag in smb_fflags and set or clear the matching
4012 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4013 max_fmask |= info2_flags_map[i].smb_fflag;
4014 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4015 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4016 *stat_fflags |= info2_flags_map[i].stat_fflag;
4018 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4023 /* If smb_fmask is asking to set any bits that are not supported by
4024 * our flag mappings, we should fail.
4026 if ((smb_fmask & max_fmask) != smb_fmask) {
4034 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4035 * of file flags and birth (create) time.
4037 static char *store_file_unix_basic_info2(connection_struct *conn,
4040 const SMB_STRUCT_STAT *psbuf)
4042 uint32 file_flags = 0;
4043 uint32 flags_mask = 0;
4045 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4047 /* Create (birth) time 64 bit */
4048 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4051 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4052 SIVAL(pdata, 0, file_flags); /* flags */
4053 SIVAL(pdata, 4, flags_mask); /* mask */
4059 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4060 const struct stream_struct *streams,
4062 unsigned int max_data_bytes,
4063 unsigned int *data_size)
4066 unsigned int ofs = 0;
4068 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4069 unsigned int next_offset;
4071 smb_ucs2_t *namebuf;
4073 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4074 streams[i].name, &namelen) ||
4077 return NT_STATUS_INVALID_PARAMETER;
4081 * name_buf is now null-terminated, we need to marshall as not
4087 SIVAL(data, ofs+4, namelen);
4088 SOFF_T(data, ofs+8, streams[i].size);
4089 SOFF_T(data, ofs+16, streams[i].alloc_size);
4090 memcpy(data+ofs+24, namebuf, namelen);
4091 TALLOC_FREE(namebuf);
4093 next_offset = ofs + 24 + namelen;
4095 if (i == num_streams-1) {
4096 SIVAL(data, ofs, 0);
4099 unsigned int align = ndr_align_size(next_offset, 8);
4101 memset(data+next_offset, 0, align);
4102 next_offset += align;
4104 SIVAL(data, ofs, next_offset - ofs);
4113 return NT_STATUS_OK;
4116 /****************************************************************************
4117 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4118 ****************************************************************************/
4120 static void call_trans2qpipeinfo(connection_struct *conn,
4121 struct smb_request *req,
4122 unsigned int tran_call,
4123 char **pparams, int total_params,
4124 char **ppdata, int total_data,
4125 unsigned int max_data_bytes)
4127 char *params = *pparams;
4128 char *pdata = *ppdata;
4129 unsigned int data_size = 0;
4130 unsigned int param_size = 2;
4135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4139 if (total_params < 4) {
4140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4144 fsp = file_fsp(req, SVAL(params,0));
4145 if (!fsp_is_np(fsp)) {
4146 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4150 info_level = SVAL(params,2);
4152 *pparams = (char *)SMB_REALLOC(*pparams,2);
4153 if (*pparams == NULL) {
4154 reply_nterror(req, NT_STATUS_NO_MEMORY);
4159 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4160 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4161 if (*ppdata == NULL ) {
4162 reply_nterror(req, NT_STATUS_NO_MEMORY);
4167 switch (info_level) {
4168 case SMB_FILE_STANDARD_INFORMATION:
4170 SOFF_T(pdata,0,4096LL);
4177 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4181 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4187 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4188 TALLOC_CTX *mem_ctx,
4189 uint16_t info_level,
4191 struct smb_filename *smb_fname,
4192 bool delete_pending,
4193 struct timespec write_time_ts,
4194 struct ea_list *ea_list,
4195 int lock_data_count,
4198 unsigned int max_data_bytes,
4200 unsigned int *pdata_size)
4202 char *pdata = *ppdata;
4203 char *dstart, *dend;
4204 unsigned int data_size;
4205 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4206 time_t create_time, mtime, atime, c_time;
4207 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4214 uint64_t file_size = 0;
4216 uint64_t allocation_size = 0;
4217 uint64_t file_index = 0;
4218 uint32_t access_mask = 0;
4220 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4221 return NT_STATUS_INVALID_LEVEL;
4224 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4225 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4226 info_level, max_data_bytes));
4228 mode = dos_mode(conn, smb_fname);
4229 nlink = psbuf->st_ex_nlink;
4231 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4235 if ((nlink > 0) && delete_pending) {
4239 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4240 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4241 if (*ppdata == NULL) {
4242 return NT_STATUS_NO_MEMORY;
4246 dend = dstart + data_size - 1;
4248 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4249 update_stat_ex_mtime(psbuf, write_time_ts);
4252 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4253 mtime_ts = psbuf->st_ex_mtime;
4254 atime_ts = psbuf->st_ex_atime;
4255 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4257 if (lp_dos_filetime_resolution(SNUM(conn))) {
4258 dos_filetime_timespec(&create_time_ts);
4259 dos_filetime_timespec(&mtime_ts);
4260 dos_filetime_timespec(&atime_ts);
4261 dos_filetime_timespec(&ctime_ts);
4264 create_time = convert_timespec_to_time_t(create_time_ts);
4265 mtime = convert_timespec_to_time_t(mtime_ts);
4266 atime = convert_timespec_to_time_t(atime_ts);
4267 c_time = convert_timespec_to_time_t(ctime_ts);
4269 p = strrchr_m(smb_fname->base_name,'/');
4271 base_name = smb_fname->base_name;
4275 /* NT expects the name to be in an exact form of the *full*
4276 filename. See the trans2 torture test */
4277 if (ISDOT(base_name)) {
4278 dos_fname = talloc_strdup(mem_ctx, "\\");
4280 return NT_STATUS_NO_MEMORY;
4283 dos_fname = talloc_asprintf(mem_ctx,
4285 smb_fname->base_name);
4287 return NT_STATUS_NO_MEMORY;
4289 if (is_ntfs_stream_smb_fname(smb_fname)) {
4290 dos_fname = talloc_asprintf(dos_fname, "%s",
4291 smb_fname->stream_name);
4293 return NT_STATUS_NO_MEMORY;
4297 string_replace(dos_fname, '/', '\\');
4300 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4303 /* Do we have this path open ? */
4305 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4306 fsp1 = file_find_di_first(conn->sconn, fileid);
4307 if (fsp1 && fsp1->initial_allocation_size) {
4308 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4312 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4313 file_size = get_file_size_stat(psbuf);
4317 pos = fsp->fh->position_information;
4321 access_mask = fsp->access_mask;
4323 /* GENERIC_EXECUTE mapping from Windows */
4324 access_mask = 0x12019F;
4327 /* This should be an index number - looks like
4330 I think this causes us to fail the IFSKIT
4331 BasicFileInformationTest. -tpot */
4332 file_index = get_FileIndex(conn, psbuf);
4334 switch (info_level) {
4335 case SMB_INFO_STANDARD:
4336 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4338 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4339 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4340 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4341 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4342 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4343 SSVAL(pdata,l1_attrFile,mode);
4346 case SMB_INFO_QUERY_EA_SIZE:
4348 unsigned int ea_size =
4349 estimate_ea_size(conn, fsp,
4350 smb_fname->base_name);
4351 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4353 srv_put_dos_date2(pdata,0,create_time);
4354 srv_put_dos_date2(pdata,4,atime);
4355 srv_put_dos_date2(pdata,8,mtime); /* write time */
4356 SIVAL(pdata,12,(uint32)file_size);
4357 SIVAL(pdata,16,(uint32)allocation_size);
4358 SSVAL(pdata,20,mode);
4359 SIVAL(pdata,22,ea_size);
4363 case SMB_INFO_IS_NAME_VALID:
4364 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4366 /* os/2 needs this ? really ?*/
4367 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4369 /* This is only reached for qpathinfo */
4373 case SMB_INFO_QUERY_EAS_FROM_LIST:
4375 size_t total_ea_len = 0;
4376 struct ea_list *ea_file_list = NULL;
4378 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4381 get_ea_list_from_file(mem_ctx, conn, fsp,
4382 smb_fname->base_name,
4384 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4386 if (!ea_list || (total_ea_len > data_size)) {
4388 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4392 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4396 case SMB_INFO_QUERY_ALL_EAS:
4398 /* We have data_size bytes to put EA's into. */
4399 size_t total_ea_len = 0;
4401 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4403 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4404 smb_fname->base_name,
4406 if (!ea_list || (total_ea_len > data_size)) {
4408 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4412 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4416 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4418 /* This is FileFullEaInformation - 0xF which maps to
4419 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4421 /* We have data_size bytes to put EA's into. */
4422 size_t total_ea_len = 0;
4423 struct ea_list *ea_file_list = NULL;
4425 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4427 /*TODO: add filtering and index handling */
4430 get_ea_list_from_file(mem_ctx, conn, fsp,
4431 smb_fname->base_name,
4433 if (!ea_file_list) {
4434 return NT_STATUS_NO_EAS_ON_FILE;
4437 status = fill_ea_chained_buffer(mem_ctx,
4441 conn, ea_file_list);
4442 if (!NT_STATUS_IS_OK(status)) {
4448 case SMB_FILE_BASIC_INFORMATION:
4449 case SMB_QUERY_FILE_BASIC_INFO:
4451 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4452 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4453 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4459 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4460 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4461 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4462 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4463 SIVAL(pdata,32,mode);
4465 DEBUG(5,("SMB_QFBI - "));
4466 DEBUG(5,("create: %s ", ctime(&create_time)));
4467 DEBUG(5,("access: %s ", ctime(&atime)));
4468 DEBUG(5,("write: %s ", ctime(&mtime)));
4469 DEBUG(5,("change: %s ", ctime(&c_time)));
4470 DEBUG(5,("mode: %x\n", mode));
4473 case SMB_FILE_STANDARD_INFORMATION:
4474 case SMB_QUERY_FILE_STANDARD_INFO:
4476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4478 SOFF_T(pdata,0,allocation_size);
4479 SOFF_T(pdata,8,file_size);
4480 SIVAL(pdata,16,nlink);
4481 SCVAL(pdata,20,delete_pending?1:0);
4482 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4483 SSVAL(pdata,22,0); /* Padding. */
4486 case SMB_FILE_EA_INFORMATION:
4487 case SMB_QUERY_FILE_EA_INFO:
4489 unsigned int ea_size =
4490 estimate_ea_size(conn, fsp, smb_fname->base_name);
4491 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4493 SIVAL(pdata,0,ea_size);
4497 /* Get the 8.3 name - used if NT SMB was negotiated. */
4498 case SMB_QUERY_FILE_ALT_NAME_INFO:
4499 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4502 char mangled_name[13];
4503 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4504 if (!name_to_8_3(base_name,mangled_name,
4505 True,conn->params)) {
4506 return NT_STATUS_NO_MEMORY;
4508 len = srvstr_push(dstart, flags2,
4509 pdata+4, mangled_name,
4510 PTR_DIFF(dend, pdata+4),
4512 data_size = 4 + len;
4517 case SMB_QUERY_FILE_NAME_INFO:
4521 this must be *exactly* right for ACLs on mapped drives to work
4523 len = srvstr_push(dstart, flags2,
4525 PTR_DIFF(dend, pdata+4),
4527 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4528 data_size = 4 + len;
4533 case SMB_FILE_ALLOCATION_INFORMATION:
4534 case SMB_QUERY_FILE_ALLOCATION_INFO:
4535 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4537 SOFF_T(pdata,0,allocation_size);
4540 case SMB_FILE_END_OF_FILE_INFORMATION:
4541 case SMB_QUERY_FILE_END_OF_FILEINFO:
4542 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4544 SOFF_T(pdata,0,file_size);
4547 case SMB_QUERY_FILE_ALL_INFO:
4548 case SMB_FILE_ALL_INFORMATION:
4551 unsigned int ea_size =
4552 estimate_ea_size(conn, fsp, smb_fname->base_name);
4553 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4554 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4555 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4556 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4557 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4558 SIVAL(pdata,32,mode);
4559 SIVAL(pdata,36,0); /* padding. */
4561 SOFF_T(pdata,0,allocation_size);
4562 SOFF_T(pdata,8,file_size);
4563 SIVAL(pdata,16,nlink);
4564 SCVAL(pdata,20,delete_pending);
4565 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4568 SIVAL(pdata,0,ea_size);
4569 pdata += 4; /* EA info */
4570 len = srvstr_push(dstart, flags2,
4572 PTR_DIFF(dend, pdata+4),
4576 data_size = PTR_DIFF(pdata,(*ppdata));
4580 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4583 unsigned int ea_size =
4584 estimate_ea_size(conn, fsp, smb_fname->base_name);
4585 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4586 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4587 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4588 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4589 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4590 SIVAL(pdata, 0x20, mode);
4591 SIVAL(pdata, 0x24, 0); /* padding. */
4592 SBVAL(pdata, 0x28, allocation_size);
4593 SBVAL(pdata, 0x30, file_size);
4594 SIVAL(pdata, 0x38, nlink);
4595 SCVAL(pdata, 0x3C, delete_pending);
4596 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4597 SSVAL(pdata, 0x3E, 0); /* padding */
4598 SBVAL(pdata, 0x40, file_index);
4599 SIVAL(pdata, 0x48, ea_size);
4600 SIVAL(pdata, 0x4C, access_mask);
4601 SBVAL(pdata, 0x50, pos);
4602 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4603 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4607 len = srvstr_push(dstart, flags2,
4609 PTR_DIFF(dend, pdata+4),
4613 data_size = PTR_DIFF(pdata,(*ppdata));
4616 case SMB_FILE_INTERNAL_INFORMATION:
4618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4619 SBVAL(pdata, 0, file_index);
4623 case SMB_FILE_ACCESS_INFORMATION:
4624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4625 SIVAL(pdata, 0, access_mask);
4629 case SMB_FILE_NAME_INFORMATION:
4630 /* Pathname with leading '\'. */
4633 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4634 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4635 SIVAL(pdata,0,byte_len);
4636 data_size = 4 + byte_len;
4640 case SMB_FILE_DISPOSITION_INFORMATION:
4641 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4643 SCVAL(pdata,0,delete_pending);
4646 case SMB_FILE_POSITION_INFORMATION:
4647 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4649 SOFF_T(pdata,0,pos);
4652 case SMB_FILE_MODE_INFORMATION:
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4654 SIVAL(pdata,0,mode);
4658 case SMB_FILE_ALIGNMENT_INFORMATION:
4659 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4660 SIVAL(pdata,0,0); /* No alignment needed. */
4665 * NT4 server just returns "invalid query" to this - if we try
4666 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4669 /* The first statement above is false - verified using Thursby
4670 * client against NT4 -- gcolley.
4672 case SMB_QUERY_FILE_STREAM_INFO:
4673 case SMB_FILE_STREAM_INFORMATION: {
4674 unsigned int num_streams = 0;
4675 struct stream_struct *streams = NULL;
4677 DEBUG(10,("smbd_do_qfilepathinfo: "
4678 "SMB_FILE_STREAM_INFORMATION\n"));
4680 if (is_ntfs_stream_smb_fname(smb_fname)) {
4681 return NT_STATUS_INVALID_PARAMETER;
4684 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4685 talloc_tos(), &num_streams, &streams);
4687 if (!NT_STATUS_IS_OK(status)) {
4688 DEBUG(10, ("could not get stream info: %s\n",
4689 nt_errstr(status)));
4693 status = marshall_stream_info(num_streams, streams,
4694 pdata, max_data_bytes,
4697 if (!NT_STATUS_IS_OK(status)) {
4698 DEBUG(10, ("marshall_stream_info failed: %s\n",
4699 nt_errstr(status)));
4703 TALLOC_FREE(streams);
4707 case SMB_QUERY_COMPRESSION_INFO:
4708 case SMB_FILE_COMPRESSION_INFORMATION:
4709 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4710 SOFF_T(pdata,0,file_size);
4711 SIVAL(pdata,8,0); /* ??? */
4712 SIVAL(pdata,12,0); /* ??? */
4716 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4717 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4718 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4719 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4720 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4721 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4722 SOFF_T(pdata,32,allocation_size);
4723 SOFF_T(pdata,40,file_size);
4724 SIVAL(pdata,48,mode);
4725 SIVAL(pdata,52,0); /* ??? */
4729 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4730 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4731 SIVAL(pdata,0,mode);
4737 * CIFS UNIX Extensions.
4740 case SMB_QUERY_FILE_UNIX_BASIC:
4742 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4743 data_size = PTR_DIFF(pdata,(*ppdata));
4745 DEBUG(4,("smbd_do_qfilepathinfo: "
4746 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4747 dump_data(4, (uint8_t *)(*ppdata), data_size);
4751 case SMB_QUERY_FILE_UNIX_INFO2:
4753 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4754 data_size = PTR_DIFF(pdata,(*ppdata));
4758 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4760 for (i=0; i<100; i++)
4761 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4767 case SMB_QUERY_FILE_UNIX_LINK:
4770 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4773 return NT_STATUS_NO_MEMORY;
4776 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4778 if(!S_ISLNK(psbuf->st_ex_mode)) {
4779 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4782 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4784 len = SMB_VFS_READLINK(conn,
4785 smb_fname->base_name,
4788 return map_nt_error_from_unix(errno);
4791 len = srvstr_push(dstart, flags2,
4793 PTR_DIFF(dend, pdata),
4796 data_size = PTR_DIFF(pdata,(*ppdata));
4801 #if defined(HAVE_POSIX_ACLS)
4802 case SMB_QUERY_POSIX_ACL:
4804 SMB_ACL_T file_acl = NULL;
4805 SMB_ACL_T def_acl = NULL;
4806 uint16 num_file_acls = 0;
4807 uint16 num_def_acls = 0;
4809 if (fsp && fsp->fh->fd != -1) {
4810 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4813 SMB_VFS_SYS_ACL_GET_FILE(conn,
4814 smb_fname->base_name,
4815 SMB_ACL_TYPE_ACCESS);
4818 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4819 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4820 "not implemented on "
4821 "filesystem containing %s\n",
4822 smb_fname->base_name));
4823 return NT_STATUS_NOT_IMPLEMENTED;
4826 if (S_ISDIR(psbuf->st_ex_mode)) {
4827 if (fsp && fsp->is_directory) {
4829 SMB_VFS_SYS_ACL_GET_FILE(
4831 fsp->fsp_name->base_name,
4832 SMB_ACL_TYPE_DEFAULT);
4835 SMB_VFS_SYS_ACL_GET_FILE(
4837 smb_fname->base_name,
4838 SMB_ACL_TYPE_DEFAULT);
4840 def_acl = free_empty_sys_acl(conn, def_acl);
4843 num_file_acls = count_acl_entries(conn, file_acl);
4844 num_def_acls = count_acl_entries(conn, def_acl);
4846 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4847 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4849 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4850 SMB_POSIX_ACL_HEADER_SIZE) ));
4852 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4855 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4857 return NT_STATUS_BUFFER_TOO_SMALL;
4860 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4861 SSVAL(pdata,2,num_file_acls);
4862 SSVAL(pdata,4,num_def_acls);
4863 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4865 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4868 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4870 return NT_STATUS_INTERNAL_ERROR;
4872 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4874 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4877 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4879 return NT_STATUS_INTERNAL_ERROR;
4883 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4886 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4888 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4894 case SMB_QUERY_POSIX_LOCK:
4899 enum brl_type lock_type;
4901 /* We need an open file with a real fd for this. */
4902 if (!fsp || fsp->fh->fd == -1) {
4903 return NT_STATUS_INVALID_LEVEL;
4906 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4907 return NT_STATUS_INVALID_PARAMETER;
4910 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4911 case POSIX_LOCK_TYPE_READ:
4912 lock_type = READ_LOCK;
4914 case POSIX_LOCK_TYPE_WRITE:
4915 lock_type = WRITE_LOCK;
4917 case POSIX_LOCK_TYPE_UNLOCK:
4919 /* There's no point in asking for an unlock... */
4920 return NT_STATUS_INVALID_PARAMETER;
4923 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4924 #if defined(HAVE_LONGLONG)
4925 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4926 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4927 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4928 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4929 #else /* HAVE_LONGLONG */
4930 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4931 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4932 #endif /* HAVE_LONGLONG */
4934 status = query_lock(fsp,
4941 if (ERROR_WAS_LOCK_DENIED(status)) {
4942 /* Here we need to report who has it locked... */
4943 data_size = POSIX_LOCK_DATA_SIZE;
4945 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4946 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4947 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4948 #if defined(HAVE_LONGLONG)
4949 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4950 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4951 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4952 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4953 #else /* HAVE_LONGLONG */
4954 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4955 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4956 #endif /* HAVE_LONGLONG */
4958 } else if (NT_STATUS_IS_OK(status)) {
4959 /* For success we just return a copy of what we sent
4960 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4961 data_size = POSIX_LOCK_DATA_SIZE;
4962 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4963 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4971 return NT_STATUS_INVALID_LEVEL;
4974 *pdata_size = data_size;
4975 return NT_STATUS_OK;
4978 /****************************************************************************
4979 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4980 file name or file id).
4981 ****************************************************************************/
4983 static void call_trans2qfilepathinfo(connection_struct *conn,
4984 struct smb_request *req,
4985 unsigned int tran_call,
4986 char **pparams, int total_params,
4987 char **ppdata, int total_data,
4988 unsigned int max_data_bytes)
4990 char *params = *pparams;
4991 char *pdata = *ppdata;
4993 unsigned int data_size = 0;
4994 unsigned int param_size = 2;
4995 struct smb_filename *smb_fname = NULL;
4996 bool delete_pending = False;
4997 struct timespec write_time_ts;
4998 files_struct *fsp = NULL;
4999 struct file_id fileid;
5000 struct ea_list *ea_list = NULL;
5001 int lock_data_count = 0;
5002 char *lock_data = NULL;
5003 NTSTATUS status = NT_STATUS_OK;
5006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5010 ZERO_STRUCT(write_time_ts);
5012 if (tran_call == TRANSACT2_QFILEINFO) {
5013 if (total_params < 4) {
5014 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5019 call_trans2qpipeinfo(conn, req, tran_call,
5020 pparams, total_params,
5026 fsp = file_fsp(req, SVAL(params,0));
5027 info_level = SVAL(params,2);
5029 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5031 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5032 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5036 /* Initial check for valid fsp ptr. */
5037 if (!check_fsp_open(conn, req, fsp)) {
5041 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5043 if (!NT_STATUS_IS_OK(status)) {
5044 reply_nterror(req, status);
5048 if(fsp->fake_file_handle) {
5050 * This is actually for the QUOTA_FAKE_FILE --metze
5053 /* We know this name is ok, it's already passed the checks. */
5055 } else if(fsp->fh->fd == -1) {
5057 * This is actually a QFILEINFO on a directory
5058 * handle (returned from an NT SMB). NT5.0 seems
5059 * to do this call. JRA.
5062 if (INFO_LEVEL_IS_UNIX(info_level)) {
5063 /* Always do lstat for UNIX calls. */
5064 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5065 DEBUG(3,("call_trans2qfilepathinfo: "
5066 "SMB_VFS_LSTAT of %s failed "
5068 smb_fname_str_dbg(smb_fname),
5071 map_nt_error_from_unix(errno));
5074 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5075 DEBUG(3,("call_trans2qfilepathinfo: "
5076 "SMB_VFS_STAT of %s failed (%s)\n",
5077 smb_fname_str_dbg(smb_fname),
5080 map_nt_error_from_unix(errno));
5084 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5085 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5088 * Original code - this is an open file.
5090 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5091 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5092 fsp->fnum, strerror(errno)));
5094 map_nt_error_from_unix(errno));
5097 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5098 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5106 if (total_params < 7) {
5107 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5111 info_level = SVAL(params,0);
5113 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5115 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5116 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5120 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5122 STR_TERMINATE, &status);
5123 if (!NT_STATUS_IS_OK(status)) {
5124 reply_nterror(req, status);
5128 status = filename_convert(req,
5130 req->flags2 & FLAGS2_DFS_PATHNAMES,
5135 if (!NT_STATUS_IS_OK(status)) {
5136 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5137 reply_botherror(req,
5138 NT_STATUS_PATH_NOT_COVERED,
5139 ERRSRV, ERRbadpath);
5142 reply_nterror(req, status);
5146 /* If this is a stream, check if there is a delete_pending. */
5147 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5148 && is_ntfs_stream_smb_fname(smb_fname)) {
5149 struct smb_filename *smb_fname_base = NULL;
5151 /* Create an smb_filename with stream_name == NULL. */
5153 create_synthetic_smb_fname(talloc_tos(),
5154 smb_fname->base_name,
5157 if (!NT_STATUS_IS_OK(status)) {
5158 reply_nterror(req, status);
5162 if (INFO_LEVEL_IS_UNIX(info_level)) {
5163 /* Always do lstat for UNIX calls. */
5164 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5165 DEBUG(3,("call_trans2qfilepathinfo: "
5166 "SMB_VFS_LSTAT of %s failed "
5168 smb_fname_str_dbg(smb_fname_base),
5170 TALLOC_FREE(smb_fname_base);
5172 map_nt_error_from_unix(errno));
5176 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5177 DEBUG(3,("call_trans2qfilepathinfo: "
5178 "fileinfo of %s failed "
5180 smb_fname_str_dbg(smb_fname_base),
5182 TALLOC_FREE(smb_fname_base);
5184 map_nt_error_from_unix(errno));
5189 status = file_name_hash(conn,
5190 smb_fname_str_dbg(smb_fname_base),
5192 if (!NT_STATUS_IS_OK(status)) {
5193 TALLOC_FREE(smb_fname_base);
5194 reply_nterror(req, status);
5198 fileid = vfs_file_id_from_sbuf(conn,
5199 &smb_fname_base->st);
5200 TALLOC_FREE(smb_fname_base);
5201 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5202 if (delete_pending) {
5203 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5208 if (INFO_LEVEL_IS_UNIX(info_level)) {
5209 /* Always do lstat for UNIX calls. */
5210 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5211 DEBUG(3,("call_trans2qfilepathinfo: "
5212 "SMB_VFS_LSTAT of %s failed (%s)\n",
5213 smb_fname_str_dbg(smb_fname),
5216 map_nt_error_from_unix(errno));
5221 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5222 DEBUG(3,("call_trans2qfilepathinfo: "
5223 "SMB_VFS_STAT of %s failed (%s)\n",
5224 smb_fname_str_dbg(smb_fname),
5227 map_nt_error_from_unix(errno));
5232 status = file_name_hash(conn,
5233 smb_fname_str_dbg(smb_fname),
5235 if (!NT_STATUS_IS_OK(status)) {
5236 reply_nterror(req, status);
5240 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5241 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5242 if (delete_pending) {
5243 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5248 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5249 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5250 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5252 /* Pull out any data sent here before we realloc. */
5253 switch (info_level) {
5254 case SMB_INFO_QUERY_EAS_FROM_LIST:
5256 /* Pull any EA list from the data portion. */
5259 if (total_data < 4) {
5261 req, NT_STATUS_INVALID_PARAMETER);
5264 ea_size = IVAL(pdata,0);
5266 if (total_data > 0 && ea_size != total_data) {
5267 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5268 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5270 req, NT_STATUS_INVALID_PARAMETER);
5274 if (!lp_ea_support(SNUM(conn))) {
5275 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5279 /* Pull out the list of names. */
5280 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5283 req, NT_STATUS_INVALID_PARAMETER);
5289 case SMB_QUERY_POSIX_LOCK:
5291 if (fsp == NULL || fsp->fh->fd == -1) {
5292 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5296 if (total_data != POSIX_LOCK_DATA_SIZE) {
5298 req, NT_STATUS_INVALID_PARAMETER);
5302 /* Copy the lock range data. */
5303 lock_data = (char *)talloc_memdup(
5304 req, pdata, total_data);
5306 reply_nterror(req, NT_STATUS_NO_MEMORY);
5309 lock_data_count = total_data;
5315 *pparams = (char *)SMB_REALLOC(*pparams,2);
5316 if (*pparams == NULL) {
5317 reply_nterror(req, NT_STATUS_NO_MEMORY);
5324 * draft-leach-cifs-v1-spec-02.txt
5325 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5328 * The requested information is placed in the Data portion of the
5329 * transaction response. For the information levels greater than 0x100,
5330 * the transaction response has 1 parameter word which should be
5331 * ignored by the client.
5333 * However Windows only follows this rule for the IS_NAME_VALID call.
5335 switch (info_level) {
5336 case SMB_INFO_IS_NAME_VALID:
5341 if ((info_level & 0xFF00) == 0xFF00) {
5343 * We use levels that start with 0xFF00
5344 * internally to represent SMB2 specific levels
5346 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5350 status = smbd_do_qfilepathinfo(conn, req, info_level,
5352 delete_pending, write_time_ts,
5354 lock_data_count, lock_data,
5355 req->flags2, max_data_bytes,
5356 ppdata, &data_size);
5357 if (!NT_STATUS_IS_OK(status)) {
5358 reply_nterror(req, status);
5362 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5368 /****************************************************************************
5369 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5371 ****************************************************************************/
5373 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5374 connection_struct *conn,
5375 struct smb_request *req,
5376 bool overwrite_if_exists,
5377 const struct smb_filename *smb_fname_old,
5378 struct smb_filename *smb_fname_new)
5380 NTSTATUS status = NT_STATUS_OK;
5382 /* source must already exist. */
5383 if (!VALID_STAT(smb_fname_old->st)) {
5384 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5387 if (VALID_STAT(smb_fname_new->st)) {
5388 if (overwrite_if_exists) {
5389 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5390 return NT_STATUS_FILE_IS_A_DIRECTORY;
5392 status = unlink_internals(conn,
5394 FILE_ATTRIBUTE_NORMAL,
5397 if (!NT_STATUS_IS_OK(status)) {
5401 /* Disallow if newname already exists. */
5402 return NT_STATUS_OBJECT_NAME_COLLISION;
5406 /* No links from a directory. */
5407 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5408 return NT_STATUS_FILE_IS_A_DIRECTORY;
5411 /* Setting a hardlink to/from a stream isn't currently supported. */
5412 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5413 is_ntfs_stream_smb_fname(smb_fname_new)) {
5414 return NT_STATUS_INVALID_PARAMETER;
5417 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5418 smb_fname_old->base_name, smb_fname_new->base_name));
5420 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5421 smb_fname_new->base_name) != 0) {
5422 status = map_nt_error_from_unix(errno);
5423 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5424 nt_errstr(status), smb_fname_old->base_name,
5425 smb_fname_new->base_name));
5430 /****************************************************************************
5431 Deal with setting the time from any of the setfilepathinfo functions.
5432 ****************************************************************************/
5434 NTSTATUS smb_set_file_time(connection_struct *conn,
5436 const struct smb_filename *smb_fname,
5437 struct smb_file_time *ft,
5438 bool setting_write_time)
5440 struct smb_filename smb_fname_base;
5442 FILE_NOTIFY_CHANGE_LAST_ACCESS
5443 |FILE_NOTIFY_CHANGE_LAST_WRITE
5444 |FILE_NOTIFY_CHANGE_CREATION;
5446 if (!VALID_STAT(smb_fname->st)) {
5447 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5450 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5451 return NT_STATUS_ACCESS_DENIED;
5454 /* get some defaults (no modifications) if any info is zero or -1. */
5455 if (null_timespec(ft->create_time)) {
5456 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5459 if (null_timespec(ft->atime)) {
5460 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5463 if (null_timespec(ft->mtime)) {
5464 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5467 if (!setting_write_time) {
5468 /* ft->mtime comes from change time, not write time. */
5469 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5472 /* Ensure the resolution is the correct for
5473 * what we can store on this filesystem. */
5475 round_timespec(conn->ts_res, &ft->create_time);
5476 round_timespec(conn->ts_res, &ft->ctime);
5477 round_timespec(conn->ts_res, &ft->atime);
5478 round_timespec(conn->ts_res, &ft->mtime);
5480 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5481 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5482 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5483 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5484 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5485 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5486 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5487 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5489 if (setting_write_time) {
5491 * This was a Windows setfileinfo on an open file.
5492 * NT does this a lot. We also need to
5493 * set the time here, as it can be read by
5494 * FindFirst/FindNext and with the patch for bug #2045
5495 * in smbd/fileio.c it ensures that this timestamp is
5496 * kept sticky even after a write. We save the request
5497 * away and will set it on file close and after a write. JRA.
5500 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5501 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5504 if (fsp->base_fsp) {
5505 set_sticky_write_time_fsp(fsp->base_fsp,
5508 set_sticky_write_time_fsp(fsp, ft->mtime);
5511 set_sticky_write_time_path(
5512 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5517 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5519 /* Always call ntimes on the base, even if a stream was passed in. */
5520 smb_fname_base = *smb_fname;
5521 smb_fname_base.stream_name = NULL;
5523 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5524 return map_nt_error_from_unix(errno);
5527 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5528 smb_fname->base_name);
5529 return NT_STATUS_OK;
5532 /****************************************************************************
5533 Deal with setting the dosmode from any of the setfilepathinfo functions.
5534 ****************************************************************************/
5536 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5537 const struct smb_filename *smb_fname,
5540 struct smb_filename *smb_fname_base = NULL;
5543 if (!VALID_STAT(smb_fname->st)) {
5544 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5547 /* Always operate on the base_name, even if a stream was passed in. */
5548 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5549 NULL, &smb_fname->st,
5551 if (!NT_STATUS_IS_OK(status)) {
5556 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5557 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5559 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5563 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5565 /* check the mode isn't different, before changing it */
5566 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5567 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5568 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5569 (unsigned int)dosmode));
5571 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5573 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5575 smb_fname_str_dbg(smb_fname_base),
5577 status = map_nt_error_from_unix(errno);
5581 status = NT_STATUS_OK;
5583 TALLOC_FREE(smb_fname_base);
5587 /****************************************************************************
5588 Deal with setting the size from any of the setfilepathinfo functions.
5589 ****************************************************************************/
5591 static NTSTATUS smb_set_file_size(connection_struct *conn,
5592 struct smb_request *req,
5594 const struct smb_filename *smb_fname,
5595 const SMB_STRUCT_STAT *psbuf,
5597 bool fail_after_createfile)
5599 NTSTATUS status = NT_STATUS_OK;
5600 struct smb_filename *smb_fname_tmp = NULL;
5601 files_struct *new_fsp = NULL;
5603 if (!VALID_STAT(*psbuf)) {
5604 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5607 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5608 return NT_STATUS_ACCESS_DENIED;
5611 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5613 if (size == get_file_size_stat(psbuf)) {
5614 return NT_STATUS_OK;
5617 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5618 smb_fname_str_dbg(smb_fname), (double)size));
5620 if (fsp && fsp->fh->fd != -1) {
5621 /* Handle based call. */
5622 if (vfs_set_filelen(fsp, size) == -1) {
5623 return map_nt_error_from_unix(errno);
5625 trigger_write_time_update_immediate(fsp);
5626 return NT_STATUS_OK;
5629 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5630 if (!NT_STATUS_IS_OK(status)) {
5634 smb_fname_tmp->st = *psbuf;
5636 status = SMB_VFS_CREATE_FILE(
5639 0, /* root_dir_fid */
5640 smb_fname_tmp, /* fname */
5641 FILE_WRITE_DATA, /* access_mask */
5642 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5644 FILE_OPEN, /* create_disposition*/
5645 0, /* create_options */
5646 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5647 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5648 0, /* allocation_size */
5649 0, /* private_flags */
5652 &new_fsp, /* result */
5655 TALLOC_FREE(smb_fname_tmp);
5657 if (!NT_STATUS_IS_OK(status)) {
5658 /* NB. We check for open_was_deferred in the caller. */
5662 /* See RAW-SFILEINFO-END-OF-FILE */
5663 if (fail_after_createfile) {
5664 close_file(req, new_fsp,NORMAL_CLOSE);
5665 return NT_STATUS_INVALID_LEVEL;
5668 if (vfs_set_filelen(new_fsp, size) == -1) {
5669 status = map_nt_error_from_unix(errno);
5670 close_file(req, new_fsp,NORMAL_CLOSE);
5674 trigger_write_time_update_immediate(new_fsp);
5675 close_file(req, new_fsp,NORMAL_CLOSE);
5676 return NT_STATUS_OK;
5679 /****************************************************************************
5680 Deal with SMB_INFO_SET_EA.
5681 ****************************************************************************/
5683 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5687 const struct smb_filename *smb_fname)
5689 struct ea_list *ea_list = NULL;
5690 TALLOC_CTX *ctx = NULL;
5691 NTSTATUS status = NT_STATUS_OK;
5693 if (total_data < 10) {
5695 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5696 length. They seem to have no effect. Bug #3212. JRA */
5698 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5699 /* We're done. We only get EA info in this call. */
5700 return NT_STATUS_OK;
5703 return NT_STATUS_INVALID_PARAMETER;
5706 if (IVAL(pdata,0) > total_data) {
5707 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5708 IVAL(pdata,0), (unsigned int)total_data));
5709 return NT_STATUS_INVALID_PARAMETER;
5713 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5715 return NT_STATUS_INVALID_PARAMETER;
5718 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5719 return NT_STATUS_ACCESS_DENIED;
5722 status = set_ea(conn, fsp, smb_fname, ea_list);
5727 /****************************************************************************
5728 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5729 ****************************************************************************/
5731 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5736 struct ea_list *ea_list = NULL;
5740 return NT_STATUS_INVALID_HANDLE;
5743 if (!lp_ea_support(SNUM(conn))) {
5744 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5745 "EA's not supported.\n",
5746 (unsigned int)total_data));
5747 return NT_STATUS_EAS_NOT_SUPPORTED;
5750 if (total_data < 10) {
5751 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5753 (unsigned int)total_data));
5754 return NT_STATUS_INVALID_PARAMETER;
5757 ea_list = read_nttrans_ea_list(talloc_tos(),
5762 return NT_STATUS_INVALID_PARAMETER;
5765 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5766 return NT_STATUS_ACCESS_DENIED;
5769 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5771 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5772 smb_fname_str_dbg(fsp->fsp_name),
5773 nt_errstr(status) ));
5779 /****************************************************************************
5780 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5781 ****************************************************************************/
5783 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5787 struct smb_filename *smb_fname)
5789 NTSTATUS status = NT_STATUS_OK;
5790 bool delete_on_close;
5793 if (total_data < 1) {
5794 return NT_STATUS_INVALID_PARAMETER;
5798 return NT_STATUS_INVALID_HANDLE;
5801 delete_on_close = (CVAL(pdata,0) ? True : False);
5802 dosmode = dos_mode(conn, smb_fname);
5804 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5805 "delete_on_close = %u\n",
5806 smb_fname_str_dbg(smb_fname),
5807 (unsigned int)dosmode,
5808 (unsigned int)delete_on_close ));
5810 if (delete_on_close) {
5811 status = can_set_delete_on_close(fsp, dosmode);
5812 if (!NT_STATUS_IS_OK(status)) {
5817 /* The set is across all open files on this dev/inode pair. */
5818 if (!set_delete_on_close(fsp, delete_on_close,
5819 conn->session_info->unix_token)) {
5820 return NT_STATUS_ACCESS_DENIED;
5822 return NT_STATUS_OK;
5825 /****************************************************************************
5826 Deal with SMB_FILE_POSITION_INFORMATION.
5827 ****************************************************************************/
5829 static NTSTATUS smb_file_position_information(connection_struct *conn,
5834 uint64_t position_information;
5836 if (total_data < 8) {
5837 return NT_STATUS_INVALID_PARAMETER;
5841 /* Ignore on pathname based set. */
5842 return NT_STATUS_OK;
5845 position_information = (uint64_t)IVAL(pdata,0);
5846 #ifdef LARGE_SMB_OFF_T
5847 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5848 #else /* LARGE_SMB_OFF_T */
5849 if (IVAL(pdata,4) != 0) {
5850 /* more than 32 bits? */
5851 return NT_STATUS_INVALID_PARAMETER;
5853 #endif /* LARGE_SMB_OFF_T */
5855 DEBUG(10,("smb_file_position_information: Set file position "
5856 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5857 (double)position_information));
5858 fsp->fh->position_information = position_information;
5859 return NT_STATUS_OK;
5862 /****************************************************************************
5863 Deal with SMB_FILE_MODE_INFORMATION.
5864 ****************************************************************************/
5866 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5872 if (total_data < 4) {
5873 return NT_STATUS_INVALID_PARAMETER;
5875 mode = IVAL(pdata,0);
5876 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5877 return NT_STATUS_INVALID_PARAMETER;
5879 return NT_STATUS_OK;
5882 /****************************************************************************
5883 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5884 ****************************************************************************/
5886 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5887 struct smb_request *req,
5890 const struct smb_filename *smb_fname)
5892 char *link_target = NULL;
5893 const char *newname = smb_fname->base_name;
5894 TALLOC_CTX *ctx = talloc_tos();
5896 /* Set a symbolic link. */
5897 /* Don't allow this if follow links is false. */
5899 if (total_data == 0) {
5900 return NT_STATUS_INVALID_PARAMETER;
5903 if (!lp_symlinks(SNUM(conn))) {
5904 return NT_STATUS_ACCESS_DENIED;
5907 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5908 total_data, STR_TERMINATE);
5911 return NT_STATUS_INVALID_PARAMETER;
5914 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5915 newname, link_target ));
5917 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5918 return map_nt_error_from_unix(errno);
5921 return NT_STATUS_OK;
5924 /****************************************************************************
5925 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5926 ****************************************************************************/
5928 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5929 struct smb_request *req,
5930 const char *pdata, int total_data,
5931 struct smb_filename *smb_fname_new)
5933 char *oldname = NULL;
5934 struct smb_filename *smb_fname_old = NULL;
5935 TALLOC_CTX *ctx = talloc_tos();
5936 NTSTATUS status = NT_STATUS_OK;
5938 /* Set a hard link. */
5939 if (total_data == 0) {
5940 return NT_STATUS_INVALID_PARAMETER;
5943 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5944 total_data, STR_TERMINATE, &status);
5945 if (!NT_STATUS_IS_OK(status)) {
5949 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5950 smb_fname_str_dbg(smb_fname_new), oldname));
5952 status = filename_convert(ctx,
5954 req->flags2 & FLAGS2_DFS_PATHNAMES,
5959 if (!NT_STATUS_IS_OK(status)) {
5963 return hardlink_internals(ctx, conn, req, false,
5964 smb_fname_old, smb_fname_new);
5967 /****************************************************************************
5968 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5969 ****************************************************************************/
5971 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5972 struct smb_request *req,
5976 struct smb_filename *smb_fname_src)
5980 char *newname = NULL;
5981 struct smb_filename *smb_fname_dst = NULL;
5982 NTSTATUS status = NT_STATUS_OK;
5983 TALLOC_CTX *ctx = talloc_tos();
5986 return NT_STATUS_INVALID_HANDLE;
5989 if (total_data < 20) {
5990 return NT_STATUS_INVALID_PARAMETER;
5993 overwrite = (CVAL(pdata,0) ? True : False);
5994 len = IVAL(pdata,16);
5996 if (len > (total_data - 20) || (len == 0)) {
5997 return NT_STATUS_INVALID_PARAMETER;
6000 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6001 &pdata[20], len, STR_TERMINATE,
6003 if (!NT_STATUS_IS_OK(status)) {
6007 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6010 status = filename_convert(ctx,
6012 req->flags2 & FLAGS2_DFS_PATHNAMES,
6017 if (!NT_STATUS_IS_OK(status)) {
6021 if (fsp->base_fsp) {
6022 /* newname must be a stream name. */
6023 if (newname[0] != ':') {
6024 return NT_STATUS_NOT_SUPPORTED;
6027 /* Create an smb_fname to call rename_internals_fsp() with. */
6028 status = create_synthetic_smb_fname(talloc_tos(),
6029 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6031 if (!NT_STATUS_IS_OK(status)) {
6036 * Set the original last component, since
6037 * rename_internals_fsp() requires it.
6039 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6041 if (smb_fname_dst->original_lcomp == NULL) {
6042 status = NT_STATUS_NO_MEMORY;
6048 DEBUG(10,("smb2_file_rename_information: "
6049 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6050 fsp->fnum, fsp_str_dbg(fsp),
6051 smb_fname_str_dbg(smb_fname_dst)));
6052 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6053 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6057 TALLOC_FREE(smb_fname_dst);
6061 static NTSTATUS smb_file_link_information(connection_struct *conn,
6062 struct smb_request *req,
6066 struct smb_filename *smb_fname_src)
6070 char *newname = NULL;
6071 struct smb_filename *smb_fname_dst = NULL;
6072 NTSTATUS status = NT_STATUS_OK;
6073 TALLOC_CTX *ctx = talloc_tos();
6076 return NT_STATUS_INVALID_HANDLE;
6079 if (total_data < 20) {
6080 return NT_STATUS_INVALID_PARAMETER;
6083 overwrite = (CVAL(pdata,0) ? true : false);
6084 len = IVAL(pdata,16);
6086 if (len > (total_data - 20) || (len == 0)) {
6087 return NT_STATUS_INVALID_PARAMETER;
6090 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6091 &pdata[20], len, STR_TERMINATE,
6093 if (!NT_STATUS_IS_OK(status)) {
6097 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6100 status = filename_convert(ctx,
6102 req->flags2 & FLAGS2_DFS_PATHNAMES,
6107 if (!NT_STATUS_IS_OK(status)) {
6111 if (fsp->base_fsp) {
6112 /* No stream names. */
6113 return NT_STATUS_NOT_SUPPORTED;
6116 DEBUG(10,("smb_file_link_information: "
6117 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6118 fsp->fnum, fsp_str_dbg(fsp),
6119 smb_fname_str_dbg(smb_fname_dst)));
6120 status = hardlink_internals(ctx,
6127 TALLOC_FREE(smb_fname_dst);
6131 /****************************************************************************
6132 Deal with SMB_FILE_RENAME_INFORMATION.
6133 ****************************************************************************/
6135 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6136 struct smb_request *req,
6140 struct smb_filename *smb_fname_src)
6145 char *newname = NULL;
6146 struct smb_filename *smb_fname_dst = NULL;
6147 bool dest_has_wcard = False;
6148 NTSTATUS status = NT_STATUS_OK;
6150 TALLOC_CTX *ctx = talloc_tos();
6152 if (total_data < 13) {
6153 return NT_STATUS_INVALID_PARAMETER;
6156 overwrite = (CVAL(pdata,0) ? True : False);
6157 root_fid = IVAL(pdata,4);
6158 len = IVAL(pdata,8);
6160 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6161 return NT_STATUS_INVALID_PARAMETER;
6164 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6167 if (!NT_STATUS_IS_OK(status)) {
6171 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6174 status = resolve_dfspath_wcard(ctx, conn,
6175 req->flags2 & FLAGS2_DFS_PATHNAMES,
6180 if (!NT_STATUS_IS_OK(status)) {
6184 /* Check the new name has no '/' characters. */
6185 if (strchr_m(newname, '/')) {
6186 return NT_STATUS_NOT_SUPPORTED;
6189 if (fsp && fsp->base_fsp) {
6190 /* newname must be a stream name. */
6191 if (newname[0] != ':') {
6192 return NT_STATUS_NOT_SUPPORTED;
6195 /* Create an smb_fname to call rename_internals_fsp() with. */
6196 status = create_synthetic_smb_fname(talloc_tos(),
6197 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6199 if (!NT_STATUS_IS_OK(status)) {
6204 * Set the original last component, since
6205 * rename_internals_fsp() requires it.
6207 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6209 if (smb_fname_dst->original_lcomp == NULL) {
6210 status = NT_STATUS_NO_MEMORY;
6216 * Build up an smb_fname_dst based on the filename passed in.
6217 * We basically just strip off the last component, and put on
6218 * the newname instead.
6220 char *base_name = NULL;
6222 /* newname must *not* be a stream name. */
6223 if (newname[0] == ':') {
6224 return NT_STATUS_NOT_SUPPORTED;
6228 * Strip off the last component (filename) of the path passed
6231 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6233 return NT_STATUS_NO_MEMORY;
6235 p = strrchr_m(base_name, '/');
6239 base_name = talloc_strdup(ctx, "");
6241 return NT_STATUS_NO_MEMORY;
6244 /* Append the new name. */
6245 base_name = talloc_asprintf_append(base_name,
6249 return NT_STATUS_NO_MEMORY;
6252 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6255 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6258 /* If an error we expect this to be
6259 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6261 if (!NT_STATUS_IS_OK(status)) {
6262 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6266 /* Create an smb_fname to call rename_internals_fsp() */
6267 status = create_synthetic_smb_fname(ctx,
6271 if (!NT_STATUS_IS_OK(status)) {
6278 DEBUG(10,("smb_file_rename_information: "
6279 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6280 fsp->fnum, fsp_str_dbg(fsp),
6281 smb_fname_str_dbg(smb_fname_dst)));
6282 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6285 DEBUG(10,("smb_file_rename_information: "
6286 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6287 smb_fname_str_dbg(smb_fname_src),
6288 smb_fname_str_dbg(smb_fname_dst)));
6289 status = rename_internals(ctx, conn, req, smb_fname_src,
6290 smb_fname_dst, 0, overwrite, false,
6292 FILE_WRITE_ATTRIBUTES);
6295 TALLOC_FREE(smb_fname_dst);
6299 /****************************************************************************
6300 Deal with SMB_SET_POSIX_ACL.
6301 ****************************************************************************/
6303 #if defined(HAVE_POSIX_ACLS)
6304 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6308 const struct smb_filename *smb_fname)
6310 uint16 posix_acl_version;
6311 uint16 num_file_acls;
6312 uint16 num_def_acls;
6313 bool valid_file_acls = True;
6314 bool valid_def_acls = True;
6316 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6317 return NT_STATUS_INVALID_PARAMETER;
6319 posix_acl_version = SVAL(pdata,0);
6320 num_file_acls = SVAL(pdata,2);
6321 num_def_acls = SVAL(pdata,4);
6323 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6324 valid_file_acls = False;
6328 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6329 valid_def_acls = False;
6333 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6334 return NT_STATUS_INVALID_PARAMETER;
6337 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6338 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6339 return NT_STATUS_INVALID_PARAMETER;
6342 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6343 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6344 (unsigned int)num_file_acls,
6345 (unsigned int)num_def_acls));
6347 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6348 smb_fname->base_name, num_file_acls,
6349 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6350 return map_nt_error_from_unix(errno);
6353 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6354 smb_fname->base_name, &smb_fname->st, num_def_acls,
6355 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6356 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6357 return map_nt_error_from_unix(errno);
6359 return NT_STATUS_OK;
6363 /****************************************************************************
6364 Deal with SMB_SET_POSIX_LOCK.
6365 ****************************************************************************/
6367 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6368 struct smb_request *req,
6376 bool blocking_lock = False;
6377 enum brl_type lock_type;
6379 NTSTATUS status = NT_STATUS_OK;
6381 if (fsp == NULL || fsp->fh->fd == -1) {
6382 return NT_STATUS_INVALID_HANDLE;
6385 if (total_data != POSIX_LOCK_DATA_SIZE) {
6386 return NT_STATUS_INVALID_PARAMETER;
6389 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6390 case POSIX_LOCK_TYPE_READ:
6391 lock_type = READ_LOCK;
6393 case POSIX_LOCK_TYPE_WRITE:
6394 /* Return the right POSIX-mappable error code for files opened read-only. */
6395 if (!fsp->can_write) {
6396 return NT_STATUS_INVALID_HANDLE;
6398 lock_type = WRITE_LOCK;
6400 case POSIX_LOCK_TYPE_UNLOCK:
6401 lock_type = UNLOCK_LOCK;
6404 return NT_STATUS_INVALID_PARAMETER;
6407 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6408 blocking_lock = False;
6409 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6410 blocking_lock = True;
6412 return NT_STATUS_INVALID_PARAMETER;
6415 if (!lp_blocking_locks(SNUM(conn))) {
6416 blocking_lock = False;
6419 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6420 #if defined(HAVE_LONGLONG)
6421 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6422 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6423 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6424 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6425 #else /* HAVE_LONGLONG */
6426 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6427 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6428 #endif /* HAVE_LONGLONG */
6430 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6431 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6433 (unsigned int)lock_type,
6434 (unsigned long long)smblctx,
6438 if (lock_type == UNLOCK_LOCK) {
6439 status = do_unlock(req->sconn->msg_ctx,
6446 uint64_t block_smblctx;
6448 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6460 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6462 * A blocking lock was requested. Package up
6463 * this smb into a queued request and push it
6464 * onto the blocking lock queue.
6466 if(push_blocking_lock_request(br_lck,
6469 -1, /* infinite timeout. */
6477 TALLOC_FREE(br_lck);
6481 TALLOC_FREE(br_lck);
6487 /****************************************************************************
6488 Deal with SMB_SET_FILE_BASIC_INFO.
6489 ****************************************************************************/
6491 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6495 const struct smb_filename *smb_fname)
6497 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6498 struct smb_file_time ft;
6500 NTSTATUS status = NT_STATUS_OK;
6504 if (total_data < 36) {
6505 return NT_STATUS_INVALID_PARAMETER;
6508 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6509 return NT_STATUS_ACCESS_DENIED;
6512 /* Set the attributes */
6513 dosmode = IVAL(pdata,32);
6514 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6515 if (!NT_STATUS_IS_OK(status)) {
6520 ft.create_time = interpret_long_date(pdata);
6523 ft.atime = interpret_long_date(pdata+8);
6526 ft.mtime = interpret_long_date(pdata+16);
6529 ft.ctime = interpret_long_date(pdata+24);
6531 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6532 smb_fname_str_dbg(smb_fname)));
6534 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6538 /****************************************************************************
6539 Deal with SMB_INFO_STANDARD.
6540 ****************************************************************************/
6542 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6546 const struct smb_filename *smb_fname)
6548 struct smb_file_time ft;
6552 if (total_data < 12) {
6553 return NT_STATUS_INVALID_PARAMETER;
6556 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6557 return NT_STATUS_ACCESS_DENIED;
6561 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6563 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6565 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6567 DEBUG(10,("smb_set_info_standard: file %s\n",
6568 smb_fname_str_dbg(smb_fname)));
6570 return smb_set_file_time(conn,
6577 /****************************************************************************
6578 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6579 ****************************************************************************/
6581 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6582 struct smb_request *req,
6586 struct smb_filename *smb_fname)
6588 uint64_t allocation_size = 0;
6589 NTSTATUS status = NT_STATUS_OK;
6590 files_struct *new_fsp = NULL;
6592 if (!VALID_STAT(smb_fname->st)) {
6593 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6596 if (total_data < 8) {
6597 return NT_STATUS_INVALID_PARAMETER;
6600 allocation_size = (uint64_t)IVAL(pdata,0);
6601 #ifdef LARGE_SMB_OFF_T
6602 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6603 #else /* LARGE_SMB_OFF_T */
6604 if (IVAL(pdata,4) != 0) {
6605 /* more than 32 bits? */
6606 return NT_STATUS_INVALID_PARAMETER;
6608 #endif /* LARGE_SMB_OFF_T */
6610 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6611 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6612 (double)allocation_size));
6614 if (allocation_size) {
6615 allocation_size = smb_roundup(conn, allocation_size);
6618 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6619 return NT_STATUS_ACCESS_DENIED;
6622 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6623 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6624 (double)allocation_size));
6626 if (fsp && fsp->fh->fd != -1) {
6627 /* Open file handle. */
6628 /* Only change if needed. */
6629 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6630 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6631 return map_nt_error_from_unix(errno);
6634 /* But always update the time. */
6636 * This is equivalent to a write. Ensure it's seen immediately
6637 * if there are no pending writes.
6639 trigger_write_time_update_immediate(fsp);
6640 return NT_STATUS_OK;
6643 /* Pathname or stat or directory file. */
6644 status = SMB_VFS_CREATE_FILE(
6647 0, /* root_dir_fid */
6648 smb_fname, /* fname */
6649 FILE_WRITE_DATA, /* access_mask */
6650 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6652 FILE_OPEN, /* create_disposition*/
6653 0, /* create_options */
6654 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6655 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6656 0, /* allocation_size */
6657 0, /* private_flags */
6660 &new_fsp, /* result */
6663 if (!NT_STATUS_IS_OK(status)) {
6664 /* NB. We check for open_was_deferred in the caller. */
6668 /* Only change if needed. */
6669 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6670 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6671 status = map_nt_error_from_unix(errno);
6672 close_file(req, new_fsp, NORMAL_CLOSE);
6677 /* Changing the allocation size should set the last mod time. */
6679 * This is equivalent to a write. Ensure it's seen immediately
6680 * if there are no pending writes.
6682 trigger_write_time_update_immediate(new_fsp);
6684 close_file(req, new_fsp, NORMAL_CLOSE);
6685 return NT_STATUS_OK;
6688 /****************************************************************************
6689 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6690 ****************************************************************************/
6692 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6693 struct smb_request *req,
6697 const struct smb_filename *smb_fname,
6698 bool fail_after_createfile)
6702 if (total_data < 8) {
6703 return NT_STATUS_INVALID_PARAMETER;
6706 size = IVAL(pdata,0);
6707 #ifdef LARGE_SMB_OFF_T
6708 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6709 #else /* LARGE_SMB_OFF_T */
6710 if (IVAL(pdata,4) != 0) {
6711 /* more than 32 bits? */
6712 return NT_STATUS_INVALID_PARAMETER;
6714 #endif /* LARGE_SMB_OFF_T */
6715 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6716 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6719 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6720 return NT_STATUS_ACCESS_DENIED;
6723 return smb_set_file_size(conn, req,
6728 fail_after_createfile);
6731 /****************************************************************************
6732 Allow a UNIX info mknod.
6733 ****************************************************************************/
6735 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6738 const struct smb_filename *smb_fname)
6740 uint32 file_type = IVAL(pdata,56);
6741 #if defined(HAVE_MAKEDEV)
6742 uint32 dev_major = IVAL(pdata,60);
6743 uint32 dev_minor = IVAL(pdata,68);
6745 SMB_DEV_T dev = (SMB_DEV_T)0;
6746 uint32 raw_unixmode = IVAL(pdata,84);
6750 if (total_data < 100) {
6751 return NT_STATUS_INVALID_PARAMETER;
6754 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6755 PERM_NEW_FILE, &unixmode);
6756 if (!NT_STATUS_IS_OK(status)) {
6760 #if defined(HAVE_MAKEDEV)
6761 dev = makedev(dev_major, dev_minor);
6764 switch (file_type) {
6765 #if defined(S_IFIFO)
6766 case UNIX_TYPE_FIFO:
6767 unixmode |= S_IFIFO;
6770 #if defined(S_IFSOCK)
6771 case UNIX_TYPE_SOCKET:
6772 unixmode |= S_IFSOCK;
6775 #if defined(S_IFCHR)
6776 case UNIX_TYPE_CHARDEV:
6777 unixmode |= S_IFCHR;
6780 #if defined(S_IFBLK)
6781 case UNIX_TYPE_BLKDEV:
6782 unixmode |= S_IFBLK;
6786 return NT_STATUS_INVALID_PARAMETER;
6789 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6790 "%.0f mode 0%o for file %s\n", (double)dev,
6791 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6793 /* Ok - do the mknod. */
6794 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6795 return map_nt_error_from_unix(errno);
6798 /* If any of the other "set" calls fail we
6799 * don't want to end up with a half-constructed mknod.
6802 if (lp_inherit_perms(SNUM(conn))) {
6804 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6806 return NT_STATUS_NO_MEMORY;
6808 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6810 TALLOC_FREE(parent);
6813 return NT_STATUS_OK;
6816 /****************************************************************************
6817 Deal with SMB_SET_FILE_UNIX_BASIC.
6818 ****************************************************************************/
6820 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6821 struct smb_request *req,
6825 const struct smb_filename *smb_fname)
6827 struct smb_file_time ft;
6828 uint32 raw_unixmode;
6831 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6832 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6833 NTSTATUS status = NT_STATUS_OK;
6834 bool delete_on_fail = False;
6835 enum perm_type ptype;
6836 files_struct *all_fsps = NULL;
6837 bool modify_mtime = true;
6839 struct smb_filename *smb_fname_tmp = NULL;
6840 SMB_STRUCT_STAT sbuf;
6844 if (total_data < 100) {
6845 return NT_STATUS_INVALID_PARAMETER;
6848 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6849 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6850 size=IVAL(pdata,0); /* first 8 Bytes are size */
6851 #ifdef LARGE_SMB_OFF_T
6852 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6853 #else /* LARGE_SMB_OFF_T */
6854 if (IVAL(pdata,4) != 0) {
6855 /* more than 32 bits? */
6856 return NT_STATUS_INVALID_PARAMETER;
6858 #endif /* LARGE_SMB_OFF_T */
6861 ft.atime = interpret_long_date(pdata+24); /* access_time */
6862 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6863 set_owner = (uid_t)IVAL(pdata,40);
6864 set_grp = (gid_t)IVAL(pdata,48);
6865 raw_unixmode = IVAL(pdata,84);
6867 if (VALID_STAT(smb_fname->st)) {
6868 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6869 ptype = PERM_EXISTING_DIR;
6871 ptype = PERM_EXISTING_FILE;
6874 ptype = PERM_NEW_FILE;
6877 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6879 if (!NT_STATUS_IS_OK(status)) {
6883 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6884 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6885 smb_fname_str_dbg(smb_fname), (double)size,
6886 (unsigned int)set_owner, (unsigned int)set_grp,
6887 (int)raw_unixmode));
6889 sbuf = smb_fname->st;
6891 if (!VALID_STAT(sbuf)) {
6893 * The only valid use of this is to create character and block
6894 * devices, and named pipes. This is deprecated (IMHO) and
6895 * a new info level should be used for mknod. JRA.
6898 status = smb_unix_mknod(conn,
6902 if (!NT_STATUS_IS_OK(status)) {
6906 status = copy_smb_filename(talloc_tos(), smb_fname,
6908 if (!NT_STATUS_IS_OK(status)) {
6912 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6913 status = map_nt_error_from_unix(errno);
6914 TALLOC_FREE(smb_fname_tmp);
6915 SMB_VFS_UNLINK(conn, smb_fname);
6919 sbuf = smb_fname_tmp->st;
6920 smb_fname = smb_fname_tmp;
6922 /* Ensure we don't try and change anything else. */
6923 raw_unixmode = SMB_MODE_NO_CHANGE;
6924 size = get_file_size_stat(&sbuf);
6925 ft.atime = sbuf.st_ex_atime;
6926 ft.mtime = sbuf.st_ex_mtime;
6928 * We continue here as we might want to change the
6931 delete_on_fail = True;
6935 /* Horrible backwards compatibility hack as an old server bug
6936 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6940 size = get_file_size_stat(&sbuf);
6945 * Deal with the UNIX specific mode set.
6948 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6949 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6950 "setting mode 0%o for file %s\n",
6951 (unsigned int)unixmode,
6952 smb_fname_str_dbg(smb_fname)));
6953 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6954 return map_nt_error_from_unix(errno);
6959 * Deal with the UNIX specific uid set.
6962 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6963 (sbuf.st_ex_uid != set_owner)) {
6966 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6967 "changing owner %u for path %s\n",
6968 (unsigned int)set_owner,
6969 smb_fname_str_dbg(smb_fname)));
6971 if (S_ISLNK(sbuf.st_ex_mode)) {
6972 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6973 set_owner, (gid_t)-1);
6975 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6976 set_owner, (gid_t)-1);
6980 status = map_nt_error_from_unix(errno);
6981 if (delete_on_fail) {
6982 SMB_VFS_UNLINK(conn, smb_fname);
6989 * Deal with the UNIX specific gid set.
6992 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6993 (sbuf.st_ex_gid != set_grp)) {
6994 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6995 "changing group %u for file %s\n",
6996 (unsigned int)set_owner,
6997 smb_fname_str_dbg(smb_fname)));
6998 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7000 status = map_nt_error_from_unix(errno);
7001 if (delete_on_fail) {
7002 SMB_VFS_UNLINK(conn, smb_fname);
7008 /* Deal with any size changes. */
7010 status = smb_set_file_size(conn, req,
7016 if (!NT_STATUS_IS_OK(status)) {
7020 /* Deal with any time changes. */
7021 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7022 /* No change, don't cancel anything. */
7026 id = vfs_file_id_from_sbuf(conn, &sbuf);
7027 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7028 all_fsps = file_find_di_next(all_fsps)) {
7030 * We're setting the time explicitly for UNIX.
7031 * Cancel any pending changes over all handles.
7033 all_fsps->update_write_time_on_close = false;
7034 TALLOC_FREE(all_fsps->update_write_time_event);
7038 * Override the "setting_write_time"
7039 * parameter here as it almost does what
7040 * we need. Just remember if we modified
7041 * mtime and send the notify ourselves.
7043 if (null_timespec(ft.mtime)) {
7044 modify_mtime = false;
7047 status = smb_set_file_time(conn,
7053 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7054 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7059 /****************************************************************************
7060 Deal with SMB_SET_FILE_UNIX_INFO2.
7061 ****************************************************************************/
7063 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7064 struct smb_request *req,
7068 const struct smb_filename *smb_fname)
7074 if (total_data < 116) {
7075 return NT_STATUS_INVALID_PARAMETER;
7078 /* Start by setting all the fields that are common between UNIX_BASIC
7081 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7083 if (!NT_STATUS_IS_OK(status)) {
7087 smb_fflags = IVAL(pdata, 108);
7088 smb_fmask = IVAL(pdata, 112);
7090 /* NB: We should only attempt to alter the file flags if the client
7091 * sends a non-zero mask.
7093 if (smb_fmask != 0) {
7094 int stat_fflags = 0;
7096 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7097 smb_fmask, &stat_fflags)) {
7098 /* Client asked to alter a flag we don't understand. */
7099 return NT_STATUS_INVALID_PARAMETER;
7102 if (fsp && fsp->fh->fd != -1) {
7103 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7104 return NT_STATUS_NOT_SUPPORTED;
7106 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7107 stat_fflags) != 0) {
7108 return map_nt_error_from_unix(errno);
7113 /* XXX: need to add support for changing the create_time here. You
7114 * can do this for paths on Darwin with setattrlist(2). The right way
7115 * to hook this up is probably by extending the VFS utimes interface.
7118 return NT_STATUS_OK;
7121 /****************************************************************************
7122 Create a directory with POSIX semantics.
7123 ****************************************************************************/
7125 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7126 struct smb_request *req,
7129 struct smb_filename *smb_fname,
7130 int *pdata_return_size)
7132 NTSTATUS status = NT_STATUS_OK;
7133 uint32 raw_unixmode = 0;
7134 uint32 mod_unixmode = 0;
7135 mode_t unixmode = (mode_t)0;
7136 files_struct *fsp = NULL;
7137 uint16 info_level_return = 0;
7139 char *pdata = *ppdata;
7141 if (total_data < 18) {
7142 return NT_STATUS_INVALID_PARAMETER;
7145 raw_unixmode = IVAL(pdata,8);
7146 /* Next 4 bytes are not yet defined. */
7148 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7149 PERM_NEW_DIR, &unixmode);
7150 if (!NT_STATUS_IS_OK(status)) {
7154 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7156 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7157 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7159 status = SMB_VFS_CREATE_FILE(
7162 0, /* root_dir_fid */
7163 smb_fname, /* fname */
7164 FILE_READ_ATTRIBUTES, /* access_mask */
7165 FILE_SHARE_NONE, /* share_access */
7166 FILE_CREATE, /* create_disposition*/
7167 FILE_DIRECTORY_FILE, /* create_options */
7168 mod_unixmode, /* file_attributes */
7169 0, /* oplock_request */
7170 0, /* allocation_size */
7171 0, /* private_flags */
7177 if (NT_STATUS_IS_OK(status)) {
7178 close_file(req, fsp, NORMAL_CLOSE);
7181 info_level_return = SVAL(pdata,16);
7183 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7184 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7185 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7186 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7188 *pdata_return_size = 12;
7191 /* Realloc the data size */
7192 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7193 if (*ppdata == NULL) {
7194 *pdata_return_size = 0;
7195 return NT_STATUS_NO_MEMORY;
7199 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7200 SSVAL(pdata,2,0); /* No fnum. */
7201 SIVAL(pdata,4,info); /* Was directory created. */
7203 switch (info_level_return) {
7204 case SMB_QUERY_FILE_UNIX_BASIC:
7205 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7206 SSVAL(pdata,10,0); /* Padding. */
7207 store_file_unix_basic(conn, pdata + 12, fsp,
7210 case SMB_QUERY_FILE_UNIX_INFO2:
7211 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7212 SSVAL(pdata,10,0); /* Padding. */
7213 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7217 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7218 SSVAL(pdata,10,0); /* Padding. */
7225 /****************************************************************************
7226 Open/Create a file with POSIX semantics.
7227 ****************************************************************************/
7229 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7230 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7232 static NTSTATUS smb_posix_open(connection_struct *conn,
7233 struct smb_request *req,
7236 struct smb_filename *smb_fname,
7237 int *pdata_return_size)
7239 bool extended_oplock_granted = False;
7240 char *pdata = *ppdata;
7242 uint32 wire_open_mode = 0;
7243 uint32 raw_unixmode = 0;
7244 uint32 mod_unixmode = 0;
7245 uint32 create_disp = 0;
7246 uint32 access_mask = 0;
7247 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7248 NTSTATUS status = NT_STATUS_OK;
7249 mode_t unixmode = (mode_t)0;
7250 files_struct *fsp = NULL;
7251 int oplock_request = 0;
7253 uint16 info_level_return = 0;
7255 if (total_data < 18) {
7256 return NT_STATUS_INVALID_PARAMETER;
7259 flags = IVAL(pdata,0);
7260 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7261 if (oplock_request) {
7262 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7265 wire_open_mode = IVAL(pdata,4);
7267 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7268 return smb_posix_mkdir(conn, req,
7275 switch (wire_open_mode & SMB_ACCMODE) {
7277 access_mask = SMB_O_RDONLY_MAPPING;
7280 access_mask = SMB_O_WRONLY_MAPPING;
7283 access_mask = (SMB_O_RDONLY_MAPPING|
7284 SMB_O_WRONLY_MAPPING);
7287 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7288 (unsigned int)wire_open_mode ));
7289 return NT_STATUS_INVALID_PARAMETER;
7292 wire_open_mode &= ~SMB_ACCMODE;
7294 /* First take care of O_CREAT|O_EXCL interactions. */
7295 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7296 case (SMB_O_CREAT | SMB_O_EXCL):
7297 /* File exists fail. File not exist create. */
7298 create_disp = FILE_CREATE;
7301 /* File exists open. File not exist create. */
7302 create_disp = FILE_OPEN_IF;
7305 /* File exists open. File not exist fail. */
7306 create_disp = FILE_OPEN;
7309 /* O_EXCL on its own without O_CREAT is undefined. */
7311 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7312 (unsigned int)wire_open_mode ));
7313 return NT_STATUS_INVALID_PARAMETER;
7316 /* Next factor in the effects of O_TRUNC. */
7317 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7319 if (wire_open_mode & SMB_O_TRUNC) {
7320 switch (create_disp) {
7322 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7323 /* Leave create_disp alone as
7324 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7326 /* File exists fail. File not exist create. */
7329 /* SMB_O_CREAT | SMB_O_TRUNC */
7330 /* File exists overwrite. File not exist create. */
7331 create_disp = FILE_OVERWRITE_IF;
7335 /* File exists overwrite. File not exist fail. */
7336 create_disp = FILE_OVERWRITE;
7339 /* Cannot get here. */
7340 smb_panic("smb_posix_open: logic error");
7341 return NT_STATUS_INVALID_PARAMETER;
7345 raw_unixmode = IVAL(pdata,8);
7346 /* Next 4 bytes are not yet defined. */
7348 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7349 (VALID_STAT(smb_fname->st) ?
7350 PERM_EXISTING_FILE : PERM_NEW_FILE),
7353 if (!NT_STATUS_IS_OK(status)) {
7357 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7359 if (wire_open_mode & SMB_O_SYNC) {
7360 create_options |= FILE_WRITE_THROUGH;
7362 if (wire_open_mode & SMB_O_APPEND) {
7363 access_mask |= FILE_APPEND_DATA;
7365 if (wire_open_mode & SMB_O_DIRECT) {
7366 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7369 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7370 VALID_STAT_OF_DIR(smb_fname->st)) {
7371 if (access_mask != SMB_O_RDONLY_MAPPING) {
7372 return NT_STATUS_FILE_IS_A_DIRECTORY;
7374 create_options &= ~FILE_NON_DIRECTORY_FILE;
7375 create_options |= FILE_DIRECTORY_FILE;
7378 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7379 smb_fname_str_dbg(smb_fname),
7380 (unsigned int)wire_open_mode,
7381 (unsigned int)unixmode ));
7383 status = SMB_VFS_CREATE_FILE(
7386 0, /* root_dir_fid */
7387 smb_fname, /* fname */
7388 access_mask, /* access_mask */
7389 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7391 create_disp, /* create_disposition*/
7392 create_options, /* create_options */
7393 mod_unixmode, /* file_attributes */
7394 oplock_request, /* oplock_request */
7395 0, /* allocation_size */
7396 0, /* private_flags */
7402 if (!NT_STATUS_IS_OK(status)) {
7406 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7407 extended_oplock_granted = True;
7410 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7411 extended_oplock_granted = True;
7414 info_level_return = SVAL(pdata,16);
7416 /* Allocate the correct return size. */
7418 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7419 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7420 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7421 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7423 *pdata_return_size = 12;
7426 /* Realloc the data size */
7427 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7428 if (*ppdata == NULL) {
7429 close_file(req, fsp, ERROR_CLOSE);
7430 *pdata_return_size = 0;
7431 return NT_STATUS_NO_MEMORY;
7435 if (extended_oplock_granted) {
7436 if (flags & REQUEST_BATCH_OPLOCK) {
7437 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7439 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7441 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7442 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7444 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7447 SSVAL(pdata,2,fsp->fnum);
7448 SIVAL(pdata,4,info); /* Was file created etc. */
7450 switch (info_level_return) {
7451 case SMB_QUERY_FILE_UNIX_BASIC:
7452 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7453 SSVAL(pdata,10,0); /* padding. */
7454 store_file_unix_basic(conn, pdata + 12, fsp,
7457 case SMB_QUERY_FILE_UNIX_INFO2:
7458 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7459 SSVAL(pdata,10,0); /* padding. */
7460 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7464 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7465 SSVAL(pdata,10,0); /* padding. */
7468 return NT_STATUS_OK;
7471 /****************************************************************************
7472 Delete a file with POSIX semantics.
7473 ****************************************************************************/
7475 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7476 struct smb_request *req,
7479 struct smb_filename *smb_fname)
7481 NTSTATUS status = NT_STATUS_OK;
7482 files_struct *fsp = NULL;
7486 int create_options = 0;
7488 struct share_mode_lock *lck = NULL;
7490 if (total_data < 2) {
7491 return NT_STATUS_INVALID_PARAMETER;
7494 flags = SVAL(pdata,0);
7496 if (!VALID_STAT(smb_fname->st)) {
7497 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7500 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7501 !VALID_STAT_OF_DIR(smb_fname->st)) {
7502 return NT_STATUS_NOT_A_DIRECTORY;
7505 DEBUG(10,("smb_posix_unlink: %s %s\n",
7506 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7507 smb_fname_str_dbg(smb_fname)));
7509 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7510 create_options |= FILE_DIRECTORY_FILE;
7513 status = SMB_VFS_CREATE_FILE(
7516 0, /* root_dir_fid */
7517 smb_fname, /* fname */
7518 DELETE_ACCESS, /* access_mask */
7519 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7521 FILE_OPEN, /* create_disposition*/
7522 create_options, /* create_options */
7523 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7524 0, /* oplock_request */
7525 0, /* allocation_size */
7526 0, /* private_flags */
7532 if (!NT_STATUS_IS_OK(status)) {
7537 * Don't lie to client. If we can't really delete due to
7538 * non-POSIX opens return SHARING_VIOLATION.
7541 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7544 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7545 "lock for file %s\n", fsp_str_dbg(fsp)));
7546 close_file(req, fsp, NORMAL_CLOSE);
7547 return NT_STATUS_INVALID_PARAMETER;
7551 * See if others still have the file open. If this is the case, then
7552 * don't delete. If all opens are POSIX delete we can set the delete
7553 * on close disposition.
7555 for (i=0; i<lck->num_share_modes; i++) {
7556 struct share_mode_entry *e = &lck->share_modes[i];
7557 if (is_valid_share_mode_entry(e)) {
7558 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7561 /* Fail with sharing violation. */
7562 close_file(req, fsp, NORMAL_CLOSE);
7564 return NT_STATUS_SHARING_VIOLATION;
7569 * Set the delete on close.
7571 status = smb_set_file_disposition_info(conn,
7577 if (!NT_STATUS_IS_OK(status)) {
7578 close_file(req, fsp, NORMAL_CLOSE);
7583 return close_file(req, fsp, NORMAL_CLOSE);
7586 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7587 struct smb_request *req,
7588 TALLOC_CTX *mem_ctx,
7589 uint16_t info_level,
7591 struct smb_filename *smb_fname,
7592 char **ppdata, int total_data,
7595 char *pdata = *ppdata;
7596 NTSTATUS status = NT_STATUS_OK;
7597 int data_return_size = 0;
7601 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7602 return NT_STATUS_INVALID_LEVEL;
7605 if (!CAN_WRITE(conn)) {
7606 /* Allow POSIX opens. The open path will deny
7607 * any non-readonly opens. */
7608 if (info_level != SMB_POSIX_PATH_OPEN) {
7609 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7613 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7614 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7615 fsp ? fsp->fnum : -1, info_level, total_data));
7617 switch (info_level) {
7619 case SMB_INFO_STANDARD:
7621 status = smb_set_info_standard(conn,
7629 case SMB_INFO_SET_EA:
7631 status = smb_info_set_ea(conn,
7639 case SMB_SET_FILE_BASIC_INFO:
7640 case SMB_FILE_BASIC_INFORMATION:
7642 status = smb_set_file_basic_info(conn,
7650 case SMB_FILE_ALLOCATION_INFORMATION:
7651 case SMB_SET_FILE_ALLOCATION_INFO:
7653 status = smb_set_file_allocation_info(conn, req,
7661 case SMB_FILE_END_OF_FILE_INFORMATION:
7662 case SMB_SET_FILE_END_OF_FILE_INFO:
7665 * XP/Win7 both fail after the createfile with
7666 * SMB_SET_FILE_END_OF_FILE_INFO but not
7667 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7668 * The level is known here, so pass it down
7672 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7674 status = smb_set_file_end_of_file_info(conn, req,
7683 case SMB_FILE_DISPOSITION_INFORMATION:
7684 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7687 /* JRA - We used to just ignore this on a path ?
7688 * Shouldn't this be invalid level on a pathname
7691 if (tran_call != TRANSACT2_SETFILEINFO) {
7692 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7695 status = smb_set_file_disposition_info(conn,
7703 case SMB_FILE_POSITION_INFORMATION:
7705 status = smb_file_position_information(conn,
7712 case SMB_FILE_FULL_EA_INFORMATION:
7714 status = smb_set_file_full_ea_info(conn,
7721 /* From tridge Samba4 :
7722 * MODE_INFORMATION in setfileinfo (I have no
7723 * idea what "mode information" on a file is - it takes a value of 0,
7724 * 2, 4 or 6. What could it be?).
7727 case SMB_FILE_MODE_INFORMATION:
7729 status = smb_file_mode_information(conn,
7736 * CIFS UNIX extensions.
7739 case SMB_SET_FILE_UNIX_BASIC:
7741 status = smb_set_file_unix_basic(conn, req,
7749 case SMB_SET_FILE_UNIX_INFO2:
7751 status = smb_set_file_unix_info2(conn, req,
7759 case SMB_SET_FILE_UNIX_LINK:
7762 /* We must have a pathname for this. */
7763 return NT_STATUS_INVALID_LEVEL;
7765 status = smb_set_file_unix_link(conn, req, pdata,
7766 total_data, smb_fname);
7770 case SMB_SET_FILE_UNIX_HLINK:
7773 /* We must have a pathname for this. */
7774 return NT_STATUS_INVALID_LEVEL;
7776 status = smb_set_file_unix_hlink(conn, req,
7782 case SMB_FILE_RENAME_INFORMATION:
7784 status = smb_file_rename_information(conn, req,
7790 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7792 /* SMB2 rename information. */
7793 status = smb2_file_rename_information(conn, req,
7799 case SMB_FILE_LINK_INFORMATION:
7801 status = smb_file_link_information(conn, req,
7807 #if defined(HAVE_POSIX_ACLS)
7808 case SMB_SET_POSIX_ACL:
7810 status = smb_set_posix_acl(conn,
7819 case SMB_SET_POSIX_LOCK:
7822 return NT_STATUS_INVALID_LEVEL;
7824 status = smb_set_posix_lock(conn, req,
7825 pdata, total_data, fsp);
7829 case SMB_POSIX_PATH_OPEN:
7832 /* We must have a pathname for this. */
7833 return NT_STATUS_INVALID_LEVEL;
7836 status = smb_posix_open(conn, req,
7844 case SMB_POSIX_PATH_UNLINK:
7847 /* We must have a pathname for this. */
7848 return NT_STATUS_INVALID_LEVEL;
7851 status = smb_posix_unlink(conn, req,
7859 return NT_STATUS_INVALID_LEVEL;
7862 if (!NT_STATUS_IS_OK(status)) {
7866 *ret_data_size = data_return_size;
7867 return NT_STATUS_OK;
7870 /****************************************************************************
7871 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7872 ****************************************************************************/
7874 static void call_trans2setfilepathinfo(connection_struct *conn,
7875 struct smb_request *req,
7876 unsigned int tran_call,
7877 char **pparams, int total_params,
7878 char **ppdata, int total_data,
7879 unsigned int max_data_bytes)
7881 char *params = *pparams;
7882 char *pdata = *ppdata;
7884 struct smb_filename *smb_fname = NULL;
7885 files_struct *fsp = NULL;
7886 NTSTATUS status = NT_STATUS_OK;
7887 int data_return_size = 0;
7890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7894 if (tran_call == TRANSACT2_SETFILEINFO) {
7895 if (total_params < 4) {
7896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7900 fsp = file_fsp(req, SVAL(params,0));
7901 /* Basic check for non-null fsp. */
7902 if (!check_fsp_open(conn, req, fsp)) {
7905 info_level = SVAL(params,2);
7907 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7909 if (!NT_STATUS_IS_OK(status)) {
7910 reply_nterror(req, status);
7914 if(fsp->fh->fd == -1) {
7916 * This is actually a SETFILEINFO on a directory
7917 * handle (returned from an NT SMB). NT5.0 seems
7918 * to do this call. JRA.
7920 if (INFO_LEVEL_IS_UNIX(info_level)) {
7921 /* Always do lstat for UNIX calls. */
7922 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7923 DEBUG(3,("call_trans2setfilepathinfo: "
7924 "SMB_VFS_LSTAT of %s failed "
7926 smb_fname_str_dbg(smb_fname),
7928 reply_nterror(req, map_nt_error_from_unix(errno));
7932 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7933 DEBUG(3,("call_trans2setfilepathinfo: "
7934 "fileinfo of %s failed (%s)\n",
7935 smb_fname_str_dbg(smb_fname),
7937 reply_nterror(req, map_nt_error_from_unix(errno));
7941 } else if (fsp->print_file) {
7943 * Doing a DELETE_ON_CLOSE should cancel a print job.
7945 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7946 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7948 DEBUG(3,("call_trans2setfilepathinfo: "
7949 "Cancelling print job (%s)\n",
7953 send_trans2_replies(conn, req, params, 2,
7959 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7964 * Original code - this is an open file.
7966 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7967 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7968 "of fnum %d failed (%s)\n", fsp->fnum,
7970 reply_nterror(req, map_nt_error_from_unix(errno));
7978 if (total_params < 7) {
7979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7983 info_level = SVAL(params,0);
7984 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7985 total_params - 6, STR_TERMINATE,
7987 if (!NT_STATUS_IS_OK(status)) {
7988 reply_nterror(req, status);
7992 status = filename_convert(req, conn,
7993 req->flags2 & FLAGS2_DFS_PATHNAMES,
7998 if (!NT_STATUS_IS_OK(status)) {
7999 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8000 reply_botherror(req,
8001 NT_STATUS_PATH_NOT_COVERED,
8002 ERRSRV, ERRbadpath);
8005 reply_nterror(req, status);
8009 if (INFO_LEVEL_IS_UNIX(info_level)) {
8011 * For CIFS UNIX extensions the target name may not exist.
8014 /* Always do lstat for UNIX calls. */
8015 SMB_VFS_LSTAT(conn, smb_fname);
8017 } else if (!VALID_STAT(smb_fname->st) &&
8018 SMB_VFS_STAT(conn, smb_fname)) {
8019 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8021 smb_fname_str_dbg(smb_fname),
8023 reply_nterror(req, map_nt_error_from_unix(errno));
8028 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8029 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8030 fsp ? fsp->fnum : -1, info_level,total_data));
8032 /* Realloc the parameter size */
8033 *pparams = (char *)SMB_REALLOC(*pparams,2);
8034 if (*pparams == NULL) {
8035 reply_nterror(req, NT_STATUS_NO_MEMORY);
8042 status = smbd_do_setfilepathinfo(conn, req, req,
8048 if (!NT_STATUS_IS_OK(status)) {
8049 if (open_was_deferred(req->sconn, req->mid)) {
8050 /* We have re-scheduled this call. */
8053 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8054 /* We have re-scheduled this call. */
8057 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8058 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8059 ERRSRV, ERRbadpath);
8062 if (info_level == SMB_POSIX_PATH_OPEN) {
8063 reply_openerror(req, status);
8067 reply_nterror(req, status);
8071 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8077 /****************************************************************************
8078 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8079 ****************************************************************************/
8081 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8082 char **pparams, int total_params,
8083 char **ppdata, int total_data,
8084 unsigned int max_data_bytes)
8086 struct smb_filename *smb_dname = NULL;
8087 char *params = *pparams;
8088 char *pdata = *ppdata;
8089 char *directory = NULL;
8090 NTSTATUS status = NT_STATUS_OK;
8091 struct ea_list *ea_list = NULL;
8092 TALLOC_CTX *ctx = talloc_tos();
8094 if (!CAN_WRITE(conn)) {
8095 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8099 if (total_params < 5) {
8100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8104 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8105 total_params - 4, STR_TERMINATE,
8107 if (!NT_STATUS_IS_OK(status)) {
8108 reply_nterror(req, status);
8112 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8114 status = filename_convert(ctx,
8116 req->flags2 & FLAGS2_DFS_PATHNAMES,
8122 if (!NT_STATUS_IS_OK(status)) {
8123 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8124 reply_botherror(req,
8125 NT_STATUS_PATH_NOT_COVERED,
8126 ERRSRV, ERRbadpath);
8129 reply_nterror(req, status);
8134 * OS/2 workplace shell seems to send SET_EA requests of "null"
8135 * length (4 bytes containing IVAL 4).
8136 * They seem to have no effect. Bug #3212. JRA.
8139 if (total_data && (total_data != 4)) {
8140 /* Any data in this call is an EA list. */
8141 if (total_data < 10) {
8142 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8146 if (IVAL(pdata,0) > total_data) {
8147 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8148 IVAL(pdata,0), (unsigned int)total_data));
8149 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8153 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8160 if (!lp_ea_support(SNUM(conn))) {
8161 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8165 /* If total_data == 4 Windows doesn't care what values
8166 * are placed in that field, it just ignores them.
8167 * The System i QNTC IBM SMB client puts bad values here,
8168 * so ignore them. */
8170 status = create_directory(conn, req, smb_dname);
8172 if (!NT_STATUS_IS_OK(status)) {
8173 reply_nterror(req, status);
8177 /* Try and set any given EA. */
8179 status = set_ea(conn, NULL, smb_dname, ea_list);
8180 if (!NT_STATUS_IS_OK(status)) {
8181 reply_nterror(req, status);
8186 /* Realloc the parameter and data sizes */
8187 *pparams = (char *)SMB_REALLOC(*pparams,2);
8188 if(*pparams == NULL) {
8189 reply_nterror(req, NT_STATUS_NO_MEMORY);
8196 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8199 TALLOC_FREE(smb_dname);
8203 /****************************************************************************
8204 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8205 We don't actually do this - we just send a null response.
8206 ****************************************************************************/
8208 static void call_trans2findnotifyfirst(connection_struct *conn,
8209 struct smb_request *req,
8210 char **pparams, int total_params,
8211 char **ppdata, int total_data,
8212 unsigned int max_data_bytes)
8214 char *params = *pparams;
8217 if (total_params < 6) {
8218 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8222 info_level = SVAL(params,4);
8223 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8225 switch (info_level) {
8230 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8234 /* Realloc the parameter and data sizes */
8235 *pparams = (char *)SMB_REALLOC(*pparams,6);
8236 if (*pparams == NULL) {
8237 reply_nterror(req, NT_STATUS_NO_MEMORY);
8242 SSVAL(params,0,fnf_handle);
8243 SSVAL(params,2,0); /* No changes */
8244 SSVAL(params,4,0); /* No EA errors */
8251 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8256 /****************************************************************************
8257 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8258 changes). Currently this does nothing.
8259 ****************************************************************************/
8261 static void call_trans2findnotifynext(connection_struct *conn,
8262 struct smb_request *req,
8263 char **pparams, int total_params,
8264 char **ppdata, int total_data,
8265 unsigned int max_data_bytes)
8267 char *params = *pparams;
8269 DEBUG(3,("call_trans2findnotifynext\n"));
8271 /* Realloc the parameter and data sizes */
8272 *pparams = (char *)SMB_REALLOC(*pparams,4);
8273 if (*pparams == NULL) {
8274 reply_nterror(req, NT_STATUS_NO_MEMORY);
8279 SSVAL(params,0,0); /* No changes */
8280 SSVAL(params,2,0); /* No EA errors */
8282 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8287 /****************************************************************************
8288 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8289 ****************************************************************************/
8291 static void call_trans2getdfsreferral(connection_struct *conn,
8292 struct smb_request *req,
8293 char **pparams, int total_params,
8294 char **ppdata, int total_data,
8295 unsigned int max_data_bytes)
8297 char *params = *pparams;
8298 char *pathname = NULL;
8300 int max_referral_level;
8301 NTSTATUS status = NT_STATUS_OK;
8302 TALLOC_CTX *ctx = talloc_tos();
8304 DEBUG(10,("call_trans2getdfsreferral\n"));
8306 if (total_params < 3) {
8307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8311 max_referral_level = SVAL(params,0);
8313 if(!lp_host_msdfs()) {
8314 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8318 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8319 total_params - 2, STR_TERMINATE);
8321 reply_nterror(req, NT_STATUS_NOT_FOUND);
8324 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8325 ppdata,&status)) < 0) {
8326 reply_nterror(req, status);
8330 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8331 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8332 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8337 #define LMCAT_SPL 0x53
8338 #define LMFUNC_GETJOBID 0x60
8340 /****************************************************************************
8341 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8342 ****************************************************************************/
8344 static void call_trans2ioctl(connection_struct *conn,
8345 struct smb_request *req,
8346 char **pparams, int total_params,
8347 char **ppdata, int total_data,
8348 unsigned int max_data_bytes)
8350 char *pdata = *ppdata;
8351 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8353 /* check for an invalid fid before proceeding */
8356 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8360 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8361 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8362 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8363 if (*ppdata == NULL) {
8364 reply_nterror(req, NT_STATUS_NO_MEMORY);
8369 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8370 CAN ACCEPT THIS IN UNICODE. JRA. */
8373 if (fsp->print_file) {
8374 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8378 srvstr_push(pdata, req->flags2, pdata + 2,
8379 lp_netbios_name(), 15,
8380 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8381 srvstr_push(pdata, req->flags2, pdata+18,
8382 lp_servicename(SNUM(conn)), 13,
8383 STR_ASCII|STR_TERMINATE); /* Service name */
8384 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8389 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8390 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8393 /****************************************************************************
8394 Reply to a SMBfindclose (stop trans2 directory search).
8395 ****************************************************************************/
8397 void reply_findclose(struct smb_request *req)
8400 struct smbd_server_connection *sconn = req->sconn;
8402 START_PROFILE(SMBfindclose);
8405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8406 END_PROFILE(SMBfindclose);
8410 dptr_num = SVALS(req->vwv+0, 0);
8412 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8414 dptr_close(sconn, &dptr_num);
8416 reply_outbuf(req, 0, 0);
8418 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8420 END_PROFILE(SMBfindclose);
8424 /****************************************************************************
8425 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8426 ****************************************************************************/
8428 void reply_findnclose(struct smb_request *req)
8432 START_PROFILE(SMBfindnclose);
8435 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8436 END_PROFILE(SMBfindnclose);
8440 dptr_num = SVAL(req->vwv+0, 0);
8442 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8444 /* We never give out valid handles for a
8445 findnotifyfirst - so any dptr_num is ok here.
8448 reply_outbuf(req, 0, 0);
8450 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8452 END_PROFILE(SMBfindnclose);
8456 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8457 struct trans_state *state)
8459 if (get_Protocol() >= PROTOCOL_NT1) {
8460 req->flags2 |= 0x40; /* IS_LONG_NAME */
8461 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8464 if (conn->encrypt_level == Required && !req->encrypted) {
8465 if (state->call != TRANSACT2_QFSINFO &&
8466 state->call != TRANSACT2_SETFSINFO) {
8467 DEBUG(0,("handle_trans2: encryption required "
8469 (unsigned int)state->call));
8470 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8475 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8477 /* Now we must call the relevant TRANS2 function */
8478 switch(state->call) {
8479 case TRANSACT2_OPEN:
8481 START_PROFILE(Trans2_open);
8482 call_trans2open(conn, req,
8483 &state->param, state->total_param,
8484 &state->data, state->total_data,
8485 state->max_data_return);
8486 END_PROFILE(Trans2_open);
8490 case TRANSACT2_FINDFIRST:
8492 START_PROFILE(Trans2_findfirst);
8493 call_trans2findfirst(conn, req,
8494 &state->param, state->total_param,
8495 &state->data, state->total_data,
8496 state->max_data_return);
8497 END_PROFILE(Trans2_findfirst);
8501 case TRANSACT2_FINDNEXT:
8503 START_PROFILE(Trans2_findnext);
8504 call_trans2findnext(conn, req,
8505 &state->param, state->total_param,
8506 &state->data, state->total_data,
8507 state->max_data_return);
8508 END_PROFILE(Trans2_findnext);
8512 case TRANSACT2_QFSINFO:
8514 START_PROFILE(Trans2_qfsinfo);
8515 call_trans2qfsinfo(conn, req,
8516 &state->param, state->total_param,
8517 &state->data, state->total_data,
8518 state->max_data_return);
8519 END_PROFILE(Trans2_qfsinfo);
8523 case TRANSACT2_SETFSINFO:
8525 START_PROFILE(Trans2_setfsinfo);
8526 call_trans2setfsinfo(conn, req,
8527 &state->param, state->total_param,
8528 &state->data, state->total_data,
8529 state->max_data_return);
8530 END_PROFILE(Trans2_setfsinfo);
8534 case TRANSACT2_QPATHINFO:
8535 case TRANSACT2_QFILEINFO:
8537 START_PROFILE(Trans2_qpathinfo);
8538 call_trans2qfilepathinfo(conn, req, state->call,
8539 &state->param, state->total_param,
8540 &state->data, state->total_data,
8541 state->max_data_return);
8542 END_PROFILE(Trans2_qpathinfo);
8546 case TRANSACT2_SETPATHINFO:
8547 case TRANSACT2_SETFILEINFO:
8549 START_PROFILE(Trans2_setpathinfo);
8550 call_trans2setfilepathinfo(conn, req, state->call,
8551 &state->param, state->total_param,
8552 &state->data, state->total_data,
8553 state->max_data_return);
8554 END_PROFILE(Trans2_setpathinfo);
8558 case TRANSACT2_FINDNOTIFYFIRST:
8560 START_PROFILE(Trans2_findnotifyfirst);
8561 call_trans2findnotifyfirst(conn, req,
8562 &state->param, state->total_param,
8563 &state->data, state->total_data,
8564 state->max_data_return);
8565 END_PROFILE(Trans2_findnotifyfirst);
8569 case TRANSACT2_FINDNOTIFYNEXT:
8571 START_PROFILE(Trans2_findnotifynext);
8572 call_trans2findnotifynext(conn, req,
8573 &state->param, state->total_param,
8574 &state->data, state->total_data,
8575 state->max_data_return);
8576 END_PROFILE(Trans2_findnotifynext);
8580 case TRANSACT2_MKDIR:
8582 START_PROFILE(Trans2_mkdir);
8583 call_trans2mkdir(conn, req,
8584 &state->param, state->total_param,
8585 &state->data, state->total_data,
8586 state->max_data_return);
8587 END_PROFILE(Trans2_mkdir);
8591 case TRANSACT2_GET_DFS_REFERRAL:
8593 START_PROFILE(Trans2_get_dfs_referral);
8594 call_trans2getdfsreferral(conn, req,
8595 &state->param, state->total_param,
8596 &state->data, state->total_data,
8597 state->max_data_return);
8598 END_PROFILE(Trans2_get_dfs_referral);
8602 case TRANSACT2_IOCTL:
8604 START_PROFILE(Trans2_ioctl);
8605 call_trans2ioctl(conn, req,
8606 &state->param, state->total_param,
8607 &state->data, state->total_data,
8608 state->max_data_return);
8609 END_PROFILE(Trans2_ioctl);
8614 /* Error in request */
8615 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8616 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8620 /****************************************************************************
8621 Reply to a SMBtrans2.
8622 ****************************************************************************/
8624 void reply_trans2(struct smb_request *req)
8626 connection_struct *conn = req->conn;
8631 unsigned int tran_call;
8632 struct trans_state *state;
8635 START_PROFILE(SMBtrans2);
8637 if (req->wct < 14) {
8638 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8639 END_PROFILE(SMBtrans2);
8643 dsoff = SVAL(req->vwv+12, 0);
8644 dscnt = SVAL(req->vwv+11, 0);
8645 psoff = SVAL(req->vwv+10, 0);
8646 pscnt = SVAL(req->vwv+9, 0);
8647 tran_call = SVAL(req->vwv+14, 0);
8649 result = allow_new_trans(conn->pending_trans, req->mid);
8650 if (!NT_STATUS_IS_OK(result)) {
8651 DEBUG(2, ("Got invalid trans2 request: %s\n",
8652 nt_errstr(result)));
8653 reply_nterror(req, result);
8654 END_PROFILE(SMBtrans2);
8659 switch (tran_call) {
8660 /* List the allowed trans2 calls on IPC$ */
8661 case TRANSACT2_OPEN:
8662 case TRANSACT2_GET_DFS_REFERRAL:
8663 case TRANSACT2_QFILEINFO:
8664 case TRANSACT2_QFSINFO:
8665 case TRANSACT2_SETFSINFO:
8668 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8669 END_PROFILE(SMBtrans2);
8674 if ((state = talloc(conn, struct trans_state)) == NULL) {
8675 DEBUG(0, ("talloc failed\n"));
8676 reply_nterror(req, NT_STATUS_NO_MEMORY);
8677 END_PROFILE(SMBtrans2);
8681 state->cmd = SMBtrans2;
8683 state->mid = req->mid;
8684 state->vuid = req->vuid;
8685 state->setup_count = SVAL(req->vwv+13, 0);
8686 state->setup = NULL;
8687 state->total_param = SVAL(req->vwv+0, 0);
8688 state->param = NULL;
8689 state->total_data = SVAL(req->vwv+1, 0);
8691 state->max_param_return = SVAL(req->vwv+2, 0);
8692 state->max_data_return = SVAL(req->vwv+3, 0);
8693 state->max_setup_return = SVAL(req->vwv+4, 0);
8694 state->close_on_completion = BITSETW(req->vwv+5, 0);
8695 state->one_way = BITSETW(req->vwv+5, 1);
8697 state->call = tran_call;
8699 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8700 is so as a sanity check */
8701 if (state->setup_count != 1) {
8703 * Need to have rc=0 for ioctl to get job id for OS/2.
8704 * Network printing will fail if function is not successful.
8705 * Similar function in reply.c will be used if protocol
8706 * is LANMAN1.0 instead of LM1.2X002.
8707 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8708 * outbuf doesn't have to be set(only job id is used).
8710 if ( (state->setup_count == 4)
8711 && (tran_call == TRANSACT2_IOCTL)
8712 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8713 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8714 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8716 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8717 DEBUG(2,("Transaction is %d\n",tran_call));
8719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8720 END_PROFILE(SMBtrans2);
8725 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8728 if (state->total_data) {
8730 if (trans_oob(state->total_data, 0, dscnt)
8731 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8735 /* Can't use talloc here, the core routines do realloc on the
8736 * params and data. */
8737 state->data = (char *)SMB_MALLOC(state->total_data);
8738 if (state->data == NULL) {
8739 DEBUG(0,("reply_trans2: data malloc fail for %u "
8740 "bytes !\n", (unsigned int)state->total_data));
8742 reply_nterror(req, NT_STATUS_NO_MEMORY);
8743 END_PROFILE(SMBtrans2);
8747 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8750 if (state->total_param) {
8752 if (trans_oob(state->total_param, 0, pscnt)
8753 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8757 /* Can't use talloc here, the core routines do realloc on the
8758 * params and data. */
8759 state->param = (char *)SMB_MALLOC(state->total_param);
8760 if (state->param == NULL) {
8761 DEBUG(0,("reply_trans: param malloc fail for %u "
8762 "bytes !\n", (unsigned int)state->total_param));
8763 SAFE_FREE(state->data);
8765 reply_nterror(req, NT_STATUS_NO_MEMORY);
8766 END_PROFILE(SMBtrans2);
8770 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8773 state->received_data = dscnt;
8774 state->received_param = pscnt;
8776 if ((state->received_param == state->total_param) &&
8777 (state->received_data == state->total_data)) {
8779 handle_trans2(conn, req, state);
8781 SAFE_FREE(state->data);
8782 SAFE_FREE(state->param);
8784 END_PROFILE(SMBtrans2);
8788 DLIST_ADD(conn->pending_trans, state);
8790 /* We need to send an interim response then receive the rest
8791 of the parameter/data bytes */
8792 reply_outbuf(req, 0, 0);
8793 show_msg((char *)req->outbuf);
8794 END_PROFILE(SMBtrans2);
8799 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8800 SAFE_FREE(state->data);
8801 SAFE_FREE(state->param);
8803 END_PROFILE(SMBtrans2);
8804 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8808 /****************************************************************************
8809 Reply to a SMBtranss2
8810 ****************************************************************************/
8812 void reply_transs2(struct smb_request *req)
8814 connection_struct *conn = req->conn;
8815 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8816 struct trans_state *state;
8818 START_PROFILE(SMBtranss2);
8820 show_msg((const char *)req->inbuf);
8823 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8824 END_PROFILE(SMBtranss2);
8828 for (state = conn->pending_trans; state != NULL;
8829 state = state->next) {
8830 if (state->mid == req->mid) {
8835 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8836 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8837 END_PROFILE(SMBtranss2);
8841 /* Revise state->total_param and state->total_data in case they have
8842 changed downwards */
8844 if (SVAL(req->vwv+0, 0) < state->total_param)
8845 state->total_param = SVAL(req->vwv+0, 0);
8846 if (SVAL(req->vwv+1, 0) < state->total_data)
8847 state->total_data = SVAL(req->vwv+1, 0);
8849 pcnt = SVAL(req->vwv+2, 0);
8850 poff = SVAL(req->vwv+3, 0);
8851 pdisp = SVAL(req->vwv+4, 0);
8853 dcnt = SVAL(req->vwv+5, 0);
8854 doff = SVAL(req->vwv+6, 0);
8855 ddisp = SVAL(req->vwv+7, 0);
8857 state->received_param += pcnt;
8858 state->received_data += dcnt;
8860 if ((state->received_data > state->total_data) ||
8861 (state->received_param > state->total_param))
8865 if (trans_oob(state->total_param, pdisp, pcnt)
8866 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8869 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8873 if (trans_oob(state->total_data, ddisp, dcnt)
8874 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8877 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8880 if ((state->received_param < state->total_param) ||
8881 (state->received_data < state->total_data)) {
8882 END_PROFILE(SMBtranss2);
8886 handle_trans2(conn, req, state);
8888 DLIST_REMOVE(conn->pending_trans, state);
8889 SAFE_FREE(state->data);
8890 SAFE_FREE(state->param);
8893 END_PROFILE(SMBtranss2);
8898 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8899 DLIST_REMOVE(conn->pending_trans, state);
8900 SAFE_FREE(state->data);
8901 SAFE_FREE(state->param);
8903 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8904 END_PROFILE(SMBtranss2);