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(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_ARRAY(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_ARRAY(
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_ARRAY(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_P(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_P(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_P(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, deny_mode, open_ofun,
1086 &access_mask, &share_mode,
1087 &create_disposition,
1090 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1094 /* Any data in this call is an EA list. */
1095 if (total_data && (total_data != 4)) {
1096 if (total_data < 10) {
1097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1101 if (IVAL(pdata,0) > total_data) {
1102 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1103 IVAL(pdata,0), (unsigned int)total_data));
1104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1108 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1115 if (!lp_ea_support(SNUM(conn))) {
1116 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1121 status = SMB_VFS_CREATE_FILE(
1124 0, /* root_dir_fid */
1125 smb_fname, /* fname */
1126 access_mask, /* access_mask */
1127 share_mode, /* share_access */
1128 create_disposition, /* create_disposition*/
1129 create_options, /* create_options */
1130 open_attr, /* file_attributes */
1131 oplock_request, /* oplock_request */
1132 open_size, /* allocation_size */
1135 ea_list, /* ea_list */
1137 &smb_action); /* psbuf */
1139 if (!NT_STATUS_IS_OK(status)) {
1140 if (open_was_deferred(req->mid)) {
1141 /* We have re-scheduled this call. */
1144 reply_openerror(req, status);
1148 size = get_file_size_stat(&smb_fname->st);
1149 fattr = dos_mode(conn, smb_fname);
1150 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1151 inode = smb_fname->st.st_ex_ino;
1152 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1153 close_file(req, fsp, ERROR_CLOSE);
1154 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1158 /* Realloc the size of parameters and data we will return */
1159 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1160 if(*pparams == NULL ) {
1161 reply_nterror(req, NT_STATUS_NO_MEMORY);
1166 SSVAL(params,0,fsp->fnum);
1167 SSVAL(params,2,fattr);
1168 srv_put_dos_date2(params,4, mtime);
1169 SIVAL(params,8, (uint32)size);
1170 SSVAL(params,12,deny_mode);
1171 SSVAL(params,14,0); /* open_type - file or directory. */
1172 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1174 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1175 smb_action |= EXTENDED_OPLOCK_GRANTED;
1178 SSVAL(params,18,smb_action);
1181 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1183 SIVAL(params,20,inode);
1184 SSVAL(params,24,0); /* Padding. */
1186 uint32 ea_size = estimate_ea_size(conn, fsp,
1187 fsp->fsp_name->base_name);
1188 SIVAL(params, 26, ea_size);
1190 SIVAL(params, 26, 0);
1193 /* Send the required number of replies */
1194 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1196 TALLOC_FREE(smb_fname);
1199 /*********************************************************
1200 Routine to check if a given string matches exactly.
1201 as a special case a mask of "." does NOT match. That
1202 is required for correct wildcard semantics
1203 Case can be significant or not.
1204 **********************************************************/
1206 static bool exact_match(bool has_wild,
1207 bool case_sensitive,
1211 if (mask[0] == '.' && mask[1] == 0) {
1219 if (case_sensitive) {
1220 return strcmp(str,mask)==0;
1222 return StrCaseCmp(str,mask) == 0;
1226 /****************************************************************************
1227 Return the filetype for UNIX extensions.
1228 ****************************************************************************/
1230 static uint32 unix_filetype(mode_t mode)
1233 return UNIX_TYPE_FILE;
1234 else if(S_ISDIR(mode))
1235 return UNIX_TYPE_DIR;
1237 else if(S_ISLNK(mode))
1238 return UNIX_TYPE_SYMLINK;
1241 else if(S_ISCHR(mode))
1242 return UNIX_TYPE_CHARDEV;
1245 else if(S_ISBLK(mode))
1246 return UNIX_TYPE_BLKDEV;
1249 else if(S_ISFIFO(mode))
1250 return UNIX_TYPE_FIFO;
1253 else if(S_ISSOCK(mode))
1254 return UNIX_TYPE_SOCKET;
1257 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1258 return UNIX_TYPE_UNKNOWN;
1261 /****************************************************************************
1262 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1263 ****************************************************************************/
1265 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1267 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1268 const SMB_STRUCT_STAT *psbuf,
1270 enum perm_type ptype,
1275 if (perms == SMB_MODE_NO_CHANGE) {
1276 if (!VALID_STAT(*psbuf)) {
1277 return NT_STATUS_INVALID_PARAMETER;
1279 *ret_perms = psbuf->st_ex_mode;
1280 return NT_STATUS_OK;
1284 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1285 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1286 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1287 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1288 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1289 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1290 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1291 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1292 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1294 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1297 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1300 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1305 /* Apply mode mask */
1306 ret &= lp_create_mask(SNUM(conn));
1307 /* Add in force bits */
1308 ret |= lp_force_create_mode(SNUM(conn));
1311 ret &= lp_dir_mask(SNUM(conn));
1312 /* Add in force bits */
1313 ret |= lp_force_dir_mode(SNUM(conn));
1315 case PERM_EXISTING_FILE:
1316 /* Apply mode mask */
1317 ret &= lp_security_mask(SNUM(conn));
1318 /* Add in force bits */
1319 ret |= lp_force_security_mode(SNUM(conn));
1321 case PERM_EXISTING_DIR:
1322 /* Apply mode mask */
1323 ret &= lp_dir_security_mask(SNUM(conn));
1324 /* Add in force bits */
1325 ret |= lp_force_dir_security_mode(SNUM(conn));
1330 return NT_STATUS_OK;
1333 /****************************************************************************
1334 Needed to show the msdfs symlinks as directories. Modifies psbuf
1335 to be a directory if it's a msdfs link.
1336 ****************************************************************************/
1338 static bool check_msdfs_link(connection_struct *conn,
1339 const char *pathname,
1340 SMB_STRUCT_STAT *psbuf)
1342 int saved_errno = errno;
1343 if(lp_host_msdfs() &&
1344 lp_msdfs_root(SNUM(conn)) &&
1345 is_msdfs_link(conn, pathname, psbuf)) {
1347 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1350 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1351 errno = saved_errno;
1354 errno = saved_errno;
1359 /****************************************************************************
1360 Get a level dependent lanman2 dir entry.
1361 ****************************************************************************/
1363 struct smbd_dirptr_lanman2_state {
1364 connection_struct *conn;
1365 uint32_t info_level;
1366 bool check_mangled_names;
1368 bool got_exact_match;
1371 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1377 struct smbd_dirptr_lanman2_state *state =
1378 (struct smbd_dirptr_lanman2_state *)private_data;
1380 char mangled_name[13]; /* mangled 8.3 name. */
1384 /* Mangle fname if it's an illegal name. */
1385 if (mangle_must_mangle(dname, state->conn->params)) {
1386 ok = name_to_8_3(dname, mangled_name,
1387 true, state->conn->params);
1391 fname = mangled_name;
1396 got_match = exact_match(state->has_wild,
1397 state->conn->case_sensitive,
1399 state->got_exact_match = got_match;
1401 got_match = mask_match(fname, mask,
1402 state->conn->case_sensitive);
1405 if(!got_match && state->check_mangled_names &&
1406 !mangle_is_8_3(fname, false, state->conn->params)) {
1408 * It turns out that NT matches wildcards against
1409 * both long *and* short names. This may explain some
1410 * of the wildcard wierdness from old DOS clients
1411 * that some people have been seeing.... JRA.
1413 /* Force the mangling into 8.3. */
1414 ok = name_to_8_3(fname, mangled_name,
1415 false, state->conn->params);
1420 got_match = exact_match(state->has_wild,
1421 state->conn->case_sensitive,
1422 mangled_name, mask);
1423 state->got_exact_match = got_match;
1425 got_match = mask_match(mangled_name, mask,
1426 state->conn->case_sensitive);
1434 *_fname = talloc_strdup(ctx, fname);
1435 if (*_fname == NULL) {
1442 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1444 struct smb_filename *smb_fname,
1447 struct smbd_dirptr_lanman2_state *state =
1448 (struct smbd_dirptr_lanman2_state *)private_data;
1449 bool ms_dfs_link = false;
1452 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1453 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1454 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1455 "Couldn't lstat [%s] (%s)\n",
1456 smb_fname_str_dbg(smb_fname),
1460 } else if (!VALID_STAT(smb_fname->st) &&
1461 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1462 /* Needed to show the msdfs symlinks as
1465 ms_dfs_link = check_msdfs_link(state->conn,
1466 smb_fname->base_name,
1469 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1470 "Couldn't stat [%s] (%s)\n",
1471 smb_fname_str_dbg(smb_fname),
1478 mode = dos_mode_msdfs(state->conn, smb_fname);
1480 mode = dos_mode(state->conn, smb_fname);
1487 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1488 connection_struct *conn,
1490 uint32_t info_level,
1491 struct ea_list *name_list,
1492 bool check_mangled_names,
1493 bool requires_resume_key,
1496 const struct smb_filename *smb_fname,
1497 int space_remaining,
1504 uint64_t *last_entry_off)
1506 char *p, *q, *pdata = *ppdata;
1508 uint64_t file_size = 0;
1509 uint64_t allocation_size = 0;
1510 uint64_t file_index = 0;
1512 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1513 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1514 time_t c_date = (time_t)0;
1516 char *last_entry_ptr;
1521 *out_of_space = false;
1523 ZERO_STRUCT(mdate_ts);
1524 ZERO_STRUCT(adate_ts);
1525 ZERO_STRUCT(create_date_ts);
1526 ZERO_STRUCT(cdate_ts);
1528 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1529 file_size = get_file_size_stat(&smb_fname->st);
1531 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1533 file_index = get_FileIndex(conn, &smb_fname->st);
1535 mdate_ts = smb_fname->st.st_ex_mtime;
1536 adate_ts = smb_fname->st.st_ex_atime;
1537 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1538 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1540 if (lp_dos_filetime_resolution(SNUM(conn))) {
1541 dos_filetime_timespec(&create_date_ts);
1542 dos_filetime_timespec(&mdate_ts);
1543 dos_filetime_timespec(&adate_ts);
1544 dos_filetime_timespec(&cdate_ts);
1547 create_date = convert_timespec_to_time_t(create_date_ts);
1548 mdate = convert_timespec_to_time_t(mdate_ts);
1549 adate = convert_timespec_to_time_t(adate_ts);
1550 c_date = convert_timespec_to_time_t(cdate_ts);
1552 /* align the record */
1553 SMB_ASSERT(align >= 1);
1555 off = (int)PTR_DIFF(pdata, base_data);
1556 pad = (off + (align-1)) & ~(align-1);
1559 if (pad && pad > space_remaining) {
1560 *out_of_space = true;
1561 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1562 "for padding (wanted %u, had %d)\n",
1565 return false; /* Not finished - just out of space */
1569 /* initialize padding to 0 */
1571 memset(pdata, 0, pad);
1573 space_remaining -= pad;
1575 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1585 switch (info_level) {
1586 case SMB_FIND_INFO_STANDARD:
1587 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1588 if(requires_resume_key) {
1592 srv_put_dos_date2(p,0,create_date);
1593 srv_put_dos_date2(p,4,adate);
1594 srv_put_dos_date2(p,8,mdate);
1595 SIVAL(p,12,(uint32)file_size);
1596 SIVAL(p,16,(uint32)allocation_size);
1600 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1601 p += ucs2_align(base_data, p, 0);
1603 len = srvstr_push(base_data, flags2, p,
1604 fname, PTR_DIFF(end_data, p),
1606 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1608 SCVAL(nameptr, -1, len - 2);
1610 SCVAL(nameptr, -1, 0);
1614 SCVAL(nameptr, -1, len - 1);
1616 SCVAL(nameptr, -1, 0);
1622 case SMB_FIND_EA_SIZE:
1623 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1624 if (requires_resume_key) {
1628 srv_put_dos_date2(p,0,create_date);
1629 srv_put_dos_date2(p,4,adate);
1630 srv_put_dos_date2(p,8,mdate);
1631 SIVAL(p,12,(uint32)file_size);
1632 SIVAL(p,16,(uint32)allocation_size);
1635 unsigned int ea_size = estimate_ea_size(conn, NULL,
1636 smb_fname->base_name);
1637 SIVAL(p,22,ea_size); /* Extended attributes */
1641 len = srvstr_push(base_data, flags2,
1642 p, fname, PTR_DIFF(end_data, p),
1643 STR_TERMINATE | STR_NOALIGN);
1644 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1657 SCVAL(nameptr,0,len);
1659 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1662 case SMB_FIND_EA_LIST:
1664 struct ea_list *file_list = NULL;
1667 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1671 if (requires_resume_key) {
1675 srv_put_dos_date2(p,0,create_date);
1676 srv_put_dos_date2(p,4,adate);
1677 srv_put_dos_date2(p,8,mdate);
1678 SIVAL(p,12,(uint32)file_size);
1679 SIVAL(p,16,(uint32)allocation_size);
1681 p += 22; /* p now points to the EA area. */
1683 file_list = get_ea_list_from_file(ctx, conn, NULL,
1684 smb_fname->base_name,
1686 name_list = ea_list_union(name_list, file_list, &ea_len);
1688 /* We need to determine if this entry will fit in the space available. */
1689 /* Max string size is 255 bytes. */
1690 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1691 *out_of_space = true;
1692 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1693 "(wanted %u, had %d)\n",
1694 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1696 return False; /* Not finished - just out of space */
1699 /* Push the ea_data followed by the name. */
1700 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1702 len = srvstr_push(base_data, flags2,
1703 p + 1, fname, PTR_DIFF(end_data, p+1),
1704 STR_TERMINATE | STR_NOALIGN);
1705 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1718 SCVAL(nameptr,0,len);
1720 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1724 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1725 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1726 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1728 SIVAL(p,0,reskey); p += 4;
1729 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1730 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1731 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1732 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1733 SOFF_T(p,0,file_size); p += 8;
1734 SOFF_T(p,0,allocation_size); p += 8;
1735 SIVAL(p,0,mode); p += 4;
1736 q = p; p += 4; /* q is placeholder for name length. */
1738 unsigned int ea_size = estimate_ea_size(conn, NULL,
1739 smb_fname->base_name);
1740 SIVAL(p,0,ea_size); /* Extended attributes */
1743 /* Clear the short name buffer. This is
1744 * IMPORTANT as not doing so will trigger
1745 * a Win2k client bug. JRA.
1747 if (!was_8_3 && check_mangled_names) {
1748 char mangled_name[13]; /* mangled 8.3 name. */
1749 if (!name_to_8_3(fname,mangled_name,True,
1751 /* Error - mangle failed ! */
1752 memset(mangled_name,'\0',12);
1754 mangled_name[12] = 0;
1755 len = srvstr_push(base_data, flags2,
1756 p+2, mangled_name, 24,
1757 STR_UPPER|STR_UNICODE);
1759 memset(p + 2 + len,'\0',24 - len);
1766 len = srvstr_push(base_data, flags2, p,
1767 fname, PTR_DIFF(end_data, p),
1768 STR_TERMINATE_ASCII);
1772 len = PTR_DIFF(p, pdata);
1773 pad = (len + (align-1)) & ~(align-1);
1775 * offset to the next entry, the caller
1776 * will overwrite it for the last entry
1777 * that's why we always include the padding
1781 * set padding to zero
1784 memset(p, 0, pad - len);
1791 case SMB_FIND_FILE_DIRECTORY_INFO:
1792 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1794 SIVAL(p,0,reskey); p += 4;
1795 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1796 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1797 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1798 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1799 SOFF_T(p,0,file_size); p += 8;
1800 SOFF_T(p,0,allocation_size); p += 8;
1801 SIVAL(p,0,mode); p += 4;
1802 len = srvstr_push(base_data, flags2,
1803 p + 4, fname, PTR_DIFF(end_data, p+4),
1804 STR_TERMINATE_ASCII);
1808 len = PTR_DIFF(p, pdata);
1809 pad = (len + (align-1)) & ~(align-1);
1811 * offset to the next entry, the caller
1812 * will overwrite it for the last entry
1813 * that's why we always include the padding
1817 * set padding to zero
1820 memset(p, 0, pad - len);
1827 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1828 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1830 SIVAL(p,0,reskey); p += 4;
1831 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1832 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1833 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1834 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1835 SOFF_T(p,0,file_size); p += 8;
1836 SOFF_T(p,0,allocation_size); p += 8;
1837 SIVAL(p,0,mode); p += 4;
1838 q = p; p += 4; /* q is placeholder for name length. */
1840 unsigned int ea_size = estimate_ea_size(conn, NULL,
1841 smb_fname->base_name);
1842 SIVAL(p,0,ea_size); /* Extended attributes */
1845 len = srvstr_push(base_data, flags2, p,
1846 fname, PTR_DIFF(end_data, p),
1847 STR_TERMINATE_ASCII);
1851 len = PTR_DIFF(p, pdata);
1852 pad = (len + (align-1)) & ~(align-1);
1854 * offset to the next entry, the caller
1855 * will overwrite it for the last entry
1856 * that's why we always include the padding
1860 * set padding to zero
1863 memset(p, 0, pad - len);
1870 case SMB_FIND_FILE_NAMES_INFO:
1871 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1873 SIVAL(p,0,reskey); p += 4;
1875 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1876 acl on a dir (tridge) */
1877 len = srvstr_push(base_data, flags2, p,
1878 fname, PTR_DIFF(end_data, p),
1879 STR_TERMINATE_ASCII);
1883 len = PTR_DIFF(p, pdata);
1884 pad = (len + (align-1)) & ~(align-1);
1886 * offset to the next entry, the caller
1887 * will overwrite it for the last entry
1888 * that's why we always include the padding
1892 * set padding to zero
1895 memset(p, 0, pad - len);
1902 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1903 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1905 SIVAL(p,0,reskey); p += 4;
1906 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1907 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1910 SOFF_T(p,0,file_size); p += 8;
1911 SOFF_T(p,0,allocation_size); p += 8;
1912 SIVAL(p,0,mode); p += 4;
1913 q = p; p += 4; /* q is placeholder for name length. */
1915 unsigned int ea_size = estimate_ea_size(conn, NULL,
1916 smb_fname->base_name);
1917 SIVAL(p,0,ea_size); /* Extended attributes */
1920 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1921 SBVAL(p,0,file_index); p += 8;
1922 len = srvstr_push(base_data, flags2, p,
1923 fname, PTR_DIFF(end_data, p),
1924 STR_TERMINATE_ASCII);
1928 len = PTR_DIFF(p, pdata);
1929 pad = (len + (align-1)) & ~(align-1);
1931 * offset to the next entry, the caller
1932 * will overwrite it for the last entry
1933 * that's why we always include the padding
1937 * set padding to zero
1940 memset(p, 0, pad - len);
1947 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1948 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1949 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1951 SIVAL(p,0,reskey); p += 4;
1952 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1953 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1954 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1955 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1956 SOFF_T(p,0,file_size); p += 8;
1957 SOFF_T(p,0,allocation_size); p += 8;
1958 SIVAL(p,0,mode); p += 4;
1959 q = p; p += 4; /* q is placeholder for name length */
1961 unsigned int ea_size = estimate_ea_size(conn, NULL,
1962 smb_fname->base_name);
1963 SIVAL(p,0,ea_size); /* Extended attributes */
1966 /* Clear the short name buffer. This is
1967 * IMPORTANT as not doing so will trigger
1968 * a Win2k client bug. JRA.
1970 if (!was_8_3 && check_mangled_names) {
1971 char mangled_name[13]; /* mangled 8.3 name. */
1972 if (!name_to_8_3(fname,mangled_name,True,
1974 /* Error - mangle failed ! */
1975 memset(mangled_name,'\0',12);
1977 mangled_name[12] = 0;
1978 len = srvstr_push(base_data, flags2,
1979 p+2, mangled_name, 24,
1980 STR_UPPER|STR_UNICODE);
1983 memset(p + 2 + len,'\0',24 - len);
1990 SSVAL(p,0,0); p += 2; /* Reserved ? */
1991 SBVAL(p,0,file_index); p += 8;
1992 len = srvstr_push(base_data, flags2, p,
1993 fname, PTR_DIFF(end_data, p),
1994 STR_TERMINATE_ASCII);
1998 len = PTR_DIFF(p, pdata);
1999 pad = (len + (align-1)) & ~(align-1);
2001 * offset to the next entry, the caller
2002 * will overwrite it for the last entry
2003 * that's why we always include the padding
2007 * set padding to zero
2010 memset(p, 0, pad - len);
2017 /* CIFS UNIX Extension. */
2019 case SMB_FIND_FILE_UNIX:
2020 case SMB_FIND_FILE_UNIX_INFO2:
2022 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2024 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2026 if (info_level == SMB_FIND_FILE_UNIX) {
2027 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2028 p = store_file_unix_basic(conn, p,
2029 NULL, &smb_fname->st);
2030 len = srvstr_push(base_data, flags2, p,
2031 fname, PTR_DIFF(end_data, p),
2034 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2035 p = store_file_unix_basic_info2(conn, p,
2036 NULL, &smb_fname->st);
2039 len = srvstr_push(base_data, flags2, p, fname,
2040 PTR_DIFF(end_data, p), 0);
2041 SIVAL(nameptr, 0, len);
2046 len = PTR_DIFF(p, pdata);
2047 pad = (len + (align-1)) & ~(align-1);
2049 * offset to the next entry, the caller
2050 * will overwrite it for the last entry
2051 * that's why we always include the padding
2055 * set padding to zero
2058 memset(p, 0, pad - len);
2063 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2071 if (PTR_DIFF(p,pdata) > space_remaining) {
2072 *out_of_space = true;
2073 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2074 "(wanted %u, had %d)\n",
2075 (unsigned int)PTR_DIFF(p,pdata),
2077 return false; /* Not finished - just out of space */
2080 /* Setup the last entry pointer, as an offset from base_data */
2081 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2082 /* Advance the data pointer to the next slot */
2088 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2089 connection_struct *conn,
2090 struct dptr_struct *dirptr,
2092 const char *path_mask,
2095 int requires_resume_key,
2103 int space_remaining,
2105 bool *got_exact_match,
2106 int *_last_entry_off,
2107 struct ea_list *name_list)
2110 const char *mask = NULL;
2111 long prev_dirpos = 0;
2114 struct smb_filename *smb_fname = NULL;
2115 struct smbd_dirptr_lanman2_state state;
2117 uint64_t last_entry_off = 0;
2121 state.info_level = info_level;
2122 state.check_mangled_names = lp_manglednames(conn->params);
2123 state.has_wild = dptr_has_wild(dirptr);
2124 state.got_exact_match = false;
2126 *out_of_space = false;
2127 *got_exact_match = false;
2129 p = strrchr_m(path_mask,'/');
2140 ok = smbd_dirptr_get_entry(ctx,
2146 smbd_dirptr_lanman2_match_fn,
2147 smbd_dirptr_lanman2_mode_fn,
2157 *got_exact_match = state.got_exact_match;
2159 ok = smbd_marshall_dir_entry(ctx,
2164 state.check_mangled_names,
2165 requires_resume_key,
2178 TALLOC_FREE(smb_fname);
2179 if (*out_of_space) {
2180 dptr_SeekDir(dirptr, prev_dirpos);
2187 *_last_entry_off = last_entry_off;
2191 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2192 connection_struct *conn,
2193 struct dptr_struct *dirptr,
2195 const char *path_mask,
2198 bool requires_resume_key,
2204 int space_remaining,
2206 bool *got_exact_match,
2207 int *last_entry_off,
2208 struct ea_list *name_list)
2211 const bool do_pad = true;
2213 if (info_level >= 1 && info_level <= 3) {
2214 /* No alignment on earlier info levels. */
2218 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2219 path_mask, dirtype, info_level,
2220 requires_resume_key, dont_descend, ask_sharemode,
2222 ppdata, base_data, end_data,
2224 out_of_space, got_exact_match,
2225 last_entry_off, name_list);
2228 /****************************************************************************
2229 Reply to a TRANS2_FINDFIRST.
2230 ****************************************************************************/
2232 static void call_trans2findfirst(connection_struct *conn,
2233 struct smb_request *req,
2234 char **pparams, int total_params,
2235 char **ppdata, int total_data,
2236 unsigned int max_data_bytes)
2238 /* We must be careful here that we don't return more than the
2239 allowed number of data bytes. If this means returning fewer than
2240 maxentries then so be it. We assume that the redirector has
2241 enough room for the fixed number of parameter bytes it has
2243 struct smb_filename *smb_dname = NULL;
2244 char *params = *pparams;
2245 char *pdata = *ppdata;
2249 uint16 findfirst_flags;
2250 bool close_after_first;
2252 bool requires_resume_key;
2254 char *directory = NULL;
2257 int last_entry_off=0;
2261 bool finished = False;
2262 bool dont_descend = False;
2263 bool out_of_space = False;
2264 int space_remaining;
2265 bool mask_contains_wcard = False;
2266 struct ea_list *ea_list = NULL;
2267 NTSTATUS ntstatus = NT_STATUS_OK;
2268 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2269 TALLOC_CTX *ctx = talloc_tos();
2270 struct dptr_struct *dirptr = NULL;
2271 struct smbd_server_connection *sconn = req->sconn;
2273 if (total_params < 13) {
2274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2278 dirtype = SVAL(params,0);
2279 maxentries = SVAL(params,2);
2280 findfirst_flags = SVAL(params,4);
2281 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2282 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2283 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2284 info_level = SVAL(params,6);
2286 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2287 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2288 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2289 info_level, max_data_bytes));
2292 /* W2K3 seems to treat zero as 1. */
2296 switch (info_level) {
2297 case SMB_FIND_INFO_STANDARD:
2298 case SMB_FIND_EA_SIZE:
2299 case SMB_FIND_EA_LIST:
2300 case SMB_FIND_FILE_DIRECTORY_INFO:
2301 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2302 case SMB_FIND_FILE_NAMES_INFO:
2303 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2304 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2305 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2307 case SMB_FIND_FILE_UNIX:
2308 case SMB_FIND_FILE_UNIX_INFO2:
2309 /* Always use filesystem for UNIX mtime query. */
2310 ask_sharemode = false;
2311 if (!lp_unix_extensions()) {
2312 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2317 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2321 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2322 params+12, total_params - 12,
2323 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2324 if (!NT_STATUS_IS_OK(ntstatus)) {
2325 reply_nterror(req, ntstatus);
2329 ntstatus = filename_convert(ctx, conn,
2330 req->flags2 & FLAGS2_DFS_PATHNAMES,
2333 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2334 &mask_contains_wcard,
2336 if (!NT_STATUS_IS_OK(ntstatus)) {
2337 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2338 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2339 ERRSRV, ERRbadpath);
2342 reply_nterror(req, ntstatus);
2346 mask = smb_dname->original_lcomp;
2348 directory = smb_dname->base_name;
2350 p = strrchr_m(directory,'/');
2352 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2353 if((directory[0] == '.') && (directory[1] == '\0')) {
2354 mask = talloc_strdup(ctx,"*");
2356 reply_nterror(req, NT_STATUS_NO_MEMORY);
2359 mask_contains_wcard = True;
2365 if (p == NULL || p == directory) {
2366 /* Ensure we don't have a directory name of "". */
2367 directory = talloc_strdup(talloc_tos(), ".");
2369 reply_nterror(req, NT_STATUS_NO_MEMORY);
2374 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2376 if (info_level == SMB_FIND_EA_LIST) {
2379 if (total_data < 4) {
2380 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2384 ea_size = IVAL(pdata,0);
2385 if (ea_size != total_data) {
2386 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2387 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2392 if (!lp_ea_support(SNUM(conn))) {
2393 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2397 /* Pull out the list of names. */
2398 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2405 *ppdata = (char *)SMB_REALLOC(
2406 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2407 if(*ppdata == NULL ) {
2408 reply_nterror(req, NT_STATUS_NO_MEMORY);
2412 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2414 /* Realloc the params space */
2415 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2416 if (*pparams == NULL) {
2417 reply_nterror(req, NT_STATUS_NO_MEMORY);
2422 /* Save the wildcard match and attribs we are using on this directory -
2423 needed as lanman2 assumes these are being saved between calls */
2425 ntstatus = dptr_create(conn,
2432 mask_contains_wcard,
2436 if (!NT_STATUS_IS_OK(ntstatus)) {
2437 reply_nterror(req, ntstatus);
2441 dptr_num = dptr_dnum(dirptr);
2442 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2444 /* Initialize per TRANS2_FIND_FIRST operation data */
2445 dptr_init_search_op(dirptr);
2447 /* We don't need to check for VOL here as this is returned by
2448 a different TRANS2 call. */
2450 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2451 directory,lp_dontdescend(SNUM(conn))));
2452 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2453 dont_descend = True;
2456 space_remaining = max_data_bytes;
2457 out_of_space = False;
2459 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2460 bool got_exact_match = False;
2462 /* this is a heuristic to avoid seeking the dirptr except when
2463 absolutely necessary. It allows for a filename of about 40 chars */
2464 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2465 out_of_space = True;
2468 finished = !get_lanman2_dir_entry(ctx,
2472 mask,dirtype,info_level,
2473 requires_resume_key,dont_descend,
2476 space_remaining, &out_of_space,
2478 &last_entry_off, ea_list);
2481 if (finished && out_of_space)
2484 if (!finished && !out_of_space)
2488 * As an optimisation if we know we aren't looking
2489 * for a wildcard name (ie. the name matches the wildcard exactly)
2490 * then we can finish on any (first) match.
2491 * This speeds up large directory searches. JRA.
2497 /* Ensure space_remaining never goes -ve. */
2498 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2499 space_remaining = 0;
2500 out_of_space = true;
2502 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2506 /* Check if we can close the dirptr */
2507 if(close_after_first || (finished && close_if_end)) {
2508 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2509 dptr_close(sconn, &dptr_num);
2513 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2514 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2515 * the protocol level is less than NT1. Tested with smbclient. JRA.
2516 * This should fix the OS/2 client bug #2335.
2519 if(numentries == 0) {
2520 dptr_close(sconn, &dptr_num);
2521 if (get_Protocol() < PROTOCOL_NT1) {
2522 reply_force_doserror(req, ERRDOS, ERRnofiles);
2525 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2526 ERRDOS, ERRbadfile);
2531 /* At this point pdata points to numentries directory entries. */
2533 /* Set up the return parameter block */
2534 SSVAL(params,0,dptr_num);
2535 SSVAL(params,2,numentries);
2536 SSVAL(params,4,finished);
2537 SSVAL(params,6,0); /* Never an EA error */
2538 SSVAL(params,8,last_entry_off);
2540 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2543 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2544 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2546 reply_nterror(req, NT_STATUS_NO_MEMORY);
2550 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2551 smb_fn_name(req->cmd),
2552 mask, directory, dirtype, numentries ) );
2555 * Force a name mangle here to ensure that the
2556 * mask as an 8.3 name is top of the mangled cache.
2557 * The reasons for this are subtle. Don't remove
2558 * this code unless you know what you are doing
2559 * (see PR#13758). JRA.
2562 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2563 char mangled_name[13];
2564 name_to_8_3(mask, mangled_name, True, conn->params);
2567 TALLOC_FREE(smb_dname);
2571 /****************************************************************************
2572 Reply to a TRANS2_FINDNEXT.
2573 ****************************************************************************/
2575 static void call_trans2findnext(connection_struct *conn,
2576 struct smb_request *req,
2577 char **pparams, int total_params,
2578 char **ppdata, int total_data,
2579 unsigned int max_data_bytes)
2581 /* We must be careful here that we don't return more than the
2582 allowed number of data bytes. If this means returning fewer than
2583 maxentries then so be it. We assume that the redirector has
2584 enough room for the fixed number of parameter bytes it has
2586 char *params = *pparams;
2587 char *pdata = *ppdata;
2593 uint16 findnext_flags;
2594 bool close_after_request;
2596 bool requires_resume_key;
2598 bool mask_contains_wcard = False;
2599 char *resume_name = NULL;
2600 const char *mask = NULL;
2601 const char *directory = NULL;
2605 int i, last_entry_off=0;
2606 bool finished = False;
2607 bool dont_descend = False;
2608 bool out_of_space = False;
2609 int space_remaining;
2610 struct ea_list *ea_list = NULL;
2611 NTSTATUS ntstatus = NT_STATUS_OK;
2612 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2613 TALLOC_CTX *ctx = talloc_tos();
2614 struct dptr_struct *dirptr;
2615 struct smbd_server_connection *sconn = req->sconn;
2617 if (total_params < 13) {
2618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2622 dptr_num = SVAL(params,0);
2623 maxentries = SVAL(params,2);
2624 info_level = SVAL(params,4);
2625 resume_key = IVAL(params,6);
2626 findnext_flags = SVAL(params,10);
2627 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2628 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2629 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2630 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2632 if (!continue_bit) {
2633 /* We only need resume_name if continue_bit is zero. */
2634 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2636 total_params - 12, STR_TERMINATE, &ntstatus,
2637 &mask_contains_wcard);
2638 if (!NT_STATUS_IS_OK(ntstatus)) {
2639 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2640 complain (it thinks we're asking for the directory above the shared
2641 path or an invalid name). Catch this as the resume name is only compared, never used in
2642 a file access. JRA. */
2643 srvstr_pull_talloc(ctx, params, req->flags2,
2644 &resume_name, params+12,
2648 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2649 reply_nterror(req, ntstatus);
2655 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2656 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2657 resume_key = %d resume name = %s continue=%d level = %d\n",
2658 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2659 requires_resume_key, resume_key,
2660 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2663 /* W2K3 seems to treat zero as 1. */
2667 switch (info_level) {
2668 case SMB_FIND_INFO_STANDARD:
2669 case SMB_FIND_EA_SIZE:
2670 case SMB_FIND_EA_LIST:
2671 case SMB_FIND_FILE_DIRECTORY_INFO:
2672 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2673 case SMB_FIND_FILE_NAMES_INFO:
2674 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2675 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2676 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2678 case SMB_FIND_FILE_UNIX:
2679 case SMB_FIND_FILE_UNIX_INFO2:
2680 /* Always use filesystem for UNIX mtime query. */
2681 ask_sharemode = false;
2682 if (!lp_unix_extensions()) {
2683 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2688 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2692 if (info_level == SMB_FIND_EA_LIST) {
2695 if (total_data < 4) {
2696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2700 ea_size = IVAL(pdata,0);
2701 if (ea_size != total_data) {
2702 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2703 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2708 if (!lp_ea_support(SNUM(conn))) {
2709 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2713 /* Pull out the list of names. */
2714 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2716 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2721 *ppdata = (char *)SMB_REALLOC(
2722 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2723 if(*ppdata == NULL) {
2724 reply_nterror(req, NT_STATUS_NO_MEMORY);
2729 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2731 /* Realloc the params space */
2732 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2733 if(*pparams == NULL ) {
2734 reply_nterror(req, NT_STATUS_NO_MEMORY);
2740 /* Check that the dptr is valid */
2741 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2742 reply_nterror(req, STATUS_NO_MORE_FILES);
2746 directory = dptr_path(sconn, dptr_num);
2748 /* Get the wildcard mask from the dptr */
2749 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2750 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2751 reply_nterror(req, STATUS_NO_MORE_FILES);
2757 /* Get the attr mask from the dptr */
2758 dirtype = dptr_attr(sconn, dptr_num);
2760 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2761 dptr_num, mask, dirtype,
2763 dptr_TellDir(dirptr)));
2765 /* Initialize per TRANS2_FIND_NEXT operation data */
2766 dptr_init_search_op(dirptr);
2768 /* We don't need to check for VOL here as this is returned by
2769 a different TRANS2 call. */
2771 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2772 directory,lp_dontdescend(SNUM(conn))));
2773 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2774 dont_descend = True;
2777 space_remaining = max_data_bytes;
2778 out_of_space = False;
2781 * Seek to the correct position. We no longer use the resume key but
2782 * depend on the last file name instead.
2785 if(!continue_bit && resume_name && *resume_name) {
2788 long current_pos = 0;
2790 * Remember, name_to_8_3 is called by
2791 * get_lanman2_dir_entry(), so the resume name
2792 * could be mangled. Ensure we check the unmangled name.
2795 if (mangle_is_mangled(resume_name, conn->params)) {
2796 char *new_resume_name = NULL;
2797 mangle_lookup_name_from_8_3(ctx,
2801 if (new_resume_name) {
2802 resume_name = new_resume_name;
2807 * Fix for NT redirector problem triggered by resume key indexes
2808 * changing between directory scans. We now return a resume key of 0
2809 * and instead look for the filename to continue from (also given
2810 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2811 * findfirst/findnext (as is usual) then the directory pointer
2812 * should already be at the correct place.
2815 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2816 } /* end if resume_name && !continue_bit */
2818 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2819 bool got_exact_match = False;
2821 /* this is a heuristic to avoid seeking the dirptr except when
2822 absolutely necessary. It allows for a filename of about 40 chars */
2823 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2824 out_of_space = True;
2827 finished = !get_lanman2_dir_entry(ctx,
2831 mask,dirtype,info_level,
2832 requires_resume_key,dont_descend,
2835 space_remaining, &out_of_space,
2837 &last_entry_off, ea_list);
2840 if (finished && out_of_space)
2843 if (!finished && !out_of_space)
2847 * As an optimisation if we know we aren't looking
2848 * for a wildcard name (ie. the name matches the wildcard exactly)
2849 * then we can finish on any (first) match.
2850 * This speeds up large directory searches. JRA.
2856 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2859 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2860 smb_fn_name(req->cmd),
2861 mask, directory, dirtype, numentries ) );
2863 /* Check if we can close the dirptr */
2864 if(close_after_request || (finished && close_if_end)) {
2865 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2866 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2869 /* Set up the return parameter block */
2870 SSVAL(params,0,numentries);
2871 SSVAL(params,2,finished);
2872 SSVAL(params,4,0); /* Never an EA error */
2873 SSVAL(params,6,last_entry_off);
2875 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2881 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2883 E_md4hash(lp_servicename(SNUM(conn)),objid);
2887 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2889 SMB_ASSERT(extended_info != NULL);
2891 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2892 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2893 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2894 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2895 #ifdef SAMBA_VERSION_REVISION
2896 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2898 extended_info->samba_subversion = 0;
2899 #ifdef SAMBA_VERSION_RC_RELEASE
2900 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2902 #ifdef SAMBA_VERSION_PRE_RELEASE
2903 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2906 #ifdef SAMBA_VERSION_VENDOR_PATCH
2907 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2909 extended_info->samba_gitcommitdate = 0;
2910 #ifdef SAMBA_VERSION_COMMIT_TIME
2911 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2914 memset(extended_info->samba_version_string, 0,
2915 sizeof(extended_info->samba_version_string));
2917 snprintf (extended_info->samba_version_string,
2918 sizeof(extended_info->samba_version_string),
2919 "%s", samba_version_string());
2922 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2923 TALLOC_CTX *mem_ctx,
2924 uint16_t info_level,
2926 unsigned int max_data_bytes,
2930 char *pdata, *end_data;
2931 int data_len = 0, len;
2932 const char *vname = volume_label(SNUM(conn));
2933 int snum = SNUM(conn);
2934 char *fstype = lp_fstype(SNUM(conn));
2935 uint32 additional_flags = 0;
2936 struct smb_filename smb_fname_dot;
2940 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2941 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2942 "info level (0x%x) on IPC$.\n",
2943 (unsigned int)info_level));
2944 return NT_STATUS_ACCESS_DENIED;
2948 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2950 ZERO_STRUCT(smb_fname_dot);
2951 smb_fname_dot.base_name = discard_const_p(char, ".");
2953 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2954 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2955 return map_nt_error_from_unix(errno);
2958 st = smb_fname_dot.st;
2960 *ppdata = (char *)SMB_REALLOC(
2961 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2962 if (*ppdata == NULL) {
2963 return NT_STATUS_NO_MEMORY;
2967 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2968 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2970 switch (info_level) {
2971 case SMB_INFO_ALLOCATION:
2973 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2975 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2976 return map_nt_error_from_unix(errno);
2979 block_size = lp_block_size(snum);
2980 if (bsize < block_size) {
2981 uint64_t factor = block_size/bsize;
2986 if (bsize > block_size) {
2987 uint64_t factor = bsize/block_size;
2992 bytes_per_sector = 512;
2993 sectors_per_unit = bsize/bytes_per_sector;
2995 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2996 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2997 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2999 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3000 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3001 SIVAL(pdata,l1_cUnit,dsize);
3002 SIVAL(pdata,l1_cUnitAvail,dfree);
3003 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3007 case SMB_INFO_VOLUME:
3008 /* Return volume name */
3010 * Add volume serial number - hash of a combination of
3011 * the called hostname and the service name.
3013 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3015 * Win2k3 and previous mess this up by sending a name length
3016 * one byte short. I believe only older clients (OS/2 Win9x) use
3017 * this call so try fixing this by adding a terminating null to
3018 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3022 pdata+l2_vol_szVolLabel, vname,
3023 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3024 STR_NOALIGN|STR_TERMINATE);
3025 SCVAL(pdata,l2_vol_cch,len);
3026 data_len = l2_vol_szVolLabel + len;
3027 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3028 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3032 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3033 case SMB_FS_ATTRIBUTE_INFORMATION:
3035 additional_flags = 0;
3036 #if defined(HAVE_SYS_QUOTAS)
3037 additional_flags |= FILE_VOLUME_QUOTAS;
3040 if(lp_nt_acl_support(SNUM(conn))) {
3041 additional_flags |= FILE_PERSISTENT_ACLS;
3044 /* Capabilities are filled in at connection time through STATVFS call */
3045 additional_flags |= conn->fs_capabilities;
3046 additional_flags |= lp_parm_int(conn->params->service,
3047 "share", "fake_fscaps",
3050 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3051 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3052 additional_flags); /* FS ATTRIBUTES */
3054 SIVAL(pdata,4,255); /* Max filename component length */
3055 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3056 and will think we can't do long filenames */
3057 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3058 PTR_DIFF(end_data, pdata+12),
3061 data_len = 12 + len;
3064 case SMB_QUERY_FS_LABEL_INFO:
3065 case SMB_FS_LABEL_INFORMATION:
3066 len = srvstr_push(pdata, flags2, pdata+4, vname,
3067 PTR_DIFF(end_data, pdata+4), 0);
3072 case SMB_QUERY_FS_VOLUME_INFO:
3073 case SMB_FS_VOLUME_INFORMATION:
3076 * Add volume serial number - hash of a combination of
3077 * the called hostname and the service name.
3079 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3080 (str_checksum(get_local_machine_name())<<16));
3082 /* Max label len is 32 characters. */
3083 len = srvstr_push(pdata, flags2, pdata+18, vname,
3084 PTR_DIFF(end_data, pdata+18),
3086 SIVAL(pdata,12,len);
3089 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3090 (int)strlen(vname),vname, lp_servicename(snum)));
3093 case SMB_QUERY_FS_SIZE_INFO:
3094 case SMB_FS_SIZE_INFORMATION:
3096 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3098 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3099 return map_nt_error_from_unix(errno);
3101 block_size = lp_block_size(snum);
3102 if (bsize < block_size) {
3103 uint64_t factor = block_size/bsize;
3108 if (bsize > block_size) {
3109 uint64_t factor = bsize/block_size;
3114 bytes_per_sector = 512;
3115 sectors_per_unit = bsize/bytes_per_sector;
3116 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3117 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3118 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3119 SBIG_UINT(pdata,0,dsize);
3120 SBIG_UINT(pdata,8,dfree);
3121 SIVAL(pdata,16,sectors_per_unit);
3122 SIVAL(pdata,20,bytes_per_sector);
3126 case SMB_FS_FULL_SIZE_INFORMATION:
3128 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3130 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3131 return map_nt_error_from_unix(errno);
3133 block_size = lp_block_size(snum);
3134 if (bsize < block_size) {
3135 uint64_t factor = block_size/bsize;
3140 if (bsize > block_size) {
3141 uint64_t factor = bsize/block_size;
3146 bytes_per_sector = 512;
3147 sectors_per_unit = bsize/bytes_per_sector;
3148 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3149 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3150 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3151 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3152 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3153 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3154 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3155 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3159 case SMB_QUERY_FS_DEVICE_INFO:
3160 case SMB_FS_DEVICE_INFORMATION:
3162 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3164 if (!CAN_WRITE(conn)) {
3165 characteristics |= FILE_READ_ONLY_DEVICE;
3168 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3169 SIVAL(pdata,4,characteristics);
3173 #ifdef HAVE_SYS_QUOTAS
3174 case SMB_FS_QUOTA_INFORMATION:
3176 * what we have to send --metze:
3178 * Unknown1: 24 NULL bytes
3179 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3180 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3181 * Quota Flags: 2 byte :
3182 * Unknown3: 6 NULL bytes
3186 * details for Quota Flags:
3188 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3189 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3190 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3191 * 0x0001 Enable Quotas: enable quota for this fs
3195 /* we need to fake up a fsp here,
3196 * because its not send in this call
3199 SMB_NTQUOTA_STRUCT quotas;
3202 ZERO_STRUCT(quotas);
3208 if (get_current_uid(conn) != 0) {
3209 DEBUG(0,("set_user_quota: access_denied "
3210 "service [%s] user [%s]\n",
3211 lp_servicename(SNUM(conn)),
3212 conn->session_info->unix_name));
3213 return NT_STATUS_ACCESS_DENIED;
3216 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3217 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3218 return map_nt_error_from_unix(errno);
3223 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3224 lp_servicename(SNUM(conn))));
3226 /* Unknown1 24 NULL bytes*/
3227 SBIG_UINT(pdata,0,(uint64_t)0);
3228 SBIG_UINT(pdata,8,(uint64_t)0);
3229 SBIG_UINT(pdata,16,(uint64_t)0);
3231 /* Default Soft Quota 8 bytes */
3232 SBIG_UINT(pdata,24,quotas.softlim);
3234 /* Default Hard Quota 8 bytes */
3235 SBIG_UINT(pdata,32,quotas.hardlim);
3237 /* Quota flag 2 bytes */
3238 SSVAL(pdata,40,quotas.qflags);
3240 /* Unknown3 6 NULL bytes */
3246 #endif /* HAVE_SYS_QUOTAS */
3247 case SMB_FS_OBJECTID_INFORMATION:
3249 unsigned char objid[16];
3250 struct smb_extended_info extended_info;
3251 memcpy(pdata,create_volume_objectid(conn, objid),16);
3252 samba_extended_info_version (&extended_info);
3253 SIVAL(pdata,16,extended_info.samba_magic);
3254 SIVAL(pdata,20,extended_info.samba_version);
3255 SIVAL(pdata,24,extended_info.samba_subversion);
3256 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3257 memcpy(pdata+36,extended_info.samba_version_string,28);
3263 * Query the version and capabilities of the CIFS UNIX extensions
3267 case SMB_QUERY_CIFS_UNIX_INFO:
3269 bool large_write = lp_min_receive_file_size() &&
3270 !srv_is_signing_active(conn->sconn);
3271 bool large_read = !srv_is_signing_active(conn->sconn);
3272 int encrypt_caps = 0;
3274 if (!lp_unix_extensions()) {
3275 return NT_STATUS_INVALID_LEVEL;
3278 switch (conn->encrypt_level) {
3284 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3287 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3288 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3289 large_write = false;
3295 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3296 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3298 /* We have POSIX ACLs, pathname, encryption,
3299 * large read/write, and locking capability. */
3301 SBIG_UINT(pdata,4,((uint64_t)(
3302 CIFS_UNIX_POSIX_ACLS_CAP|
3303 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3304 CIFS_UNIX_FCNTL_LOCKS_CAP|
3305 CIFS_UNIX_EXTATTR_CAP|
3306 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3308 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3310 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3314 case SMB_QUERY_POSIX_FS_INFO:
3317 vfs_statvfs_struct svfs;
3319 if (!lp_unix_extensions()) {
3320 return NT_STATUS_INVALID_LEVEL;
3323 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3327 SIVAL(pdata,0,svfs.OptimalTransferSize);
3328 SIVAL(pdata,4,svfs.BlockSize);
3329 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3330 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3331 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3332 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3333 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3334 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3335 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3337 } else if (rc == EOPNOTSUPP) {
3338 return NT_STATUS_INVALID_LEVEL;
3339 #endif /* EOPNOTSUPP */
3341 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3342 return NT_STATUS_DOS(ERRSRV, ERRerror);
3347 case SMB_QUERY_POSIX_WHOAMI:
3353 if (!lp_unix_extensions()) {
3354 return NT_STATUS_INVALID_LEVEL;
3357 if (max_data_bytes < 40) {
3358 return NT_STATUS_BUFFER_TOO_SMALL;
3361 /* We ARE guest if global_sid_Builtin_Guests is
3362 * in our list of SIDs.
3364 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3365 conn->session_info->security_token)) {
3366 flags |= SMB_WHOAMI_GUEST;
3369 /* We are NOT guest if global_sid_Authenticated_Users
3370 * is in our list of SIDs.
3372 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3373 conn->session_info->security_token)) {
3374 flags &= ~SMB_WHOAMI_GUEST;
3377 /* NOTE: 8 bytes for UID/GID, irrespective of native
3378 * platform size. This matches
3379 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3381 data_len = 4 /* flags */
3388 + 4 /* pad/reserved */
3389 + (conn->session_info->utok.ngroups * 8)
3391 + (conn->session_info->security_token->num_sids *
3395 SIVAL(pdata, 0, flags);
3396 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3398 (uint64_t)conn->session_info->utok.uid);
3399 SBIG_UINT(pdata, 16,
3400 (uint64_t)conn->session_info->utok.gid);
3403 if (data_len >= max_data_bytes) {
3404 /* Potential overflow, skip the GIDs and SIDs. */
3406 SIVAL(pdata, 24, 0); /* num_groups */
3407 SIVAL(pdata, 28, 0); /* num_sids */
3408 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3409 SIVAL(pdata, 36, 0); /* reserved */
3415 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3416 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3418 /* We walk the SID list twice, but this call is fairly
3419 * infrequent, and I don't expect that it's performance
3420 * sensitive -- jpeach
3422 for (i = 0, sid_bytes = 0;
3423 i < conn->session_info->security_token->num_sids; ++i) {
3424 sid_bytes += ndr_size_dom_sid(
3425 &conn->session_info->security_token->sids[i],
3429 /* SID list byte count */
3430 SIVAL(pdata, 32, sid_bytes);
3432 /* 4 bytes pad/reserved - must be zero */
3433 SIVAL(pdata, 36, 0);
3437 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3438 SBIG_UINT(pdata, data_len,
3439 (uint64_t)conn->session_info->utok.groups[i]);
3445 i < conn->session_info->security_token->num_sids; ++i) {
3446 int sid_len = ndr_size_dom_sid(
3447 &conn->session_info->security_token->sids[i],
3450 sid_linearize(pdata + data_len, sid_len,
3451 &conn->session_info->security_token->sids[i]);
3452 data_len += sid_len;
3458 case SMB_MAC_QUERY_FS_INFO:
3460 * Thursby MAC extension... ONLY on NTFS filesystems
3461 * once we do streams then we don't need this
3463 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3465 SIVAL(pdata,84,0x100); /* Don't support mac... */
3470 return NT_STATUS_INVALID_LEVEL;
3473 *ret_data_len = data_len;
3474 return NT_STATUS_OK;
3477 /****************************************************************************
3478 Reply to a TRANS2_QFSINFO (query filesystem info).
3479 ****************************************************************************/
3481 static void call_trans2qfsinfo(connection_struct *conn,
3482 struct smb_request *req,
3483 char **pparams, int total_params,
3484 char **ppdata, int total_data,
3485 unsigned int max_data_bytes)
3487 char *params = *pparams;
3488 uint16_t info_level;
3492 if (total_params < 2) {
3493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3497 info_level = SVAL(params,0);
3499 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3500 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3501 DEBUG(0,("call_trans2qfsinfo: encryption required "
3502 "and info level 0x%x sent.\n",
3503 (unsigned int)info_level));
3504 exit_server_cleanly("encryption required "
3510 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3512 status = smbd_do_qfsinfo(conn, req,
3517 if (!NT_STATUS_IS_OK(status)) {
3518 reply_nterror(req, status);
3522 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3525 DEBUG( 4, ( "%s info_level = %d\n",
3526 smb_fn_name(req->cmd), info_level) );
3531 /****************************************************************************
3532 Reply to a TRANS2_SETFSINFO (set filesystem info).
3533 ****************************************************************************/
3535 static void call_trans2setfsinfo(connection_struct *conn,
3536 struct smb_request *req,
3537 char **pparams, int total_params,
3538 char **ppdata, int total_data,
3539 unsigned int max_data_bytes)
3541 char *pdata = *ppdata;
3542 char *params = *pparams;
3545 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3548 if (total_params < 4) {
3549 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3551 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3555 info_level = SVAL(params,2);
3558 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3559 info_level != SMB_SET_CIFS_UNIX_INFO) {
3560 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3561 "info level (0x%x) on IPC$.\n",
3562 (unsigned int)info_level));
3563 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3568 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3569 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3570 DEBUG(0,("call_trans2setfsinfo: encryption required "
3571 "and info level 0x%x sent.\n",
3572 (unsigned int)info_level));
3573 exit_server_cleanly("encryption required "
3579 switch(info_level) {
3580 case SMB_SET_CIFS_UNIX_INFO:
3582 uint16 client_unix_major;
3583 uint16 client_unix_minor;
3584 uint32 client_unix_cap_low;
3585 uint32 client_unix_cap_high;
3587 if (!lp_unix_extensions()) {
3589 NT_STATUS_INVALID_LEVEL);
3593 /* There should be 12 bytes of capabilities set. */
3594 if (total_data < 8) {
3597 NT_STATUS_INVALID_PARAMETER);
3600 client_unix_major = SVAL(pdata,0);
3601 client_unix_minor = SVAL(pdata,2);
3602 client_unix_cap_low = IVAL(pdata,4);
3603 client_unix_cap_high = IVAL(pdata,8);
3604 /* Just print these values for now. */
3605 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3606 cap_low = 0x%x, cap_high = 0x%x\n",
3607 (unsigned int)client_unix_major,
3608 (unsigned int)client_unix_minor,
3609 (unsigned int)client_unix_cap_low,
3610 (unsigned int)client_unix_cap_high ));
3612 /* Here is where we must switch to posix pathname processing... */
3613 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3614 lp_set_posix_pathnames();
3615 mangle_change_to_posix();
3618 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3619 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3620 /* Client that knows how to do posix locks,
3621 * but not posix open/mkdir operations. Set a
3622 * default type for read/write checks. */
3624 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_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;
4675 struct stream_struct *streams;
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 = SMB_VFS_STREAMINFO(
4685 conn, fsp, smb_fname->base_name, talloc_tos(),
4686 &num_streams, &streams);
4688 if (!NT_STATUS_IS_OK(status)) {
4689 DEBUG(10, ("could not get stream info: %s\n",
4690 nt_errstr(status)));
4694 status = marshall_stream_info(num_streams, streams,
4695 pdata, max_data_bytes,
4698 if (!NT_STATUS_IS_OK(status)) {
4699 DEBUG(10, ("marshall_stream_info failed: %s\n",
4700 nt_errstr(status)));
4704 TALLOC_FREE(streams);
4708 case SMB_QUERY_COMPRESSION_INFO:
4709 case SMB_FILE_COMPRESSION_INFORMATION:
4710 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4711 SOFF_T(pdata,0,file_size);
4712 SIVAL(pdata,8,0); /* ??? */
4713 SIVAL(pdata,12,0); /* ??? */
4717 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4718 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4719 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4720 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4721 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4722 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4723 SOFF_T(pdata,32,allocation_size);
4724 SOFF_T(pdata,40,file_size);
4725 SIVAL(pdata,48,mode);
4726 SIVAL(pdata,52,0); /* ??? */
4730 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4732 SIVAL(pdata,0,mode);
4738 * CIFS UNIX Extensions.
4741 case SMB_QUERY_FILE_UNIX_BASIC:
4743 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4744 data_size = PTR_DIFF(pdata,(*ppdata));
4746 DEBUG(4,("smbd_do_qfilepathinfo: "
4747 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4748 dump_data(4, (uint8_t *)(*ppdata), data_size);
4752 case SMB_QUERY_FILE_UNIX_INFO2:
4754 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4755 data_size = PTR_DIFF(pdata,(*ppdata));
4759 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4761 for (i=0; i<100; i++)
4762 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4768 case SMB_QUERY_FILE_UNIX_LINK:
4771 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4774 return NT_STATUS_NO_MEMORY;
4777 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4779 if(!S_ISLNK(psbuf->st_ex_mode)) {
4780 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4783 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4785 len = SMB_VFS_READLINK(conn,
4786 smb_fname->base_name,
4789 return map_nt_error_from_unix(errno);
4792 len = srvstr_push(dstart, flags2,
4794 PTR_DIFF(dend, pdata),
4797 data_size = PTR_DIFF(pdata,(*ppdata));
4802 #if defined(HAVE_POSIX_ACLS)
4803 case SMB_QUERY_POSIX_ACL:
4805 SMB_ACL_T file_acl = NULL;
4806 SMB_ACL_T def_acl = NULL;
4807 uint16 num_file_acls = 0;
4808 uint16 num_def_acls = 0;
4810 if (fsp && fsp->fh->fd != -1) {
4811 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4814 SMB_VFS_SYS_ACL_GET_FILE(conn,
4815 smb_fname->base_name,
4816 SMB_ACL_TYPE_ACCESS);
4819 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4820 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4821 "not implemented on "
4822 "filesystem containing %s\n",
4823 smb_fname->base_name));
4824 return NT_STATUS_NOT_IMPLEMENTED;
4827 if (S_ISDIR(psbuf->st_ex_mode)) {
4828 if (fsp && fsp->is_directory) {
4830 SMB_VFS_SYS_ACL_GET_FILE(
4832 fsp->fsp_name->base_name,
4833 SMB_ACL_TYPE_DEFAULT);
4836 SMB_VFS_SYS_ACL_GET_FILE(
4838 smb_fname->base_name,
4839 SMB_ACL_TYPE_DEFAULT);
4841 def_acl = free_empty_sys_acl(conn, def_acl);
4844 num_file_acls = count_acl_entries(conn, file_acl);
4845 num_def_acls = count_acl_entries(conn, def_acl);
4847 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4848 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4850 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4851 SMB_POSIX_ACL_HEADER_SIZE) ));
4853 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4856 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4858 return NT_STATUS_BUFFER_TOO_SMALL;
4861 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4862 SSVAL(pdata,2,num_file_acls);
4863 SSVAL(pdata,4,num_def_acls);
4864 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4866 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4869 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4871 return NT_STATUS_INTERNAL_ERROR;
4873 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4875 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4878 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4880 return NT_STATUS_INTERNAL_ERROR;
4884 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4887 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4889 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4895 case SMB_QUERY_POSIX_LOCK:
4900 enum brl_type lock_type;
4902 /* We need an open file with a real fd for this. */
4903 if (!fsp || fsp->fh->fd == -1) {
4904 return NT_STATUS_INVALID_LEVEL;
4907 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4908 return NT_STATUS_INVALID_PARAMETER;
4911 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4912 case POSIX_LOCK_TYPE_READ:
4913 lock_type = READ_LOCK;
4915 case POSIX_LOCK_TYPE_WRITE:
4916 lock_type = WRITE_LOCK;
4918 case POSIX_LOCK_TYPE_UNLOCK:
4920 /* There's no point in asking for an unlock... */
4921 return NT_STATUS_INVALID_PARAMETER;
4924 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4925 #if defined(HAVE_LONGLONG)
4926 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4927 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4928 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4929 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4930 #else /* HAVE_LONGLONG */
4931 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4932 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4933 #endif /* HAVE_LONGLONG */
4935 status = query_lock(fsp,
4942 if (ERROR_WAS_LOCK_DENIED(status)) {
4943 /* Here we need to report who has it locked... */
4944 data_size = POSIX_LOCK_DATA_SIZE;
4946 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4947 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4948 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4949 #if defined(HAVE_LONGLONG)
4950 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4951 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4952 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4953 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4954 #else /* HAVE_LONGLONG */
4955 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4956 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4957 #endif /* HAVE_LONGLONG */
4959 } else if (NT_STATUS_IS_OK(status)) {
4960 /* For success we just return a copy of what we sent
4961 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4962 data_size = POSIX_LOCK_DATA_SIZE;
4963 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4964 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4972 return NT_STATUS_INVALID_LEVEL;
4975 *pdata_size = data_size;
4976 return NT_STATUS_OK;
4979 /****************************************************************************
4980 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4981 file name or file id).
4982 ****************************************************************************/
4984 static void call_trans2qfilepathinfo(connection_struct *conn,
4985 struct smb_request *req,
4986 unsigned int tran_call,
4987 char **pparams, int total_params,
4988 char **ppdata, int total_data,
4989 unsigned int max_data_bytes)
4991 char *params = *pparams;
4992 char *pdata = *ppdata;
4994 unsigned int data_size = 0;
4995 unsigned int param_size = 2;
4996 struct smb_filename *smb_fname = NULL;
4997 bool delete_pending = False;
4998 struct timespec write_time_ts;
4999 files_struct *fsp = NULL;
5000 struct file_id fileid;
5001 struct ea_list *ea_list = NULL;
5002 int lock_data_count = 0;
5003 char *lock_data = NULL;
5004 NTSTATUS status = NT_STATUS_OK;
5007 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5011 ZERO_STRUCT(write_time_ts);
5013 if (tran_call == TRANSACT2_QFILEINFO) {
5014 if (total_params < 4) {
5015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5020 call_trans2qpipeinfo(conn, req, tran_call,
5021 pparams, total_params,
5027 fsp = file_fsp(req, SVAL(params,0));
5028 info_level = SVAL(params,2);
5030 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5032 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5033 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5037 /* Initial check for valid fsp ptr. */
5038 if (!check_fsp_open(conn, req, fsp)) {
5042 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5044 if (!NT_STATUS_IS_OK(status)) {
5045 reply_nterror(req, status);
5049 if(fsp->fake_file_handle) {
5051 * This is actually for the QUOTA_FAKE_FILE --metze
5054 /* We know this name is ok, it's already passed the checks. */
5056 } else if(fsp->fh->fd == -1) {
5058 * This is actually a QFILEINFO on a directory
5059 * handle (returned from an NT SMB). NT5.0 seems
5060 * to do this call. JRA.
5063 if (INFO_LEVEL_IS_UNIX(info_level)) {
5064 /* Always do lstat for UNIX calls. */
5065 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5066 DEBUG(3,("call_trans2qfilepathinfo: "
5067 "SMB_VFS_LSTAT of %s failed "
5069 smb_fname_str_dbg(smb_fname),
5072 map_nt_error_from_unix(errno));
5075 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5076 DEBUG(3,("call_trans2qfilepathinfo: "
5077 "SMB_VFS_STAT of %s failed (%s)\n",
5078 smb_fname_str_dbg(smb_fname),
5081 map_nt_error_from_unix(errno));
5085 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5086 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5089 * Original code - this is an open file.
5091 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5092 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5093 fsp->fnum, strerror(errno)));
5095 map_nt_error_from_unix(errno));
5098 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5099 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5107 if (total_params < 7) {
5108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5112 info_level = SVAL(params,0);
5114 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5116 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5117 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5121 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5123 STR_TERMINATE, &status);
5124 if (!NT_STATUS_IS_OK(status)) {
5125 reply_nterror(req, status);
5129 status = filename_convert(req,
5131 req->flags2 & FLAGS2_DFS_PATHNAMES,
5136 if (!NT_STATUS_IS_OK(status)) {
5137 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5138 reply_botherror(req,
5139 NT_STATUS_PATH_NOT_COVERED,
5140 ERRSRV, ERRbadpath);
5143 reply_nterror(req, status);
5147 /* If this is a stream, check if there is a delete_pending. */
5148 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5149 && is_ntfs_stream_smb_fname(smb_fname)) {
5150 struct smb_filename *smb_fname_base = NULL;
5152 /* Create an smb_filename with stream_name == NULL. */
5154 create_synthetic_smb_fname(talloc_tos(),
5155 smb_fname->base_name,
5158 if (!NT_STATUS_IS_OK(status)) {
5159 reply_nterror(req, status);
5163 if (INFO_LEVEL_IS_UNIX(info_level)) {
5164 /* Always do lstat for UNIX calls. */
5165 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5166 DEBUG(3,("call_trans2qfilepathinfo: "
5167 "SMB_VFS_LSTAT of %s failed "
5169 smb_fname_str_dbg(smb_fname_base),
5171 TALLOC_FREE(smb_fname_base);
5173 map_nt_error_from_unix(errno));
5177 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5178 DEBUG(3,("call_trans2qfilepathinfo: "
5179 "fileinfo of %s failed "
5181 smb_fname_str_dbg(smb_fname_base),
5183 TALLOC_FREE(smb_fname_base);
5185 map_nt_error_from_unix(errno));
5190 status = file_name_hash(conn,
5191 smb_fname_str_dbg(smb_fname_base),
5193 if (!NT_STATUS_IS_OK(status)) {
5194 TALLOC_FREE(smb_fname_base);
5195 reply_nterror(req, status);
5199 fileid = vfs_file_id_from_sbuf(conn,
5200 &smb_fname_base->st);
5201 TALLOC_FREE(smb_fname_base);
5202 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5203 if (delete_pending) {
5204 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5209 if (INFO_LEVEL_IS_UNIX(info_level)) {
5210 /* Always do lstat for UNIX calls. */
5211 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5212 DEBUG(3,("call_trans2qfilepathinfo: "
5213 "SMB_VFS_LSTAT of %s failed (%s)\n",
5214 smb_fname_str_dbg(smb_fname),
5217 map_nt_error_from_unix(errno));
5222 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5223 DEBUG(3,("call_trans2qfilepathinfo: "
5224 "SMB_VFS_STAT of %s failed (%s)\n",
5225 smb_fname_str_dbg(smb_fname),
5228 map_nt_error_from_unix(errno));
5233 status = file_name_hash(conn,
5234 smb_fname_str_dbg(smb_fname),
5236 if (!NT_STATUS_IS_OK(status)) {
5237 reply_nterror(req, status);
5241 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5242 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5243 if (delete_pending) {
5244 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5249 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5250 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5251 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5253 /* Pull out any data sent here before we realloc. */
5254 switch (info_level) {
5255 case SMB_INFO_QUERY_EAS_FROM_LIST:
5257 /* Pull any EA list from the data portion. */
5260 if (total_data < 4) {
5262 req, NT_STATUS_INVALID_PARAMETER);
5265 ea_size = IVAL(pdata,0);
5267 if (total_data > 0 && ea_size != total_data) {
5268 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5269 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5271 req, NT_STATUS_INVALID_PARAMETER);
5275 if (!lp_ea_support(SNUM(conn))) {
5276 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5280 /* Pull out the list of names. */
5281 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5284 req, NT_STATUS_INVALID_PARAMETER);
5290 case SMB_QUERY_POSIX_LOCK:
5292 if (fsp == NULL || fsp->fh->fd == -1) {
5293 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5297 if (total_data != POSIX_LOCK_DATA_SIZE) {
5299 req, NT_STATUS_INVALID_PARAMETER);
5303 /* Copy the lock range data. */
5304 lock_data = (char *)TALLOC_MEMDUP(
5305 req, pdata, total_data);
5307 reply_nterror(req, NT_STATUS_NO_MEMORY);
5310 lock_data_count = total_data;
5316 *pparams = (char *)SMB_REALLOC(*pparams,2);
5317 if (*pparams == NULL) {
5318 reply_nterror(req, NT_STATUS_NO_MEMORY);
5325 * draft-leach-cifs-v1-spec-02.txt
5326 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5329 * The requested information is placed in the Data portion of the
5330 * transaction response. For the information levels greater than 0x100,
5331 * the transaction response has 1 parameter word which should be
5332 * ignored by the client.
5334 * However Windows only follows this rule for the IS_NAME_VALID call.
5336 switch (info_level) {
5337 case SMB_INFO_IS_NAME_VALID:
5342 if ((info_level & 0xFF00) == 0xFF00) {
5344 * We use levels that start with 0xFF00
5345 * internally to represent SMB2 specific levels
5347 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5351 status = smbd_do_qfilepathinfo(conn, req, info_level,
5353 delete_pending, write_time_ts,
5355 lock_data_count, lock_data,
5356 req->flags2, max_data_bytes,
5357 ppdata, &data_size);
5358 if (!NT_STATUS_IS_OK(status)) {
5359 reply_nterror(req, status);
5363 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5369 /****************************************************************************
5370 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5372 ****************************************************************************/
5374 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5375 connection_struct *conn,
5376 struct smb_request *req,
5377 bool overwrite_if_exists,
5378 const struct smb_filename *smb_fname_old,
5379 struct smb_filename *smb_fname_new)
5381 NTSTATUS status = NT_STATUS_OK;
5383 /* source must already exist. */
5384 if (!VALID_STAT(smb_fname_old->st)) {
5385 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5388 if (VALID_STAT(smb_fname_new->st)) {
5389 if (overwrite_if_exists) {
5390 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5391 return NT_STATUS_FILE_IS_A_DIRECTORY;
5393 status = unlink_internals(conn,
5395 FILE_ATTRIBUTE_NORMAL,
5398 if (!NT_STATUS_IS_OK(status)) {
5402 /* Disallow if newname already exists. */
5403 return NT_STATUS_OBJECT_NAME_COLLISION;
5407 /* No links from a directory. */
5408 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5409 return NT_STATUS_FILE_IS_A_DIRECTORY;
5412 /* Setting a hardlink to/from a stream isn't currently supported. */
5413 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5414 is_ntfs_stream_smb_fname(smb_fname_new)) {
5415 return NT_STATUS_INVALID_PARAMETER;
5418 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5419 smb_fname_old->base_name, smb_fname_new->base_name));
5421 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5422 smb_fname_new->base_name) != 0) {
5423 status = map_nt_error_from_unix(errno);
5424 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5425 nt_errstr(status), smb_fname_old->base_name,
5426 smb_fname_new->base_name));
5431 /****************************************************************************
5432 Deal with setting the time from any of the setfilepathinfo functions.
5433 ****************************************************************************/
5435 NTSTATUS smb_set_file_time(connection_struct *conn,
5437 const struct smb_filename *smb_fname,
5438 struct smb_file_time *ft,
5439 bool setting_write_time)
5441 struct smb_filename smb_fname_base;
5443 FILE_NOTIFY_CHANGE_LAST_ACCESS
5444 |FILE_NOTIFY_CHANGE_LAST_WRITE
5445 |FILE_NOTIFY_CHANGE_CREATION;
5447 if (!VALID_STAT(smb_fname->st)) {
5448 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5451 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5452 return NT_STATUS_ACCESS_DENIED;
5455 /* get some defaults (no modifications) if any info is zero or -1. */
5456 if (null_timespec(ft->create_time)) {
5457 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5460 if (null_timespec(ft->atime)) {
5461 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5464 if (null_timespec(ft->mtime)) {
5465 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5468 if (!setting_write_time) {
5469 /* ft->mtime comes from change time, not write time. */
5470 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5473 /* Ensure the resolution is the correct for
5474 * what we can store on this filesystem. */
5476 round_timespec(conn->ts_res, &ft->create_time);
5477 round_timespec(conn->ts_res, &ft->ctime);
5478 round_timespec(conn->ts_res, &ft->atime);
5479 round_timespec(conn->ts_res, &ft->mtime);
5481 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5482 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5483 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5484 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5485 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5486 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5487 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5488 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5490 if (setting_write_time) {
5492 * This was a Windows setfileinfo on an open file.
5493 * NT does this a lot. We also need to
5494 * set the time here, as it can be read by
5495 * FindFirst/FindNext and with the patch for bug #2045
5496 * in smbd/fileio.c it ensures that this timestamp is
5497 * kept sticky even after a write. We save the request
5498 * away and will set it on file close and after a write. JRA.
5501 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5502 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5505 if (fsp->base_fsp) {
5506 set_sticky_write_time_fsp(fsp->base_fsp,
5509 set_sticky_write_time_fsp(fsp, ft->mtime);
5512 set_sticky_write_time_path(
5513 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5518 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5520 /* Always call ntimes on the base, even if a stream was passed in. */
5521 smb_fname_base = *smb_fname;
5522 smb_fname_base.stream_name = NULL;
5524 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5525 return map_nt_error_from_unix(errno);
5528 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5529 smb_fname->base_name);
5530 return NT_STATUS_OK;
5533 /****************************************************************************
5534 Deal with setting the dosmode from any of the setfilepathinfo functions.
5535 ****************************************************************************/
5537 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5538 const struct smb_filename *smb_fname,
5541 struct smb_filename *smb_fname_base = NULL;
5544 if (!VALID_STAT(smb_fname->st)) {
5545 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5548 /* Always operate on the base_name, even if a stream was passed in. */
5549 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5550 NULL, &smb_fname->st,
5552 if (!NT_STATUS_IS_OK(status)) {
5557 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5558 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5560 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5564 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5566 /* check the mode isn't different, before changing it */
5567 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5568 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5569 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5570 (unsigned int)dosmode));
5572 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5574 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5576 smb_fname_str_dbg(smb_fname_base),
5578 status = map_nt_error_from_unix(errno);
5582 status = NT_STATUS_OK;
5584 TALLOC_FREE(smb_fname_base);
5588 /****************************************************************************
5589 Deal with setting the size from any of the setfilepathinfo functions.
5590 ****************************************************************************/
5592 static NTSTATUS smb_set_file_size(connection_struct *conn,
5593 struct smb_request *req,
5595 const struct smb_filename *smb_fname,
5596 const SMB_STRUCT_STAT *psbuf,
5598 bool fail_after_createfile)
5600 NTSTATUS status = NT_STATUS_OK;
5601 struct smb_filename *smb_fname_tmp = NULL;
5602 files_struct *new_fsp = NULL;
5604 if (!VALID_STAT(*psbuf)) {
5605 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5608 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5609 return NT_STATUS_ACCESS_DENIED;
5612 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5614 if (size == get_file_size_stat(psbuf)) {
5615 return NT_STATUS_OK;
5618 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5619 smb_fname_str_dbg(smb_fname), (double)size));
5621 if (fsp && fsp->fh->fd != -1) {
5622 /* Handle based call. */
5623 if (vfs_set_filelen(fsp, size) == -1) {
5624 return map_nt_error_from_unix(errno);
5626 trigger_write_time_update_immediate(fsp);
5627 return NT_STATUS_OK;
5630 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5631 if (!NT_STATUS_IS_OK(status)) {
5635 smb_fname_tmp->st = *psbuf;
5637 status = SMB_VFS_CREATE_FILE(
5640 0, /* root_dir_fid */
5641 smb_fname_tmp, /* fname */
5642 FILE_WRITE_DATA, /* access_mask */
5643 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5645 FILE_OPEN, /* create_disposition*/
5646 0, /* create_options */
5647 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5648 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5649 0, /* allocation_size */
5650 0, /* private_flags */
5653 &new_fsp, /* result */
5656 TALLOC_FREE(smb_fname_tmp);
5658 if (!NT_STATUS_IS_OK(status)) {
5659 /* NB. We check for open_was_deferred in the caller. */
5663 /* See RAW-SFILEINFO-END-OF-FILE */
5664 if (fail_after_createfile) {
5665 close_file(req, new_fsp,NORMAL_CLOSE);
5666 return NT_STATUS_INVALID_LEVEL;
5669 if (vfs_set_filelen(new_fsp, size) == -1) {
5670 status = map_nt_error_from_unix(errno);
5671 close_file(req, new_fsp,NORMAL_CLOSE);
5675 trigger_write_time_update_immediate(new_fsp);
5676 close_file(req, new_fsp,NORMAL_CLOSE);
5677 return NT_STATUS_OK;
5680 /****************************************************************************
5681 Deal with SMB_INFO_SET_EA.
5682 ****************************************************************************/
5684 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5688 const struct smb_filename *smb_fname)
5690 struct ea_list *ea_list = NULL;
5691 TALLOC_CTX *ctx = NULL;
5692 NTSTATUS status = NT_STATUS_OK;
5694 if (total_data < 10) {
5696 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5697 length. They seem to have no effect. Bug #3212. JRA */
5699 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5700 /* We're done. We only get EA info in this call. */
5701 return NT_STATUS_OK;
5704 return NT_STATUS_INVALID_PARAMETER;
5707 if (IVAL(pdata,0) > total_data) {
5708 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5709 IVAL(pdata,0), (unsigned int)total_data));
5710 return NT_STATUS_INVALID_PARAMETER;
5714 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5716 return NT_STATUS_INVALID_PARAMETER;
5719 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5720 return NT_STATUS_ACCESS_DENIED;
5723 status = set_ea(conn, fsp, smb_fname, ea_list);
5728 /****************************************************************************
5729 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5730 ****************************************************************************/
5732 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5737 struct ea_list *ea_list = NULL;
5741 return NT_STATUS_INVALID_HANDLE;
5744 if (!lp_ea_support(SNUM(conn))) {
5745 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5746 "EA's not supported.\n",
5747 (unsigned int)total_data));
5748 return NT_STATUS_EAS_NOT_SUPPORTED;
5751 if (total_data < 10) {
5752 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5754 (unsigned int)total_data));
5755 return NT_STATUS_INVALID_PARAMETER;
5758 ea_list = read_nttrans_ea_list(talloc_tos(),
5763 return NT_STATUS_INVALID_PARAMETER;
5766 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5767 return NT_STATUS_ACCESS_DENIED;
5770 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5772 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5773 smb_fname_str_dbg(fsp->fsp_name),
5774 nt_errstr(status) ));
5780 /****************************************************************************
5781 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5782 ****************************************************************************/
5784 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5788 struct smb_filename *smb_fname)
5790 NTSTATUS status = NT_STATUS_OK;
5791 bool delete_on_close;
5794 if (total_data < 1) {
5795 return NT_STATUS_INVALID_PARAMETER;
5799 return NT_STATUS_INVALID_HANDLE;
5802 delete_on_close = (CVAL(pdata,0) ? True : False);
5803 dosmode = dos_mode(conn, smb_fname);
5805 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5806 "delete_on_close = %u\n",
5807 smb_fname_str_dbg(smb_fname),
5808 (unsigned int)dosmode,
5809 (unsigned int)delete_on_close ));
5811 if (delete_on_close) {
5812 status = can_set_delete_on_close(fsp, dosmode);
5813 if (!NT_STATUS_IS_OK(status)) {
5818 /* The set is across all open files on this dev/inode pair. */
5819 if (!set_delete_on_close(fsp, delete_on_close,
5820 &conn->session_info->utok)) {
5821 return NT_STATUS_ACCESS_DENIED;
5823 return NT_STATUS_OK;
5826 /****************************************************************************
5827 Deal with SMB_FILE_POSITION_INFORMATION.
5828 ****************************************************************************/
5830 static NTSTATUS smb_file_position_information(connection_struct *conn,
5835 uint64_t position_information;
5837 if (total_data < 8) {
5838 return NT_STATUS_INVALID_PARAMETER;
5842 /* Ignore on pathname based set. */
5843 return NT_STATUS_OK;
5846 position_information = (uint64_t)IVAL(pdata,0);
5847 #ifdef LARGE_SMB_OFF_T
5848 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5849 #else /* LARGE_SMB_OFF_T */
5850 if (IVAL(pdata,4) != 0) {
5851 /* more than 32 bits? */
5852 return NT_STATUS_INVALID_PARAMETER;
5854 #endif /* LARGE_SMB_OFF_T */
5856 DEBUG(10,("smb_file_position_information: Set file position "
5857 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5858 (double)position_information));
5859 fsp->fh->position_information = position_information;
5860 return NT_STATUS_OK;
5863 /****************************************************************************
5864 Deal with SMB_FILE_MODE_INFORMATION.
5865 ****************************************************************************/
5867 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5873 if (total_data < 4) {
5874 return NT_STATUS_INVALID_PARAMETER;
5876 mode = IVAL(pdata,0);
5877 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5878 return NT_STATUS_INVALID_PARAMETER;
5880 return NT_STATUS_OK;
5883 /****************************************************************************
5884 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5885 ****************************************************************************/
5887 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5888 struct smb_request *req,
5891 const struct smb_filename *smb_fname)
5893 char *link_target = NULL;
5894 const char *newname = smb_fname->base_name;
5895 TALLOC_CTX *ctx = talloc_tos();
5897 /* Set a symbolic link. */
5898 /* Don't allow this if follow links is false. */
5900 if (total_data == 0) {
5901 return NT_STATUS_INVALID_PARAMETER;
5904 if (!lp_symlinks(SNUM(conn))) {
5905 return NT_STATUS_ACCESS_DENIED;
5908 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5909 total_data, STR_TERMINATE);
5912 return NT_STATUS_INVALID_PARAMETER;
5915 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5916 newname, link_target ));
5918 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5919 return map_nt_error_from_unix(errno);
5922 return NT_STATUS_OK;
5925 /****************************************************************************
5926 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5927 ****************************************************************************/
5929 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5930 struct smb_request *req,
5931 const char *pdata, int total_data,
5932 struct smb_filename *smb_fname_new)
5934 char *oldname = NULL;
5935 struct smb_filename *smb_fname_old = NULL;
5936 TALLOC_CTX *ctx = talloc_tos();
5937 NTSTATUS status = NT_STATUS_OK;
5939 /* Set a hard link. */
5940 if (total_data == 0) {
5941 return NT_STATUS_INVALID_PARAMETER;
5944 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5945 total_data, STR_TERMINATE, &status);
5946 if (!NT_STATUS_IS_OK(status)) {
5950 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5951 smb_fname_str_dbg(smb_fname_new), oldname));
5953 status = filename_convert(ctx,
5955 req->flags2 & FLAGS2_DFS_PATHNAMES,
5960 if (!NT_STATUS_IS_OK(status)) {
5964 return hardlink_internals(ctx, conn, req, false,
5965 smb_fname_old, smb_fname_new);
5968 /****************************************************************************
5969 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5970 ****************************************************************************/
5972 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5973 struct smb_request *req,
5977 struct smb_filename *smb_fname_src)
5981 char *newname = NULL;
5982 struct smb_filename *smb_fname_dst = NULL;
5983 NTSTATUS status = NT_STATUS_OK;
5984 TALLOC_CTX *ctx = talloc_tos();
5987 return NT_STATUS_INVALID_HANDLE;
5990 if (total_data < 20) {
5991 return NT_STATUS_INVALID_PARAMETER;
5994 overwrite = (CVAL(pdata,0) ? True : False);
5995 len = IVAL(pdata,16);
5997 if (len > (total_data - 20) || (len == 0)) {
5998 return NT_STATUS_INVALID_PARAMETER;
6001 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6002 &pdata[20], len, STR_TERMINATE,
6004 if (!NT_STATUS_IS_OK(status)) {
6008 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6011 status = filename_convert(ctx,
6013 req->flags2 & FLAGS2_DFS_PATHNAMES,
6018 if (!NT_STATUS_IS_OK(status)) {
6022 if (fsp->base_fsp) {
6023 /* newname must be a stream name. */
6024 if (newname[0] != ':') {
6025 return NT_STATUS_NOT_SUPPORTED;
6028 /* Create an smb_fname to call rename_internals_fsp() with. */
6029 status = create_synthetic_smb_fname(talloc_tos(),
6030 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6032 if (!NT_STATUS_IS_OK(status)) {
6037 * Set the original last component, since
6038 * rename_internals_fsp() requires it.
6040 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6042 if (smb_fname_dst->original_lcomp == NULL) {
6043 status = NT_STATUS_NO_MEMORY;
6049 DEBUG(10,("smb2_file_rename_information: "
6050 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6051 fsp->fnum, fsp_str_dbg(fsp),
6052 smb_fname_str_dbg(smb_fname_dst)));
6053 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
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 static NTSTATUS smb_posix_open(connection_struct *conn,
7230 struct smb_request *req,
7233 struct smb_filename *smb_fname,
7234 int *pdata_return_size)
7236 bool extended_oplock_granted = False;
7237 char *pdata = *ppdata;
7239 uint32 wire_open_mode = 0;
7240 uint32 raw_unixmode = 0;
7241 uint32 mod_unixmode = 0;
7242 uint32 create_disp = 0;
7243 uint32 access_mask = 0;
7244 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7245 NTSTATUS status = NT_STATUS_OK;
7246 mode_t unixmode = (mode_t)0;
7247 files_struct *fsp = NULL;
7248 int oplock_request = 0;
7250 uint16 info_level_return = 0;
7252 if (total_data < 18) {
7253 return NT_STATUS_INVALID_PARAMETER;
7256 flags = IVAL(pdata,0);
7257 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7258 if (oplock_request) {
7259 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7262 wire_open_mode = IVAL(pdata,4);
7264 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7265 return smb_posix_mkdir(conn, req,
7272 switch (wire_open_mode & SMB_ACCMODE) {
7274 access_mask = FILE_READ_DATA;
7277 access_mask = FILE_WRITE_DATA;
7280 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7283 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7284 (unsigned int)wire_open_mode ));
7285 return NT_STATUS_INVALID_PARAMETER;
7288 wire_open_mode &= ~SMB_ACCMODE;
7290 /* First take care of O_CREAT|O_EXCL interactions. */
7291 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7292 case (SMB_O_CREAT | SMB_O_EXCL):
7293 /* File exists fail. File not exist create. */
7294 create_disp = FILE_CREATE;
7297 /* File exists open. File not exist create. */
7298 create_disp = FILE_OPEN_IF;
7301 /* File exists open. File not exist fail. */
7302 create_disp = FILE_OPEN;
7305 /* O_EXCL on its own without O_CREAT is undefined. */
7307 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7308 (unsigned int)wire_open_mode ));
7309 return NT_STATUS_INVALID_PARAMETER;
7312 /* Next factor in the effects of O_TRUNC. */
7313 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7315 if (wire_open_mode & SMB_O_TRUNC) {
7316 switch (create_disp) {
7318 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7319 /* Leave create_disp alone as
7320 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7322 /* File exists fail. File not exist create. */
7325 /* SMB_O_CREAT | SMB_O_TRUNC */
7326 /* File exists overwrite. File not exist create. */
7327 create_disp = FILE_OVERWRITE_IF;
7331 /* File exists overwrite. File not exist fail. */
7332 create_disp = FILE_OVERWRITE;
7335 /* Cannot get here. */
7336 smb_panic("smb_posix_open: logic error");
7337 return NT_STATUS_INVALID_PARAMETER;
7341 raw_unixmode = IVAL(pdata,8);
7342 /* Next 4 bytes are not yet defined. */
7344 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7345 (VALID_STAT(smb_fname->st) ?
7346 PERM_EXISTING_FILE : PERM_NEW_FILE),
7349 if (!NT_STATUS_IS_OK(status)) {
7353 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7355 if (wire_open_mode & SMB_O_SYNC) {
7356 create_options |= FILE_WRITE_THROUGH;
7358 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7359 VALID_STAT_OF_DIR(smb_fname->st)) {
7360 if (access_mask != FILE_READ_DATA) {
7361 return NT_STATUS_FILE_IS_A_DIRECTORY;
7363 create_options &= ~FILE_NON_DIRECTORY_FILE;
7364 create_options |= FILE_DIRECTORY_FILE;
7366 if (wire_open_mode & SMB_O_APPEND) {
7367 access_mask |= FILE_APPEND_DATA;
7369 if (wire_open_mode & SMB_O_DIRECT) {
7370 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7373 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7374 smb_fname_str_dbg(smb_fname),
7375 (unsigned int)wire_open_mode,
7376 (unsigned int)unixmode ));
7378 status = SMB_VFS_CREATE_FILE(
7381 0, /* root_dir_fid */
7382 smb_fname, /* fname */
7383 access_mask, /* access_mask */
7384 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7386 create_disp, /* create_disposition*/
7387 create_options, /* create_options */
7388 mod_unixmode, /* file_attributes */
7389 oplock_request, /* oplock_request */
7390 0, /* allocation_size */
7391 0, /* private_flags */
7397 if (!NT_STATUS_IS_OK(status)) {
7401 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7402 extended_oplock_granted = True;
7405 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7406 extended_oplock_granted = True;
7409 info_level_return = SVAL(pdata,16);
7411 /* Allocate the correct return size. */
7413 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7414 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7415 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7416 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7418 *pdata_return_size = 12;
7421 /* Realloc the data size */
7422 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7423 if (*ppdata == NULL) {
7424 close_file(req, fsp, ERROR_CLOSE);
7425 *pdata_return_size = 0;
7426 return NT_STATUS_NO_MEMORY;
7430 if (extended_oplock_granted) {
7431 if (flags & REQUEST_BATCH_OPLOCK) {
7432 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7434 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7436 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7437 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7439 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7442 SSVAL(pdata,2,fsp->fnum);
7443 SIVAL(pdata,4,info); /* Was file created etc. */
7445 switch (info_level_return) {
7446 case SMB_QUERY_FILE_UNIX_BASIC:
7447 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7448 SSVAL(pdata,10,0); /* padding. */
7449 store_file_unix_basic(conn, pdata + 12, fsp,
7452 case SMB_QUERY_FILE_UNIX_INFO2:
7453 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7454 SSVAL(pdata,10,0); /* padding. */
7455 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7459 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7460 SSVAL(pdata,10,0); /* padding. */
7463 return NT_STATUS_OK;
7466 /****************************************************************************
7467 Delete a file with POSIX semantics.
7468 ****************************************************************************/
7470 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7471 struct smb_request *req,
7474 struct smb_filename *smb_fname)
7476 NTSTATUS status = NT_STATUS_OK;
7477 files_struct *fsp = NULL;
7481 int create_options = 0;
7483 struct share_mode_lock *lck = NULL;
7485 if (total_data < 2) {
7486 return NT_STATUS_INVALID_PARAMETER;
7489 flags = SVAL(pdata,0);
7491 if (!VALID_STAT(smb_fname->st)) {
7492 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7495 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7496 !VALID_STAT_OF_DIR(smb_fname->st)) {
7497 return NT_STATUS_NOT_A_DIRECTORY;
7500 DEBUG(10,("smb_posix_unlink: %s %s\n",
7501 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7502 smb_fname_str_dbg(smb_fname)));
7504 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7505 create_options |= FILE_DIRECTORY_FILE;
7508 status = SMB_VFS_CREATE_FILE(
7511 0, /* root_dir_fid */
7512 smb_fname, /* fname */
7513 DELETE_ACCESS, /* access_mask */
7514 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7516 FILE_OPEN, /* create_disposition*/
7517 create_options, /* create_options */
7518 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7519 0, /* oplock_request */
7520 0, /* allocation_size */
7521 0, /* private_flags */
7527 if (!NT_STATUS_IS_OK(status)) {
7532 * Don't lie to client. If we can't really delete due to
7533 * non-POSIX opens return SHARING_VIOLATION.
7536 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7539 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7540 "lock for file %s\n", fsp_str_dbg(fsp)));
7541 close_file(req, fsp, NORMAL_CLOSE);
7542 return NT_STATUS_INVALID_PARAMETER;
7546 * See if others still have the file open. If this is the case, then
7547 * don't delete. If all opens are POSIX delete we can set the delete
7548 * on close disposition.
7550 for (i=0; i<lck->num_share_modes; i++) {
7551 struct share_mode_entry *e = &lck->share_modes[i];
7552 if (is_valid_share_mode_entry(e)) {
7553 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7556 /* Fail with sharing violation. */
7557 close_file(req, fsp, NORMAL_CLOSE);
7559 return NT_STATUS_SHARING_VIOLATION;
7564 * Set the delete on close.
7566 status = smb_set_file_disposition_info(conn,
7572 if (!NT_STATUS_IS_OK(status)) {
7573 close_file(req, fsp, NORMAL_CLOSE);
7578 return close_file(req, fsp, NORMAL_CLOSE);
7581 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7582 struct smb_request *req,
7583 TALLOC_CTX *mem_ctx,
7584 uint16_t info_level,
7586 struct smb_filename *smb_fname,
7587 char **ppdata, int total_data,
7590 char *pdata = *ppdata;
7591 NTSTATUS status = NT_STATUS_OK;
7592 int data_return_size = 0;
7596 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7597 return NT_STATUS_INVALID_LEVEL;
7600 if (!CAN_WRITE(conn)) {
7601 /* Allow POSIX opens. The open path will deny
7602 * any non-readonly opens. */
7603 if (info_level != SMB_POSIX_PATH_OPEN) {
7604 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7608 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7609 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7610 fsp ? fsp->fnum : -1, info_level, total_data));
7612 switch (info_level) {
7614 case SMB_INFO_STANDARD:
7616 status = smb_set_info_standard(conn,
7624 case SMB_INFO_SET_EA:
7626 status = smb_info_set_ea(conn,
7634 case SMB_SET_FILE_BASIC_INFO:
7635 case SMB_FILE_BASIC_INFORMATION:
7637 status = smb_set_file_basic_info(conn,
7645 case SMB_FILE_ALLOCATION_INFORMATION:
7646 case SMB_SET_FILE_ALLOCATION_INFO:
7648 status = smb_set_file_allocation_info(conn, req,
7656 case SMB_FILE_END_OF_FILE_INFORMATION:
7657 case SMB_SET_FILE_END_OF_FILE_INFO:
7660 * XP/Win7 both fail after the createfile with
7661 * SMB_SET_FILE_END_OF_FILE_INFO but not
7662 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7663 * The level is known here, so pass it down
7667 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7669 status = smb_set_file_end_of_file_info(conn, req,
7678 case SMB_FILE_DISPOSITION_INFORMATION:
7679 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7682 /* JRA - We used to just ignore this on a path ?
7683 * Shouldn't this be invalid level on a pathname
7686 if (tran_call != TRANSACT2_SETFILEINFO) {
7687 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7690 status = smb_set_file_disposition_info(conn,
7698 case SMB_FILE_POSITION_INFORMATION:
7700 status = smb_file_position_information(conn,
7707 case SMB_FILE_FULL_EA_INFORMATION:
7709 status = smb_set_file_full_ea_info(conn,
7716 /* From tridge Samba4 :
7717 * MODE_INFORMATION in setfileinfo (I have no
7718 * idea what "mode information" on a file is - it takes a value of 0,
7719 * 2, 4 or 6. What could it be?).
7722 case SMB_FILE_MODE_INFORMATION:
7724 status = smb_file_mode_information(conn,
7731 * CIFS UNIX extensions.
7734 case SMB_SET_FILE_UNIX_BASIC:
7736 status = smb_set_file_unix_basic(conn, req,
7744 case SMB_SET_FILE_UNIX_INFO2:
7746 status = smb_set_file_unix_info2(conn, req,
7754 case SMB_SET_FILE_UNIX_LINK:
7757 /* We must have a pathname for this. */
7758 return NT_STATUS_INVALID_LEVEL;
7760 status = smb_set_file_unix_link(conn, req, pdata,
7761 total_data, smb_fname);
7765 case SMB_SET_FILE_UNIX_HLINK:
7768 /* We must have a pathname for this. */
7769 return NT_STATUS_INVALID_LEVEL;
7771 status = smb_set_file_unix_hlink(conn, req,
7777 case SMB_FILE_RENAME_INFORMATION:
7779 status = smb_file_rename_information(conn, req,
7785 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7787 /* SMB2 rename information. */
7788 status = smb2_file_rename_information(conn, req,
7794 case SMB_FILE_LINK_INFORMATION:
7796 status = smb_file_link_information(conn, req,
7802 #if defined(HAVE_POSIX_ACLS)
7803 case SMB_SET_POSIX_ACL:
7805 status = smb_set_posix_acl(conn,
7814 case SMB_SET_POSIX_LOCK:
7817 return NT_STATUS_INVALID_LEVEL;
7819 status = smb_set_posix_lock(conn, req,
7820 pdata, total_data, fsp);
7824 case SMB_POSIX_PATH_OPEN:
7827 /* We must have a pathname for this. */
7828 return NT_STATUS_INVALID_LEVEL;
7831 status = smb_posix_open(conn, req,
7839 case SMB_POSIX_PATH_UNLINK:
7842 /* We must have a pathname for this. */
7843 return NT_STATUS_INVALID_LEVEL;
7846 status = smb_posix_unlink(conn, req,
7854 return NT_STATUS_INVALID_LEVEL;
7857 if (!NT_STATUS_IS_OK(status)) {
7861 *ret_data_size = data_return_size;
7862 return NT_STATUS_OK;
7865 /****************************************************************************
7866 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7867 ****************************************************************************/
7869 static void call_trans2setfilepathinfo(connection_struct *conn,
7870 struct smb_request *req,
7871 unsigned int tran_call,
7872 char **pparams, int total_params,
7873 char **ppdata, int total_data,
7874 unsigned int max_data_bytes)
7876 char *params = *pparams;
7877 char *pdata = *ppdata;
7879 struct smb_filename *smb_fname = NULL;
7880 files_struct *fsp = NULL;
7881 NTSTATUS status = NT_STATUS_OK;
7882 int data_return_size = 0;
7885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7889 if (tran_call == TRANSACT2_SETFILEINFO) {
7890 if (total_params < 4) {
7891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7895 fsp = file_fsp(req, SVAL(params,0));
7896 /* Basic check for non-null fsp. */
7897 if (!check_fsp_open(conn, req, fsp)) {
7900 info_level = SVAL(params,2);
7902 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7904 if (!NT_STATUS_IS_OK(status)) {
7905 reply_nterror(req, status);
7909 if(fsp->fh->fd == -1) {
7911 * This is actually a SETFILEINFO on a directory
7912 * handle (returned from an NT SMB). NT5.0 seems
7913 * to do this call. JRA.
7915 if (INFO_LEVEL_IS_UNIX(info_level)) {
7916 /* Always do lstat for UNIX calls. */
7917 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7918 DEBUG(3,("call_trans2setfilepathinfo: "
7919 "SMB_VFS_LSTAT of %s failed "
7921 smb_fname_str_dbg(smb_fname),
7923 reply_nterror(req, map_nt_error_from_unix(errno));
7927 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7928 DEBUG(3,("call_trans2setfilepathinfo: "
7929 "fileinfo of %s failed (%s)\n",
7930 smb_fname_str_dbg(smb_fname),
7932 reply_nterror(req, map_nt_error_from_unix(errno));
7936 } else if (fsp->print_file) {
7938 * Doing a DELETE_ON_CLOSE should cancel a print job.
7940 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7941 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7943 DEBUG(3,("call_trans2setfilepathinfo: "
7944 "Cancelling print job (%s)\n",
7948 send_trans2_replies(conn, req, params, 2,
7954 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7959 * Original code - this is an open file.
7961 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7962 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7963 "of fnum %d failed (%s)\n", fsp->fnum,
7965 reply_nterror(req, map_nt_error_from_unix(errno));
7973 if (total_params < 7) {
7974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7978 info_level = SVAL(params,0);
7979 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7980 total_params - 6, STR_TERMINATE,
7982 if (!NT_STATUS_IS_OK(status)) {
7983 reply_nterror(req, status);
7987 status = filename_convert(req, conn,
7988 req->flags2 & FLAGS2_DFS_PATHNAMES,
7993 if (!NT_STATUS_IS_OK(status)) {
7994 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7995 reply_botherror(req,
7996 NT_STATUS_PATH_NOT_COVERED,
7997 ERRSRV, ERRbadpath);
8000 reply_nterror(req, status);
8004 if (INFO_LEVEL_IS_UNIX(info_level)) {
8006 * For CIFS UNIX extensions the target name may not exist.
8009 /* Always do lstat for UNIX calls. */
8010 SMB_VFS_LSTAT(conn, smb_fname);
8012 } else if (!VALID_STAT(smb_fname->st) &&
8013 SMB_VFS_STAT(conn, smb_fname)) {
8014 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8016 smb_fname_str_dbg(smb_fname),
8018 reply_nterror(req, map_nt_error_from_unix(errno));
8023 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8024 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8025 fsp ? fsp->fnum : -1, info_level,total_data));
8027 /* Realloc the parameter size */
8028 *pparams = (char *)SMB_REALLOC(*pparams,2);
8029 if (*pparams == NULL) {
8030 reply_nterror(req, NT_STATUS_NO_MEMORY);
8037 status = smbd_do_setfilepathinfo(conn, req, req,
8043 if (!NT_STATUS_IS_OK(status)) {
8044 if (open_was_deferred(req->mid)) {
8045 /* We have re-scheduled this call. */
8048 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8049 /* We have re-scheduled this call. */
8052 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8053 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8054 ERRSRV, ERRbadpath);
8057 if (info_level == SMB_POSIX_PATH_OPEN) {
8058 reply_openerror(req, status);
8062 reply_nterror(req, status);
8066 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8072 /****************************************************************************
8073 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8074 ****************************************************************************/
8076 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8077 char **pparams, int total_params,
8078 char **ppdata, int total_data,
8079 unsigned int max_data_bytes)
8081 struct smb_filename *smb_dname = NULL;
8082 char *params = *pparams;
8083 char *pdata = *ppdata;
8084 char *directory = NULL;
8085 NTSTATUS status = NT_STATUS_OK;
8086 struct ea_list *ea_list = NULL;
8087 TALLOC_CTX *ctx = talloc_tos();
8089 if (!CAN_WRITE(conn)) {
8090 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8094 if (total_params < 5) {
8095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8099 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8100 total_params - 4, STR_TERMINATE,
8102 if (!NT_STATUS_IS_OK(status)) {
8103 reply_nterror(req, status);
8107 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8109 status = filename_convert(ctx,
8111 req->flags2 & FLAGS2_DFS_PATHNAMES,
8117 if (!NT_STATUS_IS_OK(status)) {
8118 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8119 reply_botherror(req,
8120 NT_STATUS_PATH_NOT_COVERED,
8121 ERRSRV, ERRbadpath);
8124 reply_nterror(req, status);
8129 * OS/2 workplace shell seems to send SET_EA requests of "null"
8130 * length (4 bytes containing IVAL 4).
8131 * They seem to have no effect. Bug #3212. JRA.
8134 if (total_data && (total_data != 4)) {
8135 /* Any data in this call is an EA list. */
8136 if (total_data < 10) {
8137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8141 if (IVAL(pdata,0) > total_data) {
8142 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8143 IVAL(pdata,0), (unsigned int)total_data));
8144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8148 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8155 if (!lp_ea_support(SNUM(conn))) {
8156 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8160 /* If total_data == 4 Windows doesn't care what values
8161 * are placed in that field, it just ignores them.
8162 * The System i QNTC IBM SMB client puts bad values here,
8163 * so ignore them. */
8165 status = create_directory(conn, req, smb_dname);
8167 if (!NT_STATUS_IS_OK(status)) {
8168 reply_nterror(req, status);
8172 /* Try and set any given EA. */
8174 status = set_ea(conn, NULL, smb_dname, ea_list);
8175 if (!NT_STATUS_IS_OK(status)) {
8176 reply_nterror(req, status);
8181 /* Realloc the parameter and data sizes */
8182 *pparams = (char *)SMB_REALLOC(*pparams,2);
8183 if(*pparams == NULL) {
8184 reply_nterror(req, NT_STATUS_NO_MEMORY);
8191 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8194 TALLOC_FREE(smb_dname);
8198 /****************************************************************************
8199 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8200 We don't actually do this - we just send a null response.
8201 ****************************************************************************/
8203 static void call_trans2findnotifyfirst(connection_struct *conn,
8204 struct smb_request *req,
8205 char **pparams, int total_params,
8206 char **ppdata, int total_data,
8207 unsigned int max_data_bytes)
8209 char *params = *pparams;
8212 if (total_params < 6) {
8213 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8217 info_level = SVAL(params,4);
8218 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8220 switch (info_level) {
8225 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8229 /* Realloc the parameter and data sizes */
8230 *pparams = (char *)SMB_REALLOC(*pparams,6);
8231 if (*pparams == NULL) {
8232 reply_nterror(req, NT_STATUS_NO_MEMORY);
8237 SSVAL(params,0,fnf_handle);
8238 SSVAL(params,2,0); /* No changes */
8239 SSVAL(params,4,0); /* No EA errors */
8246 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8251 /****************************************************************************
8252 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8253 changes). Currently this does nothing.
8254 ****************************************************************************/
8256 static void call_trans2findnotifynext(connection_struct *conn,
8257 struct smb_request *req,
8258 char **pparams, int total_params,
8259 char **ppdata, int total_data,
8260 unsigned int max_data_bytes)
8262 char *params = *pparams;
8264 DEBUG(3,("call_trans2findnotifynext\n"));
8266 /* Realloc the parameter and data sizes */
8267 *pparams = (char *)SMB_REALLOC(*pparams,4);
8268 if (*pparams == NULL) {
8269 reply_nterror(req, NT_STATUS_NO_MEMORY);
8274 SSVAL(params,0,0); /* No changes */
8275 SSVAL(params,2,0); /* No EA errors */
8277 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8282 /****************************************************************************
8283 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8284 ****************************************************************************/
8286 static void call_trans2getdfsreferral(connection_struct *conn,
8287 struct smb_request *req,
8288 char **pparams, int total_params,
8289 char **ppdata, int total_data,
8290 unsigned int max_data_bytes)
8292 char *params = *pparams;
8293 char *pathname = NULL;
8295 int max_referral_level;
8296 NTSTATUS status = NT_STATUS_OK;
8297 TALLOC_CTX *ctx = talloc_tos();
8299 DEBUG(10,("call_trans2getdfsreferral\n"));
8301 if (total_params < 3) {
8302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8306 max_referral_level = SVAL(params,0);
8308 if(!lp_host_msdfs()) {
8309 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8313 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8314 total_params - 2, STR_TERMINATE);
8316 reply_nterror(req, NT_STATUS_NOT_FOUND);
8319 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8320 ppdata,&status)) < 0) {
8321 reply_nterror(req, status);
8325 SSVAL(req->inbuf, smb_flg2,
8326 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8327 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8332 #define LMCAT_SPL 0x53
8333 #define LMFUNC_GETJOBID 0x60
8335 /****************************************************************************
8336 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8337 ****************************************************************************/
8339 static void call_trans2ioctl(connection_struct *conn,
8340 struct smb_request *req,
8341 char **pparams, int total_params,
8342 char **ppdata, int total_data,
8343 unsigned int max_data_bytes)
8345 char *pdata = *ppdata;
8346 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8348 /* check for an invalid fid before proceeding */
8351 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8355 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8356 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8357 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8358 if (*ppdata == NULL) {
8359 reply_nterror(req, NT_STATUS_NO_MEMORY);
8364 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8365 CAN ACCEPT THIS IN UNICODE. JRA. */
8368 if (fsp->print_file) {
8369 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8373 srvstr_push(pdata, req->flags2, pdata + 2,
8374 global_myname(), 15,
8375 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8376 srvstr_push(pdata, req->flags2, pdata+18,
8377 lp_servicename(SNUM(conn)), 13,
8378 STR_ASCII|STR_TERMINATE); /* Service name */
8379 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8384 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8385 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8388 /****************************************************************************
8389 Reply to a SMBfindclose (stop trans2 directory search).
8390 ****************************************************************************/
8392 void reply_findclose(struct smb_request *req)
8395 struct smbd_server_connection *sconn = req->sconn;
8397 START_PROFILE(SMBfindclose);
8400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8401 END_PROFILE(SMBfindclose);
8405 dptr_num = SVALS(req->vwv+0, 0);
8407 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8409 dptr_close(sconn, &dptr_num);
8411 reply_outbuf(req, 0, 0);
8413 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8415 END_PROFILE(SMBfindclose);
8419 /****************************************************************************
8420 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8421 ****************************************************************************/
8423 void reply_findnclose(struct smb_request *req)
8427 START_PROFILE(SMBfindnclose);
8430 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8431 END_PROFILE(SMBfindnclose);
8435 dptr_num = SVAL(req->vwv+0, 0);
8437 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8439 /* We never give out valid handles for a
8440 findnotifyfirst - so any dptr_num is ok here.
8443 reply_outbuf(req, 0, 0);
8445 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8447 END_PROFILE(SMBfindnclose);
8451 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8452 struct trans_state *state)
8454 if (get_Protocol() >= PROTOCOL_NT1) {
8455 req->flags2 |= 0x40; /* IS_LONG_NAME */
8456 SSVAL(req->inbuf,smb_flg2,req->flags2);
8459 if (conn->encrypt_level == Required && !req->encrypted) {
8460 if (state->call != TRANSACT2_QFSINFO &&
8461 state->call != TRANSACT2_SETFSINFO) {
8462 DEBUG(0,("handle_trans2: encryption required "
8464 (unsigned int)state->call));
8465 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8470 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8472 /* Now we must call the relevant TRANS2 function */
8473 switch(state->call) {
8474 case TRANSACT2_OPEN:
8476 START_PROFILE(Trans2_open);
8477 call_trans2open(conn, req,
8478 &state->param, state->total_param,
8479 &state->data, state->total_data,
8480 state->max_data_return);
8481 END_PROFILE(Trans2_open);
8485 case TRANSACT2_FINDFIRST:
8487 START_PROFILE(Trans2_findfirst);
8488 call_trans2findfirst(conn, req,
8489 &state->param, state->total_param,
8490 &state->data, state->total_data,
8491 state->max_data_return);
8492 END_PROFILE(Trans2_findfirst);
8496 case TRANSACT2_FINDNEXT:
8498 START_PROFILE(Trans2_findnext);
8499 call_trans2findnext(conn, req,
8500 &state->param, state->total_param,
8501 &state->data, state->total_data,
8502 state->max_data_return);
8503 END_PROFILE(Trans2_findnext);
8507 case TRANSACT2_QFSINFO:
8509 START_PROFILE(Trans2_qfsinfo);
8510 call_trans2qfsinfo(conn, req,
8511 &state->param, state->total_param,
8512 &state->data, state->total_data,
8513 state->max_data_return);
8514 END_PROFILE(Trans2_qfsinfo);
8518 case TRANSACT2_SETFSINFO:
8520 START_PROFILE(Trans2_setfsinfo);
8521 call_trans2setfsinfo(conn, req,
8522 &state->param, state->total_param,
8523 &state->data, state->total_data,
8524 state->max_data_return);
8525 END_PROFILE(Trans2_setfsinfo);
8529 case TRANSACT2_QPATHINFO:
8530 case TRANSACT2_QFILEINFO:
8532 START_PROFILE(Trans2_qpathinfo);
8533 call_trans2qfilepathinfo(conn, req, state->call,
8534 &state->param, state->total_param,
8535 &state->data, state->total_data,
8536 state->max_data_return);
8537 END_PROFILE(Trans2_qpathinfo);
8541 case TRANSACT2_SETPATHINFO:
8542 case TRANSACT2_SETFILEINFO:
8544 START_PROFILE(Trans2_setpathinfo);
8545 call_trans2setfilepathinfo(conn, req, state->call,
8546 &state->param, state->total_param,
8547 &state->data, state->total_data,
8548 state->max_data_return);
8549 END_PROFILE(Trans2_setpathinfo);
8553 case TRANSACT2_FINDNOTIFYFIRST:
8555 START_PROFILE(Trans2_findnotifyfirst);
8556 call_trans2findnotifyfirst(conn, req,
8557 &state->param, state->total_param,
8558 &state->data, state->total_data,
8559 state->max_data_return);
8560 END_PROFILE(Trans2_findnotifyfirst);
8564 case TRANSACT2_FINDNOTIFYNEXT:
8566 START_PROFILE(Trans2_findnotifynext);
8567 call_trans2findnotifynext(conn, req,
8568 &state->param, state->total_param,
8569 &state->data, state->total_data,
8570 state->max_data_return);
8571 END_PROFILE(Trans2_findnotifynext);
8575 case TRANSACT2_MKDIR:
8577 START_PROFILE(Trans2_mkdir);
8578 call_trans2mkdir(conn, req,
8579 &state->param, state->total_param,
8580 &state->data, state->total_data,
8581 state->max_data_return);
8582 END_PROFILE(Trans2_mkdir);
8586 case TRANSACT2_GET_DFS_REFERRAL:
8588 START_PROFILE(Trans2_get_dfs_referral);
8589 call_trans2getdfsreferral(conn, req,
8590 &state->param, state->total_param,
8591 &state->data, state->total_data,
8592 state->max_data_return);
8593 END_PROFILE(Trans2_get_dfs_referral);
8597 case TRANSACT2_IOCTL:
8599 START_PROFILE(Trans2_ioctl);
8600 call_trans2ioctl(conn, req,
8601 &state->param, state->total_param,
8602 &state->data, state->total_data,
8603 state->max_data_return);
8604 END_PROFILE(Trans2_ioctl);
8609 /* Error in request */
8610 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8611 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8615 /****************************************************************************
8616 Reply to a SMBtrans2.
8617 ****************************************************************************/
8619 void reply_trans2(struct smb_request *req)
8621 connection_struct *conn = req->conn;
8626 unsigned int tran_call;
8627 struct trans_state *state;
8630 START_PROFILE(SMBtrans2);
8632 if (req->wct < 14) {
8633 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8634 END_PROFILE(SMBtrans2);
8638 dsoff = SVAL(req->vwv+12, 0);
8639 dscnt = SVAL(req->vwv+11, 0);
8640 psoff = SVAL(req->vwv+10, 0);
8641 pscnt = SVAL(req->vwv+9, 0);
8642 tran_call = SVAL(req->vwv+14, 0);
8644 result = allow_new_trans(conn->pending_trans, req->mid);
8645 if (!NT_STATUS_IS_OK(result)) {
8646 DEBUG(2, ("Got invalid trans2 request: %s\n",
8647 nt_errstr(result)));
8648 reply_nterror(req, result);
8649 END_PROFILE(SMBtrans2);
8654 switch (tran_call) {
8655 /* List the allowed trans2 calls on IPC$ */
8656 case TRANSACT2_OPEN:
8657 case TRANSACT2_GET_DFS_REFERRAL:
8658 case TRANSACT2_QFILEINFO:
8659 case TRANSACT2_QFSINFO:
8660 case TRANSACT2_SETFSINFO:
8663 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8664 END_PROFILE(SMBtrans2);
8669 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8670 DEBUG(0, ("talloc failed\n"));
8671 reply_nterror(req, NT_STATUS_NO_MEMORY);
8672 END_PROFILE(SMBtrans2);
8676 state->cmd = SMBtrans2;
8678 state->mid = req->mid;
8679 state->vuid = req->vuid;
8680 state->setup_count = SVAL(req->vwv+13, 0);
8681 state->setup = NULL;
8682 state->total_param = SVAL(req->vwv+0, 0);
8683 state->param = NULL;
8684 state->total_data = SVAL(req->vwv+1, 0);
8686 state->max_param_return = SVAL(req->vwv+2, 0);
8687 state->max_data_return = SVAL(req->vwv+3, 0);
8688 state->max_setup_return = SVAL(req->vwv+4, 0);
8689 state->close_on_completion = BITSETW(req->vwv+5, 0);
8690 state->one_way = BITSETW(req->vwv+5, 1);
8692 state->call = tran_call;
8694 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8695 is so as a sanity check */
8696 if (state->setup_count != 1) {
8698 * Need to have rc=0 for ioctl to get job id for OS/2.
8699 * Network printing will fail if function is not successful.
8700 * Similar function in reply.c will be used if protocol
8701 * is LANMAN1.0 instead of LM1.2X002.
8702 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8703 * outbuf doesn't have to be set(only job id is used).
8705 if ( (state->setup_count == 4)
8706 && (tran_call == TRANSACT2_IOCTL)
8707 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8708 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8709 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8711 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8712 DEBUG(2,("Transaction is %d\n",tran_call));
8714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8715 END_PROFILE(SMBtrans2);
8720 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8723 if (state->total_data) {
8725 if (trans_oob(state->total_data, 0, dscnt)
8726 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8730 /* Can't use talloc here, the core routines do realloc on the
8731 * params and data. */
8732 state->data = (char *)SMB_MALLOC(state->total_data);
8733 if (state->data == NULL) {
8734 DEBUG(0,("reply_trans2: data malloc fail for %u "
8735 "bytes !\n", (unsigned int)state->total_data));
8737 reply_nterror(req, NT_STATUS_NO_MEMORY);
8738 END_PROFILE(SMBtrans2);
8742 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8745 if (state->total_param) {
8747 if (trans_oob(state->total_param, 0, pscnt)
8748 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8752 /* Can't use talloc here, the core routines do realloc on the
8753 * params and data. */
8754 state->param = (char *)SMB_MALLOC(state->total_param);
8755 if (state->param == NULL) {
8756 DEBUG(0,("reply_trans: param malloc fail for %u "
8757 "bytes !\n", (unsigned int)state->total_param));
8758 SAFE_FREE(state->data);
8760 reply_nterror(req, NT_STATUS_NO_MEMORY);
8761 END_PROFILE(SMBtrans2);
8765 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8768 state->received_data = dscnt;
8769 state->received_param = pscnt;
8771 if ((state->received_param == state->total_param) &&
8772 (state->received_data == state->total_data)) {
8774 handle_trans2(conn, req, state);
8776 SAFE_FREE(state->data);
8777 SAFE_FREE(state->param);
8779 END_PROFILE(SMBtrans2);
8783 DLIST_ADD(conn->pending_trans, state);
8785 /* We need to send an interim response then receive the rest
8786 of the parameter/data bytes */
8787 reply_outbuf(req, 0, 0);
8788 show_msg((char *)req->outbuf);
8789 END_PROFILE(SMBtrans2);
8794 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8795 SAFE_FREE(state->data);
8796 SAFE_FREE(state->param);
8798 END_PROFILE(SMBtrans2);
8799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8803 /****************************************************************************
8804 Reply to a SMBtranss2
8805 ****************************************************************************/
8807 void reply_transs2(struct smb_request *req)
8809 connection_struct *conn = req->conn;
8810 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8811 struct trans_state *state;
8813 START_PROFILE(SMBtranss2);
8815 show_msg((char *)req->inbuf);
8818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8819 END_PROFILE(SMBtranss2);
8823 for (state = conn->pending_trans; state != NULL;
8824 state = state->next) {
8825 if (state->mid == req->mid) {
8830 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8832 END_PROFILE(SMBtranss2);
8836 /* Revise state->total_param and state->total_data in case they have
8837 changed downwards */
8839 if (SVAL(req->vwv+0, 0) < state->total_param)
8840 state->total_param = SVAL(req->vwv+0, 0);
8841 if (SVAL(req->vwv+1, 0) < state->total_data)
8842 state->total_data = SVAL(req->vwv+1, 0);
8844 pcnt = SVAL(req->vwv+2, 0);
8845 poff = SVAL(req->vwv+3, 0);
8846 pdisp = SVAL(req->vwv+4, 0);
8848 dcnt = SVAL(req->vwv+5, 0);
8849 doff = SVAL(req->vwv+6, 0);
8850 ddisp = SVAL(req->vwv+7, 0);
8852 state->received_param += pcnt;
8853 state->received_data += dcnt;
8855 if ((state->received_data > state->total_data) ||
8856 (state->received_param > state->total_param))
8860 if (trans_oob(state->total_param, pdisp, pcnt)
8861 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8864 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8868 if (trans_oob(state->total_data, ddisp, dcnt)
8869 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8872 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8875 if ((state->received_param < state->total_param) ||
8876 (state->received_data < state->total_data)) {
8877 END_PROFILE(SMBtranss2);
8881 handle_trans2(conn, req, state);
8883 DLIST_REMOVE(conn->pending_trans, state);
8884 SAFE_FREE(state->data);
8885 SAFE_FREE(state->param);
8888 END_PROFILE(SMBtranss2);
8893 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8894 DLIST_REMOVE(conn->pending_trans, state);
8895 SAFE_FREE(state->data);
8896 SAFE_FREE(state->param);
8898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8899 END_PROFILE(SMBtranss2);