2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "../librpc/gen_ndr/xattr.h"
31 #include "../librpc/gen_ndr/ndr_security.h"
32 #include "libcli/security/security.h"
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct *conn,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
44 const SMB_STRUCT_STAT *psbuf);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
53 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type = get_remote_arch();
57 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58 val = SMB_ROUNDUP(val,rval);
63 /********************************************************************
64 Create a 64 bit FileIndex. If the file is on the same device as
65 the root of the share, just return the 64-bit inode. If it isn't,
66 mangle as we used to do.
67 ********************************************************************/
69 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
72 if (conn->base_share_dev == psbuf->st_ex_dev) {
73 return (uint64_t)psbuf->st_ex_ino;
75 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
76 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
80 /****************************************************************************
81 Utility functions for dealing with extended attributes.
82 ****************************************************************************/
84 /****************************************************************************
85 Refuse to allow clients to overwrite our private xattrs.
86 ****************************************************************************/
88 static bool samba_private_attr_name(const char *unix_ea_name)
90 static const char * const prohibited_ea_names[] = {
91 SAMBA_POSIX_INHERITANCE_EA_NAME,
92 SAMBA_XATTR_DOS_ATTRIB,
100 for (i = 0; prohibited_ea_names[i]; i++) {
101 if (strequal( prohibited_ea_names[i], unix_ea_name))
104 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
105 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
111 /****************************************************************************
112 Get one EA value. Fill in a struct ea_struct.
113 ****************************************************************************/
115 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
116 files_struct *fsp, const char *fname,
117 const char *ea_name, struct ea_struct *pea)
119 /* Get the value of this xattr. Max size is 64k. */
120 size_t attr_size = 256;
126 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
128 return NT_STATUS_NO_MEMORY;
131 if (fsp && fsp->fh->fd != -1) {
132 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
134 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
137 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
143 return map_nt_error_from_unix(errno);
146 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
147 dump_data(10, (uint8 *)val, sizeret);
150 if (strnequal(ea_name, "user.", 5)) {
151 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
153 pea->name = talloc_strdup(mem_ctx, ea_name);
155 if (pea->name == NULL) {
157 return NT_STATUS_NO_MEMORY;
159 pea->value.data = (unsigned char *)val;
160 pea->value.length = (size_t)sizeret;
164 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
165 files_struct *fsp, const char *fname,
166 char ***pnames, size_t *pnum_names)
168 /* Get a list of all xattrs. Max namesize is 64k. */
169 size_t ea_namelist_size = 1024;
170 char *ea_namelist = NULL;
175 ssize_t sizeret = -1;
177 if (!lp_ea_support(SNUM(conn))) {
186 * TALLOC the result early to get the talloc hierarchy right.
189 names = TALLOC_ARRAY(mem_ctx, char *, 1);
191 DEBUG(0, ("talloc failed\n"));
192 return NT_STATUS_NO_MEMORY;
195 while (ea_namelist_size <= 65536) {
197 ea_namelist = TALLOC_REALLOC_ARRAY(
198 names, ea_namelist, char, ea_namelist_size);
199 if (ea_namelist == NULL) {
200 DEBUG(0, ("talloc failed\n"));
202 return NT_STATUS_NO_MEMORY;
205 if (fsp && fsp->fh->fd != -1) {
206 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
209 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
213 if ((sizeret == -1) && (errno == ERANGE)) {
214 ea_namelist_size *= 2;
223 return map_nt_error_from_unix(errno);
226 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
227 (unsigned int)sizeret));
239 * Ensure the result is 0-terminated
242 if (ea_namelist[sizeret-1] != '\0') {
244 return NT_STATUS_INTERNAL_ERROR;
252 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
256 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
258 DEBUG(0, ("talloc failed\n"));
260 return NT_STATUS_NO_MEMORY;
266 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
267 names[num_names++] = p;
275 *pnum_names = num_names;
279 /****************************************************************************
280 Return a linked list of the total EA's. Plus the total size
281 ****************************************************************************/
283 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
284 const char *fname, size_t *pea_total_len)
286 /* Get a list of all xattrs. Max namesize is 64k. */
289 struct ea_list *ea_list_head = NULL;
294 if (!lp_ea_support(SNUM(conn))) {
298 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
301 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
305 for (i=0; i<num_names; i++) {
306 struct ea_list *listp;
309 if (strnequal(names[i], "system.", 7)
310 || samba_private_attr_name(names[i]))
313 listp = TALLOC_P(mem_ctx, struct ea_list);
318 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
324 push_ascii_fstring(dos_ea_name, listp->ea.name);
327 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
329 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
330 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
331 (unsigned int)listp->ea.value.length));
333 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
337 /* Add on 4 for total length. */
338 if (*pea_total_len) {
342 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
343 (unsigned int)*pea_total_len));
348 /****************************************************************************
349 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
351 ****************************************************************************/
353 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
354 connection_struct *conn, struct ea_list *ea_list)
356 unsigned int ret_data_size = 4;
359 SMB_ASSERT(total_data_size >= 4);
361 if (!lp_ea_support(SNUM(conn))) {
366 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
369 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
370 dos_namelen = strlen(dos_ea_name);
371 if (dos_namelen > 255 || dos_namelen == 0) {
374 if (ea_list->ea.value.length > 65535) {
377 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
381 /* We know we have room. */
382 SCVAL(p,0,ea_list->ea.flags);
383 SCVAL(p,1,dos_namelen);
384 SSVAL(p,2,ea_list->ea.value.length);
385 fstrcpy(p+4, dos_ea_name);
386 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
388 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
392 ret_data_size = PTR_DIFF(p, pdata);
393 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
394 SIVAL(pdata,0,ret_data_size);
395 return ret_data_size;
398 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
400 unsigned int total_data_size,
401 unsigned int *ret_data_size,
402 connection_struct *conn,
403 struct ea_list *ea_list)
405 uint8_t *p = (uint8_t *)pdata;
406 uint8_t *last_start = NULL;
410 if (!lp_ea_support(SNUM(conn))) {
411 return NT_STATUS_NO_EAS_ON_FILE;
414 for (; ea_list; ea_list = ea_list->next) {
420 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
424 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
425 dos_namelen = strlen(dos_ea_name);
426 if (dos_namelen > 255 || dos_namelen == 0) {
427 return NT_STATUS_INTERNAL_ERROR;
429 if (ea_list->ea.value.length > 65535) {
430 return NT_STATUS_INTERNAL_ERROR;
433 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
436 size_t pad = 4 - (this_size % 4);
440 if (this_size > total_data_size) {
441 return NT_STATUS_INFO_LENGTH_MISMATCH;
444 /* We know we have room. */
445 SIVAL(p, 0x00, 0); /* next offset */
446 SCVAL(p, 0x04, ea_list->ea.flags);
447 SCVAL(p, 0x05, dos_namelen);
448 SSVAL(p, 0x06, ea_list->ea.value.length);
449 fstrcpy((char *)(p+0x08), dos_ea_name);
450 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
452 total_data_size -= this_size;
456 *ret_data_size = PTR_DIFF(p, pdata);
457 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
461 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
463 size_t total_ea_len = 0;
464 TALLOC_CTX *mem_ctx = NULL;
466 if (!lp_ea_support(SNUM(conn))) {
469 mem_ctx = talloc_tos();
470 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
474 /****************************************************************************
475 Ensure the EA name is case insensitive by matching any existing EA name.
476 ****************************************************************************/
478 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
481 TALLOC_CTX *mem_ctx = talloc_tos();
482 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
484 for (; ea_list; ea_list = ea_list->next) {
485 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
486 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
487 &unix_ea_name[5], ea_list->ea.name));
488 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
494 /****************************************************************************
495 Set or delete an extended attribute.
496 ****************************************************************************/
498 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
499 const struct smb_filename *smb_fname, struct ea_list *ea_list)
503 if (!lp_ea_support(SNUM(conn))) {
504 return NT_STATUS_EAS_NOT_SUPPORTED;
507 /* For now setting EAs on streams isn't supported. */
508 fname = smb_fname->base_name;
510 for (;ea_list; ea_list = ea_list->next) {
512 fstring unix_ea_name;
514 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
515 fstrcat(unix_ea_name, ea_list->ea.name);
517 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
519 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
521 if (samba_private_attr_name(unix_ea_name)) {
522 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
523 return NT_STATUS_ACCESS_DENIED;
526 if (ea_list->ea.value.length == 0) {
527 /* Remove the attribute. */
528 if (fsp && (fsp->fh->fd != -1)) {
529 DEBUG(10,("set_ea: deleting ea name %s on "
530 "file %s by file descriptor.\n",
531 unix_ea_name, fsp_str_dbg(fsp)));
532 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
534 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
535 unix_ea_name, fname));
536 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
539 /* Removing a non existent attribute always succeeds. */
540 if (ret == -1 && errno == ENOATTR) {
541 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
547 if (fsp && (fsp->fh->fd != -1)) {
548 DEBUG(10,("set_ea: setting ea name %s on file "
549 "%s by file descriptor.\n",
550 unix_ea_name, fsp_str_dbg(fsp)));
551 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
552 ea_list->ea.value.data, ea_list->ea.value.length, 0);
554 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
555 unix_ea_name, fname));
556 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
557 ea_list->ea.value.data, ea_list->ea.value.length, 0);
563 if (errno == ENOTSUP) {
564 return NT_STATUS_EAS_NOT_SUPPORTED;
567 return map_nt_error_from_unix(errno);
573 /****************************************************************************
574 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
575 ****************************************************************************/
577 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
579 struct ea_list *ea_list_head = NULL;
580 size_t converted_size, offset = 0;
582 while (offset + 2 < data_size) {
583 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
584 unsigned int namelen = CVAL(pdata,offset);
586 offset++; /* Go past the namelen byte. */
588 /* integer wrap paranioa. */
589 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
590 (offset > data_size) || (namelen > data_size) ||
591 (offset + namelen >= data_size)) {
594 /* Ensure the name is null terminated. */
595 if (pdata[offset + namelen] != '\0') {
598 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
600 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
601 "failed: %s", strerror(errno)));
607 offset += (namelen + 1); /* Go past the name + terminating zero. */
608 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
609 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
615 /****************************************************************************
616 Read one EA list entry from the buffer.
617 ****************************************************************************/
619 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
621 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
623 unsigned int namelen;
624 size_t converted_size;
634 eal->ea.flags = CVAL(pdata,0);
635 namelen = CVAL(pdata,1);
636 val_len = SVAL(pdata,2);
638 if (4 + namelen + 1 + val_len > data_size) {
642 /* Ensure the name is null terminated. */
643 if (pdata[namelen + 4] != '\0') {
646 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
647 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
654 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
655 if (!eal->ea.value.data) {
659 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
661 /* Ensure we're null terminated just in case we print the value. */
662 eal->ea.value.data[val_len] = '\0';
663 /* But don't count the null. */
664 eal->ea.value.length--;
667 *pbytes_used = 4 + namelen + 1 + val_len;
670 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
671 dump_data(10, eal->ea.value.data, eal->ea.value.length);
676 /****************************************************************************
677 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
678 ****************************************************************************/
680 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
682 struct ea_list *ea_list_head = NULL;
684 size_t bytes_used = 0;
686 while (offset < data_size) {
687 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
693 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
694 offset += bytes_used;
700 /****************************************************************************
701 Count the total EA size needed.
702 ****************************************************************************/
704 static size_t ea_list_size(struct ea_list *ealist)
707 struct ea_list *listp;
710 for (listp = ealist; listp; listp = listp->next) {
711 push_ascii_fstring(dos_ea_name, listp->ea.name);
712 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
714 /* Add on 4 for total length. */
722 /****************************************************************************
723 Return a union of EA's from a file list and a list of names.
724 The TALLOC context for the two lists *MUST* be identical as we steal
725 memory from one list to add to another. JRA.
726 ****************************************************************************/
728 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
730 struct ea_list *nlistp, *flistp;
732 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
733 for (flistp = file_list; flistp; flistp = flistp->next) {
734 if (strequal(nlistp->ea.name, flistp->ea.name)) {
740 /* Copy the data from this entry. */
741 nlistp->ea.flags = flistp->ea.flags;
742 nlistp->ea.value = flistp->ea.value;
745 nlistp->ea.flags = 0;
746 ZERO_STRUCT(nlistp->ea.value);
750 *total_ea_len = ea_list_size(name_list);
754 /****************************************************************************
755 Send the required number of replies back.
756 We assume all fields other than the data fields are
757 set correctly for the type of call.
758 HACK ! Always assumes smb_setup field is zero.
759 ****************************************************************************/
761 void send_trans2_replies(connection_struct *conn,
762 struct smb_request *req,
769 /* As we are using a protocol > LANMAN1 then the max_send
770 variable must have been set in the sessetupX call.
771 This takes precedence over the max_xmit field in the
772 global struct. These different max_xmit variables should
773 be merged as this is now too confusing */
775 int data_to_send = datasize;
776 int params_to_send = paramsize;
778 const char *pp = params;
779 const char *pd = pdata;
780 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
781 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
782 int data_alignment_offset = 0;
783 bool overflow = False;
784 struct smbd_server_connection *sconn = req->sconn;
785 int max_send = sconn->smb1.sessions.max_send;
787 /* Modify the data_to_send and datasize and set the error if
788 we're trying to send more than max_data_bytes. We still send
789 the part of the packet(s) that fit. Strange, but needed
792 if (max_data_bytes > 0 && datasize > max_data_bytes) {
793 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
794 max_data_bytes, datasize ));
795 datasize = data_to_send = max_data_bytes;
799 /* If there genuinely are no parameters or data to send just send the empty packet */
801 if(params_to_send == 0 && data_to_send == 0) {
802 reply_outbuf(req, 10, 0);
803 show_msg((char *)req->outbuf);
804 if (!srv_send_smb(sconn,
807 IS_CONN_ENCRYPTED(conn),
809 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
811 TALLOC_FREE(req->outbuf);
815 /* When sending params and data ensure that both are nicely aligned */
816 /* Only do this alignment when there is also data to send - else
817 can cause NT redirector problems. */
819 if (((params_to_send % 4) != 0) && (data_to_send != 0))
820 data_alignment_offset = 4 - (params_to_send % 4);
822 /* Space is bufsize minus Netbios over TCP header minus SMB header */
823 /* The alignment_offset is to align the param bytes on an even byte
824 boundary. NT 4.0 Beta needs this to work correctly. */
826 useable_space = max_send - (smb_size
829 + data_alignment_offset);
831 if (useable_space < 0) {
832 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
833 "= %d!!!", useable_space));
834 exit_server_cleanly("send_trans2_replies: Not enough space");
837 while (params_to_send || data_to_send) {
838 /* Calculate whether we will totally or partially fill this packet */
840 total_sent_thistime = params_to_send + data_to_send;
842 /* We can never send more than useable_space */
844 * Note that 'useable_space' does not include the alignment offsets,
845 * but we must include the alignment offsets in the calculation of
846 * the length of the data we send over the wire, as the alignment offsets
847 * are sent here. Fix from Marc_Jacobsen@hp.com.
850 total_sent_thistime = MIN(total_sent_thistime, useable_space);
852 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
853 + data_alignment_offset);
856 * We might have SMBtrans2s in req which was transferred to
857 * the outbuf, fix that.
859 SCVAL(req->outbuf, smb_com, SMBtrans2);
861 /* Set total params and data to be sent */
862 SSVAL(req->outbuf,smb_tprcnt,paramsize);
863 SSVAL(req->outbuf,smb_tdrcnt,datasize);
865 /* Calculate how many parameters and data we can fit into
866 * this packet. Parameters get precedence
869 params_sent_thistime = MIN(params_to_send,useable_space);
870 data_sent_thistime = useable_space - params_sent_thistime;
871 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
873 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
875 /* smb_proff is the offset from the start of the SMB header to the
876 parameter bytes, however the first 4 bytes of outbuf are
877 the Netbios over TCP header. Thus use smb_base() to subtract
878 them from the calculation */
880 SSVAL(req->outbuf,smb_proff,
881 ((smb_buf(req->outbuf)+alignment_offset)
882 - smb_base(req->outbuf)));
884 if(params_sent_thistime == 0)
885 SSVAL(req->outbuf,smb_prdisp,0);
887 /* Absolute displacement of param bytes sent in this packet */
888 SSVAL(req->outbuf,smb_prdisp,pp - params);
890 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
891 if(data_sent_thistime == 0) {
892 SSVAL(req->outbuf,smb_droff,0);
893 SSVAL(req->outbuf,smb_drdisp, 0);
895 /* The offset of the data bytes is the offset of the
896 parameter bytes plus the number of parameters being sent this time */
897 SSVAL(req->outbuf, smb_droff,
898 ((smb_buf(req->outbuf)+alignment_offset)
899 - smb_base(req->outbuf))
900 + params_sent_thistime + data_alignment_offset);
901 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
904 /* Initialize the padding for alignment */
906 if (alignment_offset != 0) {
907 memset(smb_buf(req->outbuf), 0, alignment_offset);
910 /* Copy the param bytes into the packet */
912 if(params_sent_thistime) {
913 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
914 params_sent_thistime);
917 /* Copy in the data bytes */
918 if(data_sent_thistime) {
919 if (data_alignment_offset != 0) {
920 memset((smb_buf(req->outbuf)+alignment_offset+
921 params_sent_thistime), 0,
922 data_alignment_offset);
924 memcpy(smb_buf(req->outbuf)+alignment_offset
925 +params_sent_thistime+data_alignment_offset,
926 pd,data_sent_thistime);
929 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
930 params_sent_thistime, data_sent_thistime, useable_space));
931 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
932 params_to_send, data_to_send, paramsize, datasize));
935 error_packet_set((char *)req->outbuf,
936 ERRDOS,ERRbufferoverflow,
937 STATUS_BUFFER_OVERFLOW,
941 /* Send the packet */
942 show_msg((char *)req->outbuf);
943 if (!srv_send_smb(sconn,
946 IS_CONN_ENCRYPTED(conn),
948 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
950 TALLOC_FREE(req->outbuf);
952 pp += params_sent_thistime;
953 pd += data_sent_thistime;
955 params_to_send -= params_sent_thistime;
956 data_to_send -= data_sent_thistime;
959 if(params_to_send < 0 || data_to_send < 0) {
960 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
961 params_to_send, data_to_send));
969 /****************************************************************************
970 Reply to a TRANSACT2_OPEN.
971 ****************************************************************************/
973 static void call_trans2open(connection_struct *conn,
974 struct smb_request *req,
975 char **pparams, int total_params,
976 char **ppdata, int total_data,
977 unsigned int max_data_bytes)
979 struct smb_filename *smb_fname = NULL;
980 char *params = *pparams;
981 char *pdata = *ppdata;
986 bool return_additional_info;
999 struct ea_list *ea_list = NULL;
1004 uint32 create_disposition;
1005 uint32 create_options = 0;
1006 uint32_t private_flags = 0;
1007 TALLOC_CTX *ctx = talloc_tos();
1010 * Ensure we have enough parameters to perform the operation.
1013 if (total_params < 29) {
1014 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1018 flags = SVAL(params, 0);
1019 deny_mode = SVAL(params, 2);
1020 open_attr = SVAL(params,6);
1021 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1022 if (oplock_request) {
1023 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1027 return_additional_info = BITSETW(params,0);
1028 open_sattr = SVAL(params, 4);
1029 open_time = make_unix_date3(params+8);
1031 open_ofun = SVAL(params,12);
1032 open_size = IVAL(params,14);
1033 pname = ¶ms[28];
1036 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1040 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1041 total_params - 28, STR_TERMINATE,
1043 if (!NT_STATUS_IS_OK(status)) {
1044 reply_nterror(req, status);
1048 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1049 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1050 (unsigned int)open_ofun, open_size));
1052 status = filename_convert(ctx,
1054 req->flags2 & FLAGS2_DFS_PATHNAMES,
1059 if (!NT_STATUS_IS_OK(status)) {
1060 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1061 reply_botherror(req,
1062 NT_STATUS_PATH_NOT_COVERED,
1063 ERRSRV, ERRbadpath);
1066 reply_nterror(req, status);
1070 if (open_ofun == 0) {
1071 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1075 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1076 &access_mask, &share_mode,
1077 &create_disposition,
1080 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1084 /* Any data in this call is an EA list. */
1085 if (total_data && (total_data != 4)) {
1086 if (total_data < 10) {
1087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1091 if (IVAL(pdata,0) > total_data) {
1092 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1093 IVAL(pdata,0), (unsigned int)total_data));
1094 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1098 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1105 if (!lp_ea_support(SNUM(conn))) {
1106 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1111 status = SMB_VFS_CREATE_FILE(
1114 0, /* root_dir_fid */
1115 smb_fname, /* fname */
1116 access_mask, /* access_mask */
1117 share_mode, /* share_access */
1118 create_disposition, /* create_disposition*/
1119 create_options, /* create_options */
1120 open_attr, /* file_attributes */
1121 oplock_request, /* oplock_request */
1122 open_size, /* allocation_size */
1125 ea_list, /* ea_list */
1127 &smb_action); /* psbuf */
1129 if (!NT_STATUS_IS_OK(status)) {
1130 if (open_was_deferred(req->mid)) {
1131 /* We have re-scheduled this call. */
1134 reply_openerror(req, status);
1138 size = get_file_size_stat(&smb_fname->st);
1139 fattr = dos_mode(conn, smb_fname);
1140 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1141 inode = smb_fname->st.st_ex_ino;
1143 close_file(req, fsp, ERROR_CLOSE);
1144 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1148 /* Realloc the size of parameters and data we will return */
1149 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1150 if(*pparams == NULL ) {
1151 reply_nterror(req, NT_STATUS_NO_MEMORY);
1156 SSVAL(params,0,fsp->fnum);
1157 SSVAL(params,2,fattr);
1158 srv_put_dos_date2(params,4, mtime);
1159 SIVAL(params,8, (uint32)size);
1160 SSVAL(params,12,deny_mode);
1161 SSVAL(params,14,0); /* open_type - file or directory. */
1162 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1164 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1165 smb_action |= EXTENDED_OPLOCK_GRANTED;
1168 SSVAL(params,18,smb_action);
1171 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1173 SIVAL(params,20,inode);
1174 SSVAL(params,24,0); /* Padding. */
1176 uint32 ea_size = estimate_ea_size(conn, fsp,
1177 fsp->fsp_name->base_name);
1178 SIVAL(params, 26, ea_size);
1180 SIVAL(params, 26, 0);
1183 /* Send the required number of replies */
1184 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1186 TALLOC_FREE(smb_fname);
1189 /*********************************************************
1190 Routine to check if a given string matches exactly.
1191 as a special case a mask of "." does NOT match. That
1192 is required for correct wildcard semantics
1193 Case can be significant or not.
1194 **********************************************************/
1196 static bool exact_match(bool has_wild,
1197 bool case_sensitive,
1201 if (mask[0] == '.' && mask[1] == 0) {
1209 if (case_sensitive) {
1210 return strcmp(str,mask)==0;
1212 return StrCaseCmp(str,mask) == 0;
1216 /****************************************************************************
1217 Return the filetype for UNIX extensions.
1218 ****************************************************************************/
1220 static uint32 unix_filetype(mode_t mode)
1223 return UNIX_TYPE_FILE;
1224 else if(S_ISDIR(mode))
1225 return UNIX_TYPE_DIR;
1227 else if(S_ISLNK(mode))
1228 return UNIX_TYPE_SYMLINK;
1231 else if(S_ISCHR(mode))
1232 return UNIX_TYPE_CHARDEV;
1235 else if(S_ISBLK(mode))
1236 return UNIX_TYPE_BLKDEV;
1239 else if(S_ISFIFO(mode))
1240 return UNIX_TYPE_FIFO;
1243 else if(S_ISSOCK(mode))
1244 return UNIX_TYPE_SOCKET;
1247 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1248 return UNIX_TYPE_UNKNOWN;
1251 /****************************************************************************
1252 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1253 ****************************************************************************/
1255 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1257 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1258 const SMB_STRUCT_STAT *psbuf,
1260 enum perm_type ptype,
1265 if (perms == SMB_MODE_NO_CHANGE) {
1266 if (!VALID_STAT(*psbuf)) {
1267 return NT_STATUS_INVALID_PARAMETER;
1269 *ret_perms = psbuf->st_ex_mode;
1270 return NT_STATUS_OK;
1274 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1275 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1276 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1277 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1278 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1279 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1280 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1281 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1282 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1284 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1287 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1290 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1295 /* Apply mode mask */
1296 ret &= lp_create_mask(SNUM(conn));
1297 /* Add in force bits */
1298 ret |= lp_force_create_mode(SNUM(conn));
1301 ret &= lp_dir_mask(SNUM(conn));
1302 /* Add in force bits */
1303 ret |= lp_force_dir_mode(SNUM(conn));
1305 case PERM_EXISTING_FILE:
1306 /* Apply mode mask */
1307 ret &= lp_security_mask(SNUM(conn));
1308 /* Add in force bits */
1309 ret |= lp_force_security_mode(SNUM(conn));
1311 case PERM_EXISTING_DIR:
1312 /* Apply mode mask */
1313 ret &= lp_dir_security_mask(SNUM(conn));
1314 /* Add in force bits */
1315 ret |= lp_force_dir_security_mode(SNUM(conn));
1320 return NT_STATUS_OK;
1323 /****************************************************************************
1324 Needed to show the msdfs symlinks as directories. Modifies psbuf
1325 to be a directory if it's a msdfs link.
1326 ****************************************************************************/
1328 static bool check_msdfs_link(connection_struct *conn,
1329 const char *pathname,
1330 SMB_STRUCT_STAT *psbuf)
1332 int saved_errno = errno;
1333 if(lp_host_msdfs() &&
1334 lp_msdfs_root(SNUM(conn)) &&
1335 is_msdfs_link(conn, pathname, psbuf)) {
1337 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1340 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1341 errno = saved_errno;
1344 errno = saved_errno;
1349 /****************************************************************************
1350 Get a level dependent lanman2 dir entry.
1351 ****************************************************************************/
1353 struct smbd_dirptr_lanman2_state {
1354 connection_struct *conn;
1355 uint32_t info_level;
1356 bool check_mangled_names;
1358 bool got_exact_match;
1361 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1367 struct smbd_dirptr_lanman2_state *state =
1368 (struct smbd_dirptr_lanman2_state *)private_data;
1370 char mangled_name[13]; /* mangled 8.3 name. */
1374 /* Mangle fname if it's an illegal name. */
1375 if (mangle_must_mangle(dname, state->conn->params)) {
1376 ok = name_to_8_3(dname, mangled_name,
1377 true, state->conn->params);
1381 fname = mangled_name;
1386 got_match = exact_match(state->has_wild,
1387 state->conn->case_sensitive,
1389 state->got_exact_match = got_match;
1391 got_match = mask_match(fname, mask,
1392 state->conn->case_sensitive);
1395 if(!got_match && state->check_mangled_names &&
1396 !mangle_is_8_3(fname, false, state->conn->params)) {
1398 * It turns out that NT matches wildcards against
1399 * both long *and* short names. This may explain some
1400 * of the wildcard wierdness from old DOS clients
1401 * that some people have been seeing.... JRA.
1403 /* Force the mangling into 8.3. */
1404 ok = name_to_8_3(fname, mangled_name,
1405 false, state->conn->params);
1410 got_match = exact_match(state->has_wild,
1411 state->conn->case_sensitive,
1412 mangled_name, mask);
1413 state->got_exact_match = got_match;
1415 got_match = mask_match(mangled_name, mask,
1416 state->conn->case_sensitive);
1424 *_fname = talloc_strdup(ctx, fname);
1425 if (*_fname == NULL) {
1432 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1434 struct smb_filename *smb_fname,
1437 struct smbd_dirptr_lanman2_state *state =
1438 (struct smbd_dirptr_lanman2_state *)private_data;
1439 bool ms_dfs_link = false;
1442 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1443 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1444 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1445 "Couldn't lstat [%s] (%s)\n",
1446 smb_fname_str_dbg(smb_fname),
1450 } else if (!VALID_STAT(smb_fname->st) &&
1451 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1452 /* Needed to show the msdfs symlinks as
1455 ms_dfs_link = check_msdfs_link(state->conn,
1456 smb_fname->base_name,
1459 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1460 "Couldn't stat [%s] (%s)\n",
1461 smb_fname_str_dbg(smb_fname),
1468 mode = dos_mode_msdfs(state->conn, smb_fname);
1470 mode = dos_mode(state->conn, smb_fname);
1477 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1478 connection_struct *conn,
1480 uint32_t info_level,
1481 struct ea_list *name_list,
1482 bool check_mangled_names,
1483 bool requires_resume_key,
1486 const struct smb_filename *smb_fname,
1487 int space_remaining,
1494 uint64_t *last_entry_off)
1496 char *p, *q, *pdata = *ppdata;
1498 uint64_t file_size = 0;
1499 uint64_t allocation_size = 0;
1500 uint64_t file_index = 0;
1502 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1503 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1504 time_t c_date = (time_t)0;
1506 char *last_entry_ptr;
1511 *out_of_space = false;
1513 ZERO_STRUCT(mdate_ts);
1514 ZERO_STRUCT(adate_ts);
1515 ZERO_STRUCT(create_date_ts);
1516 ZERO_STRUCT(cdate_ts);
1518 if (!(mode & aDIR)) {
1519 file_size = get_file_size_stat(&smb_fname->st);
1521 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1523 file_index = get_FileIndex(conn, &smb_fname->st);
1525 mdate_ts = smb_fname->st.st_ex_mtime;
1526 adate_ts = smb_fname->st.st_ex_atime;
1527 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1528 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1530 if (lp_dos_filetime_resolution(SNUM(conn))) {
1531 dos_filetime_timespec(&create_date_ts);
1532 dos_filetime_timespec(&mdate_ts);
1533 dos_filetime_timespec(&adate_ts);
1534 dos_filetime_timespec(&cdate_ts);
1537 create_date = convert_timespec_to_time_t(create_date_ts);
1538 mdate = convert_timespec_to_time_t(mdate_ts);
1539 adate = convert_timespec_to_time_t(adate_ts);
1540 c_date = convert_timespec_to_time_t(cdate_ts);
1542 /* align the record */
1543 SMB_ASSERT(align >= 1);
1545 off = (int)PTR_DIFF(pdata, base_data);
1546 pad = (off + (align-1)) & ~(align-1);
1549 if (pad && pad > space_remaining) {
1550 *out_of_space = true;
1551 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1552 "for padding (wanted %u, had %d)\n",
1555 return false; /* Not finished - just out of space */
1559 /* initialize padding to 0 */
1561 memset(pdata, 0, pad);
1563 space_remaining -= pad;
1565 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1575 switch (info_level) {
1576 case SMB_FIND_INFO_STANDARD:
1577 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1578 if(requires_resume_key) {
1582 srv_put_dos_date2(p,0,create_date);
1583 srv_put_dos_date2(p,4,adate);
1584 srv_put_dos_date2(p,8,mdate);
1585 SIVAL(p,12,(uint32)file_size);
1586 SIVAL(p,16,(uint32)allocation_size);
1590 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1591 p += ucs2_align(base_data, p, 0);
1593 len = srvstr_push(base_data, flags2, p,
1594 fname, PTR_DIFF(end_data, p),
1596 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1598 SCVAL(nameptr, -1, len - 2);
1600 SCVAL(nameptr, -1, 0);
1604 SCVAL(nameptr, -1, len - 1);
1606 SCVAL(nameptr, -1, 0);
1612 case SMB_FIND_EA_SIZE:
1613 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1614 if (requires_resume_key) {
1618 srv_put_dos_date2(p,0,create_date);
1619 srv_put_dos_date2(p,4,adate);
1620 srv_put_dos_date2(p,8,mdate);
1621 SIVAL(p,12,(uint32)file_size);
1622 SIVAL(p,16,(uint32)allocation_size);
1625 unsigned int ea_size = estimate_ea_size(conn, NULL,
1626 smb_fname->base_name);
1627 SIVAL(p,22,ea_size); /* Extended attributes */
1631 len = srvstr_push(base_data, flags2,
1632 p, fname, PTR_DIFF(end_data, p),
1633 STR_TERMINATE | STR_NOALIGN);
1634 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1647 SCVAL(nameptr,0,len);
1649 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1652 case SMB_FIND_EA_LIST:
1654 struct ea_list *file_list = NULL;
1657 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1661 if (requires_resume_key) {
1665 srv_put_dos_date2(p,0,create_date);
1666 srv_put_dos_date2(p,4,adate);
1667 srv_put_dos_date2(p,8,mdate);
1668 SIVAL(p,12,(uint32)file_size);
1669 SIVAL(p,16,(uint32)allocation_size);
1671 p += 22; /* p now points to the EA area. */
1673 file_list = get_ea_list_from_file(ctx, conn, NULL,
1674 smb_fname->base_name,
1676 name_list = ea_list_union(name_list, file_list, &ea_len);
1678 /* We need to determine if this entry will fit in the space available. */
1679 /* Max string size is 255 bytes. */
1680 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1681 *out_of_space = true;
1682 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1683 "(wanted %u, had %d)\n",
1684 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1686 return False; /* Not finished - just out of space */
1689 /* Push the ea_data followed by the name. */
1690 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1692 len = srvstr_push(base_data, flags2,
1693 p + 1, fname, PTR_DIFF(end_data, p+1),
1694 STR_TERMINATE | STR_NOALIGN);
1695 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1708 SCVAL(nameptr,0,len);
1710 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1714 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1715 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1716 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1718 SIVAL(p,0,reskey); p += 4;
1719 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1720 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1721 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1722 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1723 SOFF_T(p,0,file_size); p += 8;
1724 SOFF_T(p,0,allocation_size); p += 8;
1725 SIVAL(p,0,mode); p += 4;
1726 q = p; p += 4; /* q is placeholder for name length. */
1728 unsigned int ea_size = estimate_ea_size(conn, NULL,
1729 smb_fname->base_name);
1730 SIVAL(p,0,ea_size); /* Extended attributes */
1733 /* Clear the short name buffer. This is
1734 * IMPORTANT as not doing so will trigger
1735 * a Win2k client bug. JRA.
1737 if (!was_8_3 && check_mangled_names) {
1738 char mangled_name[13]; /* mangled 8.3 name. */
1739 if (!name_to_8_3(fname,mangled_name,True,
1741 /* Error - mangle failed ! */
1742 memset(mangled_name,'\0',12);
1744 mangled_name[12] = 0;
1745 len = srvstr_push(base_data, flags2,
1746 p+2, mangled_name, 24,
1747 STR_UPPER|STR_UNICODE);
1749 memset(p + 2 + len,'\0',24 - len);
1756 len = srvstr_push(base_data, flags2, p,
1757 fname, PTR_DIFF(end_data, p),
1758 STR_TERMINATE_ASCII);
1762 len = PTR_DIFF(p, pdata);
1763 pad = (len + (align-1)) & ~(align-1);
1765 * offset to the next entry, the caller
1766 * will overwrite it for the last entry
1767 * that's why we always include the padding
1771 * set padding to zero
1774 memset(p, 0, pad - len);
1781 case SMB_FIND_FILE_DIRECTORY_INFO:
1782 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1784 SIVAL(p,0,reskey); p += 4;
1785 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1787 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1788 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1789 SOFF_T(p,0,file_size); p += 8;
1790 SOFF_T(p,0,allocation_size); p += 8;
1791 SIVAL(p,0,mode); p += 4;
1792 len = srvstr_push(base_data, flags2,
1793 p + 4, fname, PTR_DIFF(end_data, p+4),
1794 STR_TERMINATE_ASCII);
1798 len = PTR_DIFF(p, pdata);
1799 pad = (len + (align-1)) & ~(align-1);
1801 * offset to the next entry, the caller
1802 * will overwrite it for the last entry
1803 * that's why we always include the padding
1807 * set padding to zero
1810 memset(p, 0, pad - len);
1817 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1818 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1820 SIVAL(p,0,reskey); p += 4;
1821 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1822 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1823 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1824 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1825 SOFF_T(p,0,file_size); p += 8;
1826 SOFF_T(p,0,allocation_size); p += 8;
1827 SIVAL(p,0,mode); p += 4;
1828 q = p; p += 4; /* q is placeholder for name length. */
1830 unsigned int ea_size = estimate_ea_size(conn, NULL,
1831 smb_fname->base_name);
1832 SIVAL(p,0,ea_size); /* Extended attributes */
1835 len = srvstr_push(base_data, flags2, p,
1836 fname, PTR_DIFF(end_data, p),
1837 STR_TERMINATE_ASCII);
1841 len = PTR_DIFF(p, pdata);
1842 pad = (len + (align-1)) & ~(align-1);
1844 * offset to the next entry, the caller
1845 * will overwrite it for the last entry
1846 * that's why we always include the padding
1850 * set padding to zero
1853 memset(p, 0, pad - len);
1860 case SMB_FIND_FILE_NAMES_INFO:
1861 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1863 SIVAL(p,0,reskey); p += 4;
1865 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1866 acl on a dir (tridge) */
1867 len = srvstr_push(base_data, flags2, p,
1868 fname, PTR_DIFF(end_data, p),
1869 STR_TERMINATE_ASCII);
1873 len = PTR_DIFF(p, pdata);
1874 pad = (len + (align-1)) & ~(align-1);
1876 * offset to the next entry, the caller
1877 * will overwrite it for the last entry
1878 * that's why we always include the padding
1882 * set padding to zero
1885 memset(p, 0, pad - len);
1892 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1893 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1895 SIVAL(p,0,reskey); p += 4;
1896 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1897 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1898 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1899 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1900 SOFF_T(p,0,file_size); p += 8;
1901 SOFF_T(p,0,allocation_size); p += 8;
1902 SIVAL(p,0,mode); p += 4;
1903 q = p; p += 4; /* q is placeholder for name length. */
1905 unsigned int ea_size = estimate_ea_size(conn, NULL,
1906 smb_fname->base_name);
1907 SIVAL(p,0,ea_size); /* Extended attributes */
1910 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1911 SBVAL(p,0,file_index); p += 8;
1912 len = srvstr_push(base_data, flags2, p,
1913 fname, PTR_DIFF(end_data, p),
1914 STR_TERMINATE_ASCII);
1918 len = PTR_DIFF(p, pdata);
1919 pad = (len + (align-1)) & ~(align-1);
1921 * offset to the next entry, the caller
1922 * will overwrite it for the last entry
1923 * that's why we always include the padding
1927 * set padding to zero
1930 memset(p, 0, pad - len);
1937 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1938 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1939 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1941 SIVAL(p,0,reskey); p += 4;
1942 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1943 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1944 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1945 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1946 SOFF_T(p,0,file_size); p += 8;
1947 SOFF_T(p,0,allocation_size); p += 8;
1948 SIVAL(p,0,mode); p += 4;
1949 q = p; p += 4; /* q is placeholder for name length */
1951 unsigned int ea_size = estimate_ea_size(conn, NULL,
1952 smb_fname->base_name);
1953 SIVAL(p,0,ea_size); /* Extended attributes */
1956 /* Clear the short name buffer. This is
1957 * IMPORTANT as not doing so will trigger
1958 * a Win2k client bug. JRA.
1960 if (!was_8_3 && check_mangled_names) {
1961 char mangled_name[13]; /* mangled 8.3 name. */
1962 if (!name_to_8_3(fname,mangled_name,True,
1964 /* Error - mangle failed ! */
1965 memset(mangled_name,'\0',12);
1967 mangled_name[12] = 0;
1968 len = srvstr_push(base_data, flags2,
1969 p+2, mangled_name, 24,
1970 STR_UPPER|STR_UNICODE);
1973 memset(p + 2 + len,'\0',24 - len);
1980 SSVAL(p,0,0); p += 2; /* Reserved ? */
1981 SBVAL(p,0,file_index); p += 8;
1982 len = srvstr_push(base_data, flags2, p,
1983 fname, PTR_DIFF(end_data, p),
1984 STR_TERMINATE_ASCII);
1988 len = PTR_DIFF(p, pdata);
1989 pad = (len + (align-1)) & ~(align-1);
1991 * offset to the next entry, the caller
1992 * will overwrite it for the last entry
1993 * that's why we always include the padding
1997 * set padding to zero
2000 memset(p, 0, pad - len);
2007 /* CIFS UNIX Extension. */
2009 case SMB_FIND_FILE_UNIX:
2010 case SMB_FIND_FILE_UNIX_INFO2:
2012 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2014 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2016 if (info_level == SMB_FIND_FILE_UNIX) {
2017 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2018 p = store_file_unix_basic(conn, p,
2019 NULL, &smb_fname->st);
2020 len = srvstr_push(base_data, flags2, p,
2021 fname, PTR_DIFF(end_data, p),
2024 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2025 p = store_file_unix_basic_info2(conn, p,
2026 NULL, &smb_fname->st);
2029 len = srvstr_push(base_data, flags2, p, fname,
2030 PTR_DIFF(end_data, p), 0);
2031 SIVAL(nameptr, 0, len);
2036 len = PTR_DIFF(p, pdata);
2037 pad = (len + (align-1)) & ~(align-1);
2039 * offset to the next entry, the caller
2040 * will overwrite it for the last entry
2041 * that's why we always include the padding
2045 * set padding to zero
2048 memset(p, 0, pad - len);
2053 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2061 if (PTR_DIFF(p,pdata) > space_remaining) {
2062 *out_of_space = true;
2063 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2064 "(wanted %u, had %d)\n",
2065 (unsigned int)PTR_DIFF(p,pdata),
2067 return false; /* Not finished - just out of space */
2070 /* Setup the last entry pointer, as an offset from base_data */
2071 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2072 /* Advance the data pointer to the next slot */
2078 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2079 connection_struct *conn,
2080 struct dptr_struct *dirptr,
2082 const char *path_mask,
2085 int requires_resume_key,
2093 int space_remaining,
2095 bool *got_exact_match,
2096 int *_last_entry_off,
2097 struct ea_list *name_list)
2100 const char *mask = NULL;
2101 long prev_dirpos = 0;
2104 struct smb_filename *smb_fname = NULL;
2105 struct smbd_dirptr_lanman2_state state;
2107 uint64_t last_entry_off = 0;
2111 state.info_level = info_level;
2112 state.check_mangled_names = lp_manglednames(conn->params);
2113 state.has_wild = dptr_has_wild(dirptr);
2114 state.got_exact_match = false;
2116 *out_of_space = false;
2117 *got_exact_match = false;
2119 p = strrchr_m(path_mask,'/');
2130 ok = smbd_dirptr_get_entry(ctx,
2136 smbd_dirptr_lanman2_match_fn,
2137 smbd_dirptr_lanman2_mode_fn,
2147 *got_exact_match = state.got_exact_match;
2149 ok = smbd_marshall_dir_entry(ctx,
2154 state.check_mangled_names,
2155 requires_resume_key,
2168 TALLOC_FREE(smb_fname);
2169 if (*out_of_space) {
2170 dptr_SeekDir(dirptr, prev_dirpos);
2177 *_last_entry_off = last_entry_off;
2181 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2182 connection_struct *conn,
2183 struct dptr_struct *dirptr,
2185 const char *path_mask,
2188 bool requires_resume_key,
2194 int space_remaining,
2196 bool *got_exact_match,
2197 int *last_entry_off,
2198 struct ea_list *name_list)
2201 const bool do_pad = true;
2203 if (info_level >= 1 && info_level <= 3) {
2204 /* No alignment on earlier info levels. */
2208 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2209 path_mask, dirtype, info_level,
2210 requires_resume_key, dont_descend, ask_sharemode,
2212 ppdata, base_data, end_data,
2214 out_of_space, got_exact_match,
2215 last_entry_off, name_list);
2218 /****************************************************************************
2219 Reply to a TRANS2_FINDFIRST.
2220 ****************************************************************************/
2222 static void call_trans2findfirst(connection_struct *conn,
2223 struct smb_request *req,
2224 char **pparams, int total_params,
2225 char **ppdata, int total_data,
2226 unsigned int max_data_bytes)
2228 /* We must be careful here that we don't return more than the
2229 allowed number of data bytes. If this means returning fewer than
2230 maxentries then so be it. We assume that the redirector has
2231 enough room for the fixed number of parameter bytes it has
2233 struct smb_filename *smb_dname = NULL;
2234 char *params = *pparams;
2235 char *pdata = *ppdata;
2239 uint16 findfirst_flags;
2240 bool close_after_first;
2242 bool requires_resume_key;
2244 char *directory = NULL;
2247 int last_entry_off=0;
2251 bool finished = False;
2252 bool dont_descend = False;
2253 bool out_of_space = False;
2254 int space_remaining;
2255 bool mask_contains_wcard = False;
2256 struct ea_list *ea_list = NULL;
2257 NTSTATUS ntstatus = NT_STATUS_OK;
2258 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2259 TALLOC_CTX *ctx = talloc_tos();
2260 struct dptr_struct *dirptr = NULL;
2261 struct smbd_server_connection *sconn = req->sconn;
2263 if (total_params < 13) {
2264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2268 dirtype = SVAL(params,0);
2269 maxentries = SVAL(params,2);
2270 findfirst_flags = SVAL(params,4);
2271 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2272 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2273 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2274 info_level = SVAL(params,6);
2276 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2277 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2278 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2279 info_level, max_data_bytes));
2282 /* W2K3 seems to treat zero as 1. */
2286 switch (info_level) {
2287 case SMB_FIND_INFO_STANDARD:
2288 case SMB_FIND_EA_SIZE:
2289 case SMB_FIND_EA_LIST:
2290 case SMB_FIND_FILE_DIRECTORY_INFO:
2291 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2292 case SMB_FIND_FILE_NAMES_INFO:
2293 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2294 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2295 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2297 case SMB_FIND_FILE_UNIX:
2298 case SMB_FIND_FILE_UNIX_INFO2:
2299 /* Always use filesystem for UNIX mtime query. */
2300 ask_sharemode = false;
2301 if (!lp_unix_extensions()) {
2302 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2307 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2311 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2312 params+12, total_params - 12,
2313 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2314 if (!NT_STATUS_IS_OK(ntstatus)) {
2315 reply_nterror(req, ntstatus);
2319 ntstatus = filename_convert(ctx, conn,
2320 req->flags2 & FLAGS2_DFS_PATHNAMES,
2323 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2324 &mask_contains_wcard,
2326 if (!NT_STATUS_IS_OK(ntstatus)) {
2327 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2328 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2329 ERRSRV, ERRbadpath);
2332 reply_nterror(req, ntstatus);
2336 mask = smb_dname->original_lcomp;
2338 directory = smb_dname->base_name;
2340 p = strrchr_m(directory,'/');
2342 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2343 if((directory[0] == '.') && (directory[1] == '\0')) {
2344 mask = talloc_strdup(ctx,"*");
2346 reply_nterror(req, NT_STATUS_NO_MEMORY);
2349 mask_contains_wcard = True;
2351 directory = talloc_strdup(talloc_tos(), "./");
2353 reply_nterror(req, NT_STATUS_NO_MEMORY);
2360 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2362 if (info_level == SMB_FIND_EA_LIST) {
2365 if (total_data < 4) {
2366 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2370 ea_size = IVAL(pdata,0);
2371 if (ea_size != total_data) {
2372 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2373 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2378 if (!lp_ea_support(SNUM(conn))) {
2379 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2383 /* Pull out the list of names. */
2384 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2391 *ppdata = (char *)SMB_REALLOC(
2392 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2393 if(*ppdata == NULL ) {
2394 reply_nterror(req, NT_STATUS_NO_MEMORY);
2398 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2400 /* Realloc the params space */
2401 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2402 if (*pparams == NULL) {
2403 reply_nterror(req, NT_STATUS_NO_MEMORY);
2408 /* Save the wildcard match and attribs we are using on this directory -
2409 needed as lanman2 assumes these are being saved between calls */
2411 ntstatus = dptr_create(conn,
2417 mask_contains_wcard,
2421 if (!NT_STATUS_IS_OK(ntstatus)) {
2422 reply_nterror(req, ntstatus);
2426 dptr_num = dptr_dnum(dirptr);
2427 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2429 /* Initialize per TRANS2_FIND_FIRST operation data */
2430 dptr_init_search_op(dirptr);
2432 /* We don't need to check for VOL here as this is returned by
2433 a different TRANS2 call. */
2435 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2436 directory,lp_dontdescend(SNUM(conn))));
2437 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2438 dont_descend = True;
2441 space_remaining = max_data_bytes;
2442 out_of_space = False;
2444 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2445 bool got_exact_match = False;
2447 /* this is a heuristic to avoid seeking the dirptr except when
2448 absolutely necessary. It allows for a filename of about 40 chars */
2449 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2450 out_of_space = True;
2453 finished = !get_lanman2_dir_entry(ctx,
2457 mask,dirtype,info_level,
2458 requires_resume_key,dont_descend,
2461 space_remaining, &out_of_space,
2463 &last_entry_off, ea_list);
2466 if (finished && out_of_space)
2469 if (!finished && !out_of_space)
2473 * As an optimisation if we know we aren't looking
2474 * for a wildcard name (ie. the name matches the wildcard exactly)
2475 * then we can finish on any (first) match.
2476 * This speeds up large directory searches. JRA.
2482 /* Ensure space_remaining never goes -ve. */
2483 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2484 space_remaining = 0;
2485 out_of_space = true;
2487 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2491 /* Check if we can close the dirptr */
2492 if(close_after_first || (finished && close_if_end)) {
2493 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2494 dptr_close(sconn, &dptr_num);
2498 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2499 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2500 * the protocol level is less than NT1. Tested with smbclient. JRA.
2501 * This should fix the OS/2 client bug #2335.
2504 if(numentries == 0) {
2505 dptr_close(sconn, &dptr_num);
2506 if (get_Protocol() < PROTOCOL_NT1) {
2507 reply_force_doserror(req, ERRDOS, ERRnofiles);
2510 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2511 ERRDOS, ERRbadfile);
2516 /* At this point pdata points to numentries directory entries. */
2518 /* Set up the return parameter block */
2519 SSVAL(params,0,dptr_num);
2520 SSVAL(params,2,numentries);
2521 SSVAL(params,4,finished);
2522 SSVAL(params,6,0); /* Never an EA error */
2523 SSVAL(params,8,last_entry_off);
2525 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2528 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2529 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2531 reply_nterror(req, NT_STATUS_NO_MEMORY);
2535 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2536 smb_fn_name(req->cmd),
2537 mask, directory, dirtype, numentries ) );
2540 * Force a name mangle here to ensure that the
2541 * mask as an 8.3 name is top of the mangled cache.
2542 * The reasons for this are subtle. Don't remove
2543 * this code unless you know what you are doing
2544 * (see PR#13758). JRA.
2547 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2548 char mangled_name[13];
2549 name_to_8_3(mask, mangled_name, True, conn->params);
2552 TALLOC_FREE(smb_dname);
2556 /****************************************************************************
2557 Reply to a TRANS2_FINDNEXT.
2558 ****************************************************************************/
2560 static void call_trans2findnext(connection_struct *conn,
2561 struct smb_request *req,
2562 char **pparams, int total_params,
2563 char **ppdata, int total_data,
2564 unsigned int max_data_bytes)
2566 /* We must be careful here that we don't return more than the
2567 allowed number of data bytes. If this means returning fewer than
2568 maxentries then so be it. We assume that the redirector has
2569 enough room for the fixed number of parameter bytes it has
2571 char *params = *pparams;
2572 char *pdata = *ppdata;
2578 uint16 findnext_flags;
2579 bool close_after_request;
2581 bool requires_resume_key;
2583 bool mask_contains_wcard = False;
2584 char *resume_name = NULL;
2585 const char *mask = NULL;
2586 const char *directory = NULL;
2590 int i, last_entry_off=0;
2591 bool finished = False;
2592 bool dont_descend = False;
2593 bool out_of_space = False;
2594 int space_remaining;
2595 struct ea_list *ea_list = NULL;
2596 NTSTATUS ntstatus = NT_STATUS_OK;
2597 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2598 TALLOC_CTX *ctx = talloc_tos();
2599 struct dptr_struct *dirptr;
2600 struct smbd_server_connection *sconn = req->sconn;
2602 if (total_params < 13) {
2603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2607 dptr_num = SVAL(params,0);
2608 maxentries = SVAL(params,2);
2609 info_level = SVAL(params,4);
2610 resume_key = IVAL(params,6);
2611 findnext_flags = SVAL(params,10);
2612 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2613 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2614 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2615 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2617 if (!continue_bit) {
2618 /* We only need resume_name if continue_bit is zero. */
2619 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2621 total_params - 12, STR_TERMINATE, &ntstatus,
2622 &mask_contains_wcard);
2623 if (!NT_STATUS_IS_OK(ntstatus)) {
2624 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2625 complain (it thinks we're asking for the directory above the shared
2626 path or an invalid name). Catch this as the resume name is only compared, never used in
2627 a file access. JRA. */
2628 srvstr_pull_talloc(ctx, params, req->flags2,
2629 &resume_name, params+12,
2633 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2634 reply_nterror(req, ntstatus);
2640 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2641 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2642 resume_key = %d resume name = %s continue=%d level = %d\n",
2643 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2644 requires_resume_key, resume_key,
2645 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2648 /* W2K3 seems to treat zero as 1. */
2652 switch (info_level) {
2653 case SMB_FIND_INFO_STANDARD:
2654 case SMB_FIND_EA_SIZE:
2655 case SMB_FIND_EA_LIST:
2656 case SMB_FIND_FILE_DIRECTORY_INFO:
2657 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2658 case SMB_FIND_FILE_NAMES_INFO:
2659 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2660 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2661 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2663 case SMB_FIND_FILE_UNIX:
2664 case SMB_FIND_FILE_UNIX_INFO2:
2665 /* Always use filesystem for UNIX mtime query. */
2666 ask_sharemode = false;
2667 if (!lp_unix_extensions()) {
2668 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2673 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2677 if (info_level == SMB_FIND_EA_LIST) {
2680 if (total_data < 4) {
2681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2685 ea_size = IVAL(pdata,0);
2686 if (ea_size != total_data) {
2687 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2688 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2693 if (!lp_ea_support(SNUM(conn))) {
2694 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2698 /* Pull out the list of names. */
2699 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2706 *ppdata = (char *)SMB_REALLOC(
2707 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2708 if(*ppdata == NULL) {
2709 reply_nterror(req, NT_STATUS_NO_MEMORY);
2714 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2716 /* Realloc the params space */
2717 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2718 if(*pparams == NULL ) {
2719 reply_nterror(req, NT_STATUS_NO_MEMORY);
2725 /* Check that the dptr is valid */
2726 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2727 reply_nterror(req, STATUS_NO_MORE_FILES);
2731 directory = dptr_path(sconn, dptr_num);
2733 /* Get the wildcard mask from the dptr */
2734 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2735 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2736 reply_nterror(req, STATUS_NO_MORE_FILES);
2742 /* Get the attr mask from the dptr */
2743 dirtype = dptr_attr(sconn, dptr_num);
2745 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2746 dptr_num, mask, dirtype,
2748 dptr_TellDir(dirptr)));
2750 /* Initialize per TRANS2_FIND_NEXT operation data */
2751 dptr_init_search_op(dirptr);
2753 /* We don't need to check for VOL here as this is returned by
2754 a different TRANS2 call. */
2756 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2757 directory,lp_dontdescend(SNUM(conn))));
2758 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2759 dont_descend = True;
2762 space_remaining = max_data_bytes;
2763 out_of_space = False;
2766 * Seek to the correct position. We no longer use the resume key but
2767 * depend on the last file name instead.
2770 if(!continue_bit && resume_name && *resume_name) {
2773 long current_pos = 0;
2775 * Remember, name_to_8_3 is called by
2776 * get_lanman2_dir_entry(), so the resume name
2777 * could be mangled. Ensure we check the unmangled name.
2780 if (mangle_is_mangled(resume_name, conn->params)) {
2781 char *new_resume_name = NULL;
2782 mangle_lookup_name_from_8_3(ctx,
2786 if (new_resume_name) {
2787 resume_name = new_resume_name;
2792 * Fix for NT redirector problem triggered by resume key indexes
2793 * changing between directory scans. We now return a resume key of 0
2794 * and instead look for the filename to continue from (also given
2795 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2796 * findfirst/findnext (as is usual) then the directory pointer
2797 * should already be at the correct place.
2800 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2801 } /* end if resume_name && !continue_bit */
2803 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2804 bool got_exact_match = False;
2806 /* this is a heuristic to avoid seeking the dirptr except when
2807 absolutely necessary. It allows for a filename of about 40 chars */
2808 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2809 out_of_space = True;
2812 finished = !get_lanman2_dir_entry(ctx,
2816 mask,dirtype,info_level,
2817 requires_resume_key,dont_descend,
2820 space_remaining, &out_of_space,
2822 &last_entry_off, ea_list);
2825 if (finished && out_of_space)
2828 if (!finished && !out_of_space)
2832 * As an optimisation if we know we aren't looking
2833 * for a wildcard name (ie. the name matches the wildcard exactly)
2834 * then we can finish on any (first) match.
2835 * This speeds up large directory searches. JRA.
2841 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2844 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2845 smb_fn_name(req->cmd),
2846 mask, directory, dirtype, numentries ) );
2848 /* Check if we can close the dirptr */
2849 if(close_after_request || (finished && close_if_end)) {
2850 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2851 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2854 /* Set up the return parameter block */
2855 SSVAL(params,0,numentries);
2856 SSVAL(params,2,finished);
2857 SSVAL(params,4,0); /* Never an EA error */
2858 SSVAL(params,6,last_entry_off);
2860 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2866 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2868 E_md4hash(lp_servicename(SNUM(conn)),objid);
2872 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2874 SMB_ASSERT(extended_info != NULL);
2876 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2877 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2878 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2879 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2880 #ifdef SAMBA_VERSION_REVISION
2881 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2883 extended_info->samba_subversion = 0;
2884 #ifdef SAMBA_VERSION_RC_RELEASE
2885 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2887 #ifdef SAMBA_VERSION_PRE_RELEASE
2888 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2891 #ifdef SAMBA_VERSION_VENDOR_PATCH
2892 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2894 extended_info->samba_gitcommitdate = 0;
2895 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2896 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2899 memset(extended_info->samba_version_string, 0,
2900 sizeof(extended_info->samba_version_string));
2902 snprintf (extended_info->samba_version_string,
2903 sizeof(extended_info->samba_version_string),
2904 "%s", samba_version_string());
2907 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2908 TALLOC_CTX *mem_ctx,
2909 uint16_t info_level,
2911 unsigned int max_data_bytes,
2915 char *pdata, *end_data;
2916 int data_len = 0, len;
2917 const char *vname = volume_label(SNUM(conn));
2918 int snum = SNUM(conn);
2919 char *fstype = lp_fstype(SNUM(conn));
2920 uint32 additional_flags = 0;
2921 struct smb_filename smb_fname_dot;
2925 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2926 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2927 "info level (0x%x) on IPC$.\n",
2928 (unsigned int)info_level));
2929 return NT_STATUS_ACCESS_DENIED;
2933 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2935 ZERO_STRUCT(smb_fname_dot);
2936 smb_fname_dot.base_name = discard_const_p(char, ".");
2938 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2939 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2940 return map_nt_error_from_unix(errno);
2943 st = smb_fname_dot.st;
2945 *ppdata = (char *)SMB_REALLOC(
2946 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2947 if (*ppdata == NULL) {
2948 return NT_STATUS_NO_MEMORY;
2952 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2953 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2955 switch (info_level) {
2956 case SMB_INFO_ALLOCATION:
2958 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2960 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2961 return map_nt_error_from_unix(errno);
2964 block_size = lp_block_size(snum);
2965 if (bsize < block_size) {
2966 uint64_t factor = block_size/bsize;
2971 if (bsize > block_size) {
2972 uint64_t factor = bsize/block_size;
2977 bytes_per_sector = 512;
2978 sectors_per_unit = bsize/bytes_per_sector;
2980 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2981 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2982 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2984 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2985 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2986 SIVAL(pdata,l1_cUnit,dsize);
2987 SIVAL(pdata,l1_cUnitAvail,dfree);
2988 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2992 case SMB_INFO_VOLUME:
2993 /* Return volume name */
2995 * Add volume serial number - hash of a combination of
2996 * the called hostname and the service name.
2998 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3000 * Win2k3 and previous mess this up by sending a name length
3001 * one byte short. I believe only older clients (OS/2 Win9x) use
3002 * this call so try fixing this by adding a terminating null to
3003 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3007 pdata+l2_vol_szVolLabel, vname,
3008 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3009 STR_NOALIGN|STR_TERMINATE);
3010 SCVAL(pdata,l2_vol_cch,len);
3011 data_len = l2_vol_szVolLabel + len;
3012 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3013 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3017 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3018 case SMB_FS_ATTRIBUTE_INFORMATION:
3020 additional_flags = 0;
3021 #if defined(HAVE_SYS_QUOTAS)
3022 additional_flags |= FILE_VOLUME_QUOTAS;
3025 if(lp_nt_acl_support(SNUM(conn))) {
3026 additional_flags |= FILE_PERSISTENT_ACLS;
3029 /* Capabilities are filled in at connection time through STATVFS call */
3030 additional_flags |= conn->fs_capabilities;
3031 additional_flags |= lp_parm_int(conn->params->service,
3032 "share", "fake_fscaps",
3035 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3036 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3037 additional_flags); /* FS ATTRIBUTES */
3039 SIVAL(pdata,4,255); /* Max filename component length */
3040 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3041 and will think we can't do long filenames */
3042 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3043 PTR_DIFF(end_data, pdata+12),
3046 data_len = 12 + len;
3049 case SMB_QUERY_FS_LABEL_INFO:
3050 case SMB_FS_LABEL_INFORMATION:
3051 len = srvstr_push(pdata, flags2, pdata+4, vname,
3052 PTR_DIFF(end_data, pdata+4), 0);
3057 case SMB_QUERY_FS_VOLUME_INFO:
3058 case SMB_FS_VOLUME_INFORMATION:
3061 * Add volume serial number - hash of a combination of
3062 * the called hostname and the service name.
3064 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3065 (str_checksum(get_local_machine_name())<<16));
3067 /* Max label len is 32 characters. */
3068 len = srvstr_push(pdata, flags2, pdata+18, vname,
3069 PTR_DIFF(end_data, pdata+18),
3071 SIVAL(pdata,12,len);
3074 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3075 (int)strlen(vname),vname, lp_servicename(snum)));
3078 case SMB_QUERY_FS_SIZE_INFO:
3079 case SMB_FS_SIZE_INFORMATION:
3081 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3083 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3084 return map_nt_error_from_unix(errno);
3086 block_size = lp_block_size(snum);
3087 if (bsize < block_size) {
3088 uint64_t factor = block_size/bsize;
3093 if (bsize > block_size) {
3094 uint64_t factor = bsize/block_size;
3099 bytes_per_sector = 512;
3100 sectors_per_unit = bsize/bytes_per_sector;
3101 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3102 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3103 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3104 SBIG_UINT(pdata,0,dsize);
3105 SBIG_UINT(pdata,8,dfree);
3106 SIVAL(pdata,16,sectors_per_unit);
3107 SIVAL(pdata,20,bytes_per_sector);
3111 case SMB_FS_FULL_SIZE_INFORMATION:
3113 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3115 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3116 return map_nt_error_from_unix(errno);
3118 block_size = lp_block_size(snum);
3119 if (bsize < block_size) {
3120 uint64_t factor = block_size/bsize;
3125 if (bsize > block_size) {
3126 uint64_t factor = bsize/block_size;
3131 bytes_per_sector = 512;
3132 sectors_per_unit = bsize/bytes_per_sector;
3133 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3134 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3135 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3136 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3137 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3138 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3139 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3140 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3144 case SMB_QUERY_FS_DEVICE_INFO:
3145 case SMB_FS_DEVICE_INFORMATION:
3147 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3149 if (!CAN_WRITE(conn)) {
3150 characteristics |= FILE_READ_ONLY_DEVICE;
3153 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3154 SIVAL(pdata,4,characteristics);
3158 #ifdef HAVE_SYS_QUOTAS
3159 case SMB_FS_QUOTA_INFORMATION:
3161 * what we have to send --metze:
3163 * Unknown1: 24 NULL bytes
3164 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3165 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3166 * Quota Flags: 2 byte :
3167 * Unknown3: 6 NULL bytes
3171 * details for Quota Flags:
3173 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3174 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3175 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3176 * 0x0001 Enable Quotas: enable quota for this fs
3180 /* we need to fake up a fsp here,
3181 * because its not send in this call
3184 SMB_NTQUOTA_STRUCT quotas;
3187 ZERO_STRUCT(quotas);
3193 if (conn->server_info->utok.uid != sec_initial_uid()) {
3194 DEBUG(0,("set_user_quota: access_denied "
3195 "service [%s] user [%s]\n",
3196 lp_servicename(SNUM(conn)),
3197 conn->server_info->unix_name));
3198 return NT_STATUS_ACCESS_DENIED;
3201 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3202 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3203 return map_nt_error_from_unix(errno);
3208 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3209 lp_servicename(SNUM(conn))));
3211 /* Unknown1 24 NULL bytes*/
3212 SBIG_UINT(pdata,0,(uint64_t)0);
3213 SBIG_UINT(pdata,8,(uint64_t)0);
3214 SBIG_UINT(pdata,16,(uint64_t)0);
3216 /* Default Soft Quota 8 bytes */
3217 SBIG_UINT(pdata,24,quotas.softlim);
3219 /* Default Hard Quota 8 bytes */
3220 SBIG_UINT(pdata,32,quotas.hardlim);
3222 /* Quota flag 2 bytes */
3223 SSVAL(pdata,40,quotas.qflags);
3225 /* Unknown3 6 NULL bytes */
3231 #endif /* HAVE_SYS_QUOTAS */
3232 case SMB_FS_OBJECTID_INFORMATION:
3234 unsigned char objid[16];
3235 struct smb_extended_info extended_info;
3236 memcpy(pdata,create_volume_objectid(conn, objid),16);
3237 samba_extended_info_version (&extended_info);
3238 SIVAL(pdata,16,extended_info.samba_magic);
3239 SIVAL(pdata,20,extended_info.samba_version);
3240 SIVAL(pdata,24,extended_info.samba_subversion);
3241 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3242 memcpy(pdata+36,extended_info.samba_version_string,28);
3248 * Query the version and capabilities of the CIFS UNIX extensions
3252 case SMB_QUERY_CIFS_UNIX_INFO:
3254 bool large_write = lp_min_receive_file_size() &&
3255 !srv_is_signing_active(conn->sconn);
3256 bool large_read = !srv_is_signing_active(conn->sconn);
3257 int encrypt_caps = 0;
3259 if (!lp_unix_extensions()) {
3260 return NT_STATUS_INVALID_LEVEL;
3263 switch (conn->encrypt_level) {
3269 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3272 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3273 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3274 large_write = false;
3280 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3281 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3283 /* We have POSIX ACLs, pathname, encryption,
3284 * large read/write, and locking capability. */
3286 SBIG_UINT(pdata,4,((uint64_t)(
3287 CIFS_UNIX_POSIX_ACLS_CAP|
3288 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3289 CIFS_UNIX_FCNTL_LOCKS_CAP|
3290 CIFS_UNIX_EXTATTR_CAP|
3291 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3293 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3295 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3299 case SMB_QUERY_POSIX_FS_INFO:
3302 vfs_statvfs_struct svfs;
3304 if (!lp_unix_extensions()) {
3305 return NT_STATUS_INVALID_LEVEL;
3308 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3312 SIVAL(pdata,0,svfs.OptimalTransferSize);
3313 SIVAL(pdata,4,svfs.BlockSize);
3314 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3315 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3316 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3317 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3318 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3319 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3320 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3322 } else if (rc == EOPNOTSUPP) {
3323 return NT_STATUS_INVALID_LEVEL;
3324 #endif /* EOPNOTSUPP */
3326 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3327 return NT_STATUS_DOS(ERRSRV, ERRerror);
3332 case SMB_QUERY_POSIX_WHOAMI:
3338 if (!lp_unix_extensions()) {
3339 return NT_STATUS_INVALID_LEVEL;
3342 if (max_data_bytes < 40) {
3343 return NT_STATUS_BUFFER_TOO_SMALL;
3346 /* We ARE guest if global_sid_Builtin_Guests is
3347 * in our list of SIDs.
3349 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3350 conn->server_info->ptok)) {
3351 flags |= SMB_WHOAMI_GUEST;
3354 /* We are NOT guest if global_sid_Authenticated_Users
3355 * is in our list of SIDs.
3357 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3358 conn->server_info->ptok)) {
3359 flags &= ~SMB_WHOAMI_GUEST;
3362 /* NOTE: 8 bytes for UID/GID, irrespective of native
3363 * platform size. This matches
3364 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3366 data_len = 4 /* flags */
3373 + 4 /* pad/reserved */
3374 + (conn->server_info->utok.ngroups * 8)
3376 + (conn->server_info->ptok->num_sids *
3380 SIVAL(pdata, 0, flags);
3381 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3383 (uint64_t)conn->server_info->utok.uid);
3384 SBIG_UINT(pdata, 16,
3385 (uint64_t)conn->server_info->utok.gid);
3388 if (data_len >= max_data_bytes) {
3389 /* Potential overflow, skip the GIDs and SIDs. */
3391 SIVAL(pdata, 24, 0); /* num_groups */
3392 SIVAL(pdata, 28, 0); /* num_sids */
3393 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3394 SIVAL(pdata, 36, 0); /* reserved */
3400 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3401 SIVAL(pdata, 28, conn->server_info->ptok->num_sids);
3403 /* We walk the SID list twice, but this call is fairly
3404 * infrequent, and I don't expect that it's performance
3405 * sensitive -- jpeach
3407 for (i = 0, sid_bytes = 0;
3408 i < conn->server_info->ptok->num_sids; ++i) {
3409 sid_bytes += ndr_size_dom_sid(
3410 &conn->server_info->ptok->sids[i],
3414 /* SID list byte count */
3415 SIVAL(pdata, 32, sid_bytes);
3417 /* 4 bytes pad/reserved - must be zero */
3418 SIVAL(pdata, 36, 0);
3422 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3423 SBIG_UINT(pdata, data_len,
3424 (uint64_t)conn->server_info->utok.groups[i]);
3430 i < conn->server_info->ptok->num_sids; ++i) {
3431 int sid_len = ndr_size_dom_sid(
3432 &conn->server_info->ptok->sids[i],
3435 sid_linearize(pdata + data_len, sid_len,
3436 &conn->server_info->ptok->sids[i]);
3437 data_len += sid_len;
3443 case SMB_MAC_QUERY_FS_INFO:
3445 * Thursby MAC extension... ONLY on NTFS filesystems
3446 * once we do streams then we don't need this
3448 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3450 SIVAL(pdata,84,0x100); /* Don't support mac... */
3455 return NT_STATUS_INVALID_LEVEL;
3458 *ret_data_len = data_len;
3459 return NT_STATUS_OK;
3462 /****************************************************************************
3463 Reply to a TRANS2_QFSINFO (query filesystem info).
3464 ****************************************************************************/
3466 static void call_trans2qfsinfo(connection_struct *conn,
3467 struct smb_request *req,
3468 char **pparams, int total_params,
3469 char **ppdata, int total_data,
3470 unsigned int max_data_bytes)
3472 char *params = *pparams;
3473 uint16_t info_level;
3477 if (total_params < 2) {
3478 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3482 info_level = SVAL(params,0);
3484 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3485 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3486 DEBUG(0,("call_trans2qfsinfo: encryption required "
3487 "and info level 0x%x sent.\n",
3488 (unsigned int)info_level));
3489 exit_server_cleanly("encryption required "
3495 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3497 status = smbd_do_qfsinfo(conn, req,
3502 if (!NT_STATUS_IS_OK(status)) {
3503 reply_nterror(req, status);
3507 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3510 DEBUG( 4, ( "%s info_level = %d\n",
3511 smb_fn_name(req->cmd), info_level) );
3516 /****************************************************************************
3517 Reply to a TRANS2_SETFSINFO (set filesystem info).
3518 ****************************************************************************/
3520 static void call_trans2setfsinfo(connection_struct *conn,
3521 struct smb_request *req,
3522 char **pparams, int total_params,
3523 char **ppdata, int total_data,
3524 unsigned int max_data_bytes)
3526 char *pdata = *ppdata;
3527 char *params = *pparams;
3530 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3533 if (total_params < 4) {
3534 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3536 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3540 info_level = SVAL(params,2);
3543 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3544 info_level != SMB_SET_CIFS_UNIX_INFO) {
3545 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3546 "info level (0x%x) on IPC$.\n",
3547 (unsigned int)info_level));
3548 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3553 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3554 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3555 DEBUG(0,("call_trans2setfsinfo: encryption required "
3556 "and info level 0x%x sent.\n",
3557 (unsigned int)info_level));
3558 exit_server_cleanly("encryption required "
3564 switch(info_level) {
3565 case SMB_SET_CIFS_UNIX_INFO:
3567 uint16 client_unix_major;
3568 uint16 client_unix_minor;
3569 uint32 client_unix_cap_low;
3570 uint32 client_unix_cap_high;
3572 if (!lp_unix_extensions()) {
3574 NT_STATUS_INVALID_LEVEL);
3578 /* There should be 12 bytes of capabilities set. */
3579 if (total_data < 8) {
3582 NT_STATUS_INVALID_PARAMETER);
3585 client_unix_major = SVAL(pdata,0);
3586 client_unix_minor = SVAL(pdata,2);
3587 client_unix_cap_low = IVAL(pdata,4);
3588 client_unix_cap_high = IVAL(pdata,8);
3589 /* Just print these values for now. */
3590 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3591 cap_low = 0x%x, cap_high = 0x%x\n",
3592 (unsigned int)client_unix_major,
3593 (unsigned int)client_unix_minor,
3594 (unsigned int)client_unix_cap_low,
3595 (unsigned int)client_unix_cap_high ));
3597 /* Here is where we must switch to posix pathname processing... */
3598 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3599 lp_set_posix_pathnames();
3600 mangle_change_to_posix();
3603 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3604 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3605 /* Client that knows how to do posix locks,
3606 * but not posix open/mkdir operations. Set a
3607 * default type for read/write checks. */
3609 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3615 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3618 size_t param_len = 0;
3619 size_t data_len = total_data;
3621 if (!lp_unix_extensions()) {
3624 NT_STATUS_INVALID_LEVEL);
3628 if (lp_smb_encrypt(SNUM(conn)) == false) {
3631 NT_STATUS_NOT_SUPPORTED);
3635 if (req->sconn->smb1.echo_handler.trusted_fde) {
3636 DEBUG( 2,("call_trans2setfsinfo: "
3637 "request transport encryption disabled"
3638 "with 'fork echo handler = yes'\n"));
3641 NT_STATUS_NOT_SUPPORTED);
3645 DEBUG( 4,("call_trans2setfsinfo: "
3646 "request transport encryption.\n"));
3648 status = srv_request_encryption_setup(conn,
3649 (unsigned char **)ppdata,
3651 (unsigned char **)pparams,
3654 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3655 !NT_STATUS_IS_OK(status)) {
3656 reply_nterror(req, status);
3660 send_trans2_replies(conn, req,
3667 if (NT_STATUS_IS_OK(status)) {
3668 /* Server-side transport
3669 * encryption is now *on*. */
3670 status = srv_encryption_start(conn);
3671 if (!NT_STATUS_IS_OK(status)) {
3672 exit_server_cleanly(
3673 "Failure in setting "
3674 "up encrypted transport");
3680 case SMB_FS_QUOTA_INFORMATION:
3682 files_struct *fsp = NULL;
3683 SMB_NTQUOTA_STRUCT quotas;
3685 ZERO_STRUCT(quotas);
3688 if ((conn->server_info->utok.uid != sec_initial_uid())
3689 ||!CAN_WRITE(conn)) {
3690 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3691 lp_servicename(SNUM(conn)),
3692 conn->server_info->unix_name));
3693 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3697 /* note: normaly there're 48 bytes,
3698 * but we didn't use the last 6 bytes for now
3701 fsp = file_fsp(req, SVAL(params,0));
3703 if (!check_fsp_ntquota_handle(conn, req,
3705 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3707 req, NT_STATUS_INVALID_HANDLE);
3711 if (total_data < 42) {
3712 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3716 NT_STATUS_INVALID_PARAMETER);
3720 /* unknown_1 24 NULL bytes in pdata*/
3722 /* the soft quotas 8 bytes (uint64_t)*/
3723 quotas.softlim = (uint64_t)IVAL(pdata,24);
3724 #ifdef LARGE_SMB_OFF_T
3725 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3726 #else /* LARGE_SMB_OFF_T */
3727 if ((IVAL(pdata,28) != 0)&&
3728 ((quotas.softlim != 0xFFFFFFFF)||
3729 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3730 /* more than 32 bits? */
3733 NT_STATUS_INVALID_PARAMETER);
3736 #endif /* LARGE_SMB_OFF_T */
3738 /* the hard quotas 8 bytes (uint64_t)*/
3739 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3740 #ifdef LARGE_SMB_OFF_T
3741 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3742 #else /* LARGE_SMB_OFF_T */
3743 if ((IVAL(pdata,36) != 0)&&
3744 ((quotas.hardlim != 0xFFFFFFFF)||
3745 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3746 /* more than 32 bits? */
3749 NT_STATUS_INVALID_PARAMETER);
3752 #endif /* LARGE_SMB_OFF_T */
3754 /* quota_flags 2 bytes **/
3755 quotas.qflags = SVAL(pdata,40);
3757 /* unknown_2 6 NULL bytes follow*/
3759 /* now set the quotas */
3760 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3761 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3762 reply_nterror(req, map_nt_error_from_unix(errno));
3769 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3771 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3777 * sending this reply works fine,
3778 * but I'm not sure it's the same
3779 * like windows do...
3782 reply_outbuf(req, 10, 0);
3785 #if defined(HAVE_POSIX_ACLS)
3786 /****************************************************************************
3787 Utility function to count the number of entries in a POSIX acl.
3788 ****************************************************************************/
3790 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3792 unsigned int ace_count = 0;
3793 int entry_id = SMB_ACL_FIRST_ENTRY;
3794 SMB_ACL_ENTRY_T entry;
3796 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3798 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3799 entry_id = SMB_ACL_NEXT_ENTRY;
3806 /****************************************************************************
3807 Utility function to marshall a POSIX acl into wire format.
3808 ****************************************************************************/
3810 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3812 int entry_id = SMB_ACL_FIRST_ENTRY;
3813 SMB_ACL_ENTRY_T entry;
3815 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3816 SMB_ACL_TAG_T tagtype;
3817 SMB_ACL_PERMSET_T permset;
3818 unsigned char perms = 0;
3819 unsigned int own_grp;
3822 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3823 entry_id = SMB_ACL_NEXT_ENTRY;
3826 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3827 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3831 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3832 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3836 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3837 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3838 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3840 SCVAL(pdata,1,perms);
3843 case SMB_ACL_USER_OBJ:
3844 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3845 own_grp = (unsigned int)pst->st_ex_uid;
3846 SIVAL(pdata,2,own_grp);
3851 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3853 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3856 own_grp = (unsigned int)*puid;
3857 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3858 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3859 SIVAL(pdata,2,own_grp);
3863 case SMB_ACL_GROUP_OBJ:
3864 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3865 own_grp = (unsigned int)pst->st_ex_gid;
3866 SIVAL(pdata,2,own_grp);
3871 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3873 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3876 own_grp = (unsigned int)*pgid;
3877 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3878 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3879 SIVAL(pdata,2,own_grp);
3884 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3885 SIVAL(pdata,2,0xFFFFFFFF);
3886 SIVAL(pdata,6,0xFFFFFFFF);
3889 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3890 SIVAL(pdata,2,0xFFFFFFFF);
3891 SIVAL(pdata,6,0xFFFFFFFF);
3894 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3897 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3904 /****************************************************************************
3905 Store the FILE_UNIX_BASIC info.
3906 ****************************************************************************/
3908 static char *store_file_unix_basic(connection_struct *conn,
3911 const SMB_STRUCT_STAT *psbuf)
3913 uint64_t file_index = get_FileIndex(conn, psbuf);
3915 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3916 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3918 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3921 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3924 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3925 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3926 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3929 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3933 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3937 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3940 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3944 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3948 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3951 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3955 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3962 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3963 * the chflags(2) (or equivalent) flags.
3965 * XXX: this really should be behind the VFS interface. To do this, we would
3966 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3967 * Each VFS module could then implement its own mapping as appropriate for the
3968 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3970 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3974 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3978 { UF_IMMUTABLE, EXT_IMMUTABLE },
3982 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3986 { UF_HIDDEN, EXT_HIDDEN },
3989 /* Do not remove. We need to guarantee that this array has at least one
3990 * entry to build on HP-UX.
3996 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3997 uint32 *smb_fflags, uint32 *smb_fmask)
4001 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4002 *smb_fmask |= info2_flags_map[i].smb_fflag;
4003 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4004 *smb_fflags |= info2_flags_map[i].smb_fflag;
4009 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4010 const uint32 smb_fflags,
4011 const uint32 smb_fmask,
4014 uint32 max_fmask = 0;
4017 *stat_fflags = psbuf->st_ex_flags;
4019 /* For each flags requested in smb_fmask, check the state of the
4020 * corresponding flag in smb_fflags and set or clear the matching
4024 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4025 max_fmask |= info2_flags_map[i].smb_fflag;
4026 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4027 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4028 *stat_fflags |= info2_flags_map[i].stat_fflag;
4030 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4035 /* If smb_fmask is asking to set any bits that are not supported by
4036 * our flag mappings, we should fail.
4038 if ((smb_fmask & max_fmask) != smb_fmask) {
4046 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4047 * of file flags and birth (create) time.
4049 static char *store_file_unix_basic_info2(connection_struct *conn,
4052 const SMB_STRUCT_STAT *psbuf)
4054 uint32 file_flags = 0;
4055 uint32 flags_mask = 0;
4057 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4059 /* Create (birth) time 64 bit */
4060 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4063 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4064 SIVAL(pdata, 0, file_flags); /* flags */
4065 SIVAL(pdata, 4, flags_mask); /* mask */
4071 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4072 const struct stream_struct *streams,
4074 unsigned int max_data_bytes,
4075 unsigned int *data_size)
4078 unsigned int ofs = 0;
4080 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4081 unsigned int next_offset;
4083 smb_ucs2_t *namebuf;
4085 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4086 streams[i].name, &namelen) ||
4089 return NT_STATUS_INVALID_PARAMETER;
4093 * name_buf is now null-terminated, we need to marshall as not
4099 SIVAL(data, ofs+4, namelen);
4100 SOFF_T(data, ofs+8, streams[i].size);
4101 SOFF_T(data, ofs+16, streams[i].alloc_size);
4102 memcpy(data+ofs+24, namebuf, namelen);
4103 TALLOC_FREE(namebuf);
4105 next_offset = ofs + 24 + namelen;
4107 if (i == num_streams-1) {
4108 SIVAL(data, ofs, 0);
4111 unsigned int align = ndr_align_size(next_offset, 8);
4113 memset(data+next_offset, 0, align);
4114 next_offset += align;
4116 SIVAL(data, ofs, next_offset - ofs);
4125 return NT_STATUS_OK;
4128 /****************************************************************************
4129 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4130 ****************************************************************************/
4132 static void call_trans2qpipeinfo(connection_struct *conn,
4133 struct smb_request *req,
4134 unsigned int tran_call,
4135 char **pparams, int total_params,
4136 char **ppdata, int total_data,
4137 unsigned int max_data_bytes)
4139 char *params = *pparams;
4140 char *pdata = *ppdata;
4141 unsigned int data_size = 0;
4142 unsigned int param_size = 2;
4147 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4151 if (total_params < 4) {
4152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4156 fsp = file_fsp(req, SVAL(params,0));
4157 if (!fsp_is_np(fsp)) {
4158 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4162 info_level = SVAL(params,2);
4164 *pparams = (char *)SMB_REALLOC(*pparams,2);
4165 if (*pparams == NULL) {
4166 reply_nterror(req, NT_STATUS_NO_MEMORY);
4171 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4172 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4173 if (*ppdata == NULL ) {
4174 reply_nterror(req, NT_STATUS_NO_MEMORY);
4179 switch (info_level) {
4180 case SMB_FILE_STANDARD_INFORMATION:
4182 SOFF_T(pdata,0,4096LL);
4189 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4193 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4199 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4200 TALLOC_CTX *mem_ctx,
4201 uint16_t info_level,
4203 struct smb_filename *smb_fname,
4204 bool delete_pending,
4205 struct timespec write_time_ts,
4206 struct ea_list *ea_list,
4207 int lock_data_count,
4210 unsigned int max_data_bytes,
4212 unsigned int *pdata_size)
4214 char *pdata = *ppdata;
4215 char *dstart, *dend;
4216 unsigned int data_size;
4217 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4218 time_t create_time, mtime, atime, c_time;
4219 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4226 uint64_t file_size = 0;
4228 uint64_t allocation_size = 0;
4229 uint64_t file_index = 0;
4230 uint32_t access_mask = 0;
4232 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4233 return NT_STATUS_INVALID_LEVEL;
4236 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4237 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4238 info_level, max_data_bytes));
4240 mode = dos_mode(conn, smb_fname);
4241 nlink = psbuf->st_ex_nlink;
4243 if (nlink && (mode&aDIR)) {
4247 if ((nlink > 0) && delete_pending) {
4251 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4252 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4253 if (*ppdata == NULL) {
4254 return NT_STATUS_NO_MEMORY;
4258 dend = dstart + data_size - 1;
4260 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4261 update_stat_ex_mtime(psbuf, write_time_ts);
4264 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4265 mtime_ts = psbuf->st_ex_mtime;
4266 atime_ts = psbuf->st_ex_atime;
4267 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4269 if (lp_dos_filetime_resolution(SNUM(conn))) {
4270 dos_filetime_timespec(&create_time_ts);
4271 dos_filetime_timespec(&mtime_ts);
4272 dos_filetime_timespec(&atime_ts);
4273 dos_filetime_timespec(&ctime_ts);
4276 create_time = convert_timespec_to_time_t(create_time_ts);
4277 mtime = convert_timespec_to_time_t(mtime_ts);
4278 atime = convert_timespec_to_time_t(atime_ts);
4279 c_time = convert_timespec_to_time_t(ctime_ts);
4281 p = strrchr_m(smb_fname->base_name,'/');
4283 base_name = smb_fname->base_name;
4287 /* NT expects the name to be in an exact form of the *full*
4288 filename. See the trans2 torture test */
4289 if (ISDOT(base_name)) {
4290 dos_fname = talloc_strdup(mem_ctx, "\\");
4292 return NT_STATUS_NO_MEMORY;
4295 dos_fname = talloc_asprintf(mem_ctx,
4297 smb_fname->base_name);
4299 return NT_STATUS_NO_MEMORY;
4301 if (is_ntfs_stream_smb_fname(smb_fname)) {
4302 dos_fname = talloc_asprintf(dos_fname, "%s",
4303 smb_fname->stream_name);
4305 return NT_STATUS_NO_MEMORY;
4309 string_replace(dos_fname, '/', '\\');
4312 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4315 /* Do we have this path open ? */
4317 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4318 fsp1 = file_find_di_first(conn->sconn, fileid);
4319 if (fsp1 && fsp1->initial_allocation_size) {
4320 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4324 if (!(mode & aDIR)) {
4325 file_size = get_file_size_stat(psbuf);
4329 pos = fsp->fh->position_information;
4333 access_mask = fsp->access_mask;
4335 /* GENERIC_EXECUTE mapping from Windows */
4336 access_mask = 0x12019F;
4339 /* This should be an index number - looks like
4342 I think this causes us to fail the IFSKIT
4343 BasicFileInformationTest. -tpot */
4344 file_index = get_FileIndex(conn, psbuf);
4346 switch (info_level) {
4347 case SMB_INFO_STANDARD:
4348 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4350 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4351 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4352 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4353 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4354 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4355 SSVAL(pdata,l1_attrFile,mode);
4358 case SMB_INFO_QUERY_EA_SIZE:
4360 unsigned int ea_size =
4361 estimate_ea_size(conn, fsp,
4362 smb_fname->base_name);
4363 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4365 srv_put_dos_date2(pdata,0,create_time);
4366 srv_put_dos_date2(pdata,4,atime);
4367 srv_put_dos_date2(pdata,8,mtime); /* write time */
4368 SIVAL(pdata,12,(uint32)file_size);
4369 SIVAL(pdata,16,(uint32)allocation_size);
4370 SSVAL(pdata,20,mode);
4371 SIVAL(pdata,22,ea_size);
4375 case SMB_INFO_IS_NAME_VALID:
4376 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4378 /* os/2 needs this ? really ?*/
4379 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4381 /* This is only reached for qpathinfo */
4385 case SMB_INFO_QUERY_EAS_FROM_LIST:
4387 size_t total_ea_len = 0;
4388 struct ea_list *ea_file_list = NULL;
4390 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4393 get_ea_list_from_file(mem_ctx, conn, fsp,
4394 smb_fname->base_name,
4396 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4398 if (!ea_list || (total_ea_len > data_size)) {
4400 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4404 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4408 case SMB_INFO_QUERY_ALL_EAS:
4410 /* We have data_size bytes to put EA's into. */
4411 size_t total_ea_len = 0;
4413 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4415 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4416 smb_fname->base_name,
4418 if (!ea_list || (total_ea_len > data_size)) {
4420 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4424 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4428 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4430 /* This is FileFullEaInformation - 0xF which maps to
4431 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4433 /* We have data_size bytes to put EA's into. */
4434 size_t total_ea_len = 0;
4435 struct ea_list *ea_file_list = NULL;
4437 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4439 /*TODO: add filtering and index handling */
4442 get_ea_list_from_file(mem_ctx, conn, fsp,
4443 smb_fname->base_name,
4445 if (!ea_file_list) {
4446 return NT_STATUS_NO_EAS_ON_FILE;
4449 status = fill_ea_chained_buffer(mem_ctx,
4453 conn, ea_file_list);
4454 if (!NT_STATUS_IS_OK(status)) {
4460 case SMB_FILE_BASIC_INFORMATION:
4461 case SMB_QUERY_FILE_BASIC_INFO:
4463 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4465 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4467 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4471 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4472 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4473 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4474 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4475 SIVAL(pdata,32,mode);
4477 DEBUG(5,("SMB_QFBI - "));
4478 DEBUG(5,("create: %s ", ctime(&create_time)));
4479 DEBUG(5,("access: %s ", ctime(&atime)));
4480 DEBUG(5,("write: %s ", ctime(&mtime)));
4481 DEBUG(5,("change: %s ", ctime(&c_time)));
4482 DEBUG(5,("mode: %x\n", mode));
4485 case SMB_FILE_STANDARD_INFORMATION:
4486 case SMB_QUERY_FILE_STANDARD_INFO:
4488 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4490 SOFF_T(pdata,0,allocation_size);
4491 SOFF_T(pdata,8,file_size);
4492 SIVAL(pdata,16,nlink);
4493 SCVAL(pdata,20,delete_pending?1:0);
4494 SCVAL(pdata,21,(mode&aDIR)?1:0);
4495 SSVAL(pdata,22,0); /* Padding. */
4498 case SMB_FILE_EA_INFORMATION:
4499 case SMB_QUERY_FILE_EA_INFO:
4501 unsigned int ea_size =
4502 estimate_ea_size(conn, fsp, smb_fname->base_name);
4503 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4505 SIVAL(pdata,0,ea_size);
4509 /* Get the 8.3 name - used if NT SMB was negotiated. */
4510 case SMB_QUERY_FILE_ALT_NAME_INFO:
4511 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4514 char mangled_name[13];
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4516 if (!name_to_8_3(base_name,mangled_name,
4517 True,conn->params)) {
4518 return NT_STATUS_NO_MEMORY;
4520 len = srvstr_push(dstart, flags2,
4521 pdata+4, mangled_name,
4522 PTR_DIFF(dend, pdata+4),
4524 data_size = 4 + len;
4529 case SMB_QUERY_FILE_NAME_INFO:
4533 this must be *exactly* right for ACLs on mapped drives to work
4535 len = srvstr_push(dstart, flags2,
4537 PTR_DIFF(dend, pdata+4),
4539 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4540 data_size = 4 + len;
4545 case SMB_FILE_ALLOCATION_INFORMATION:
4546 case SMB_QUERY_FILE_ALLOCATION_INFO:
4547 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4549 SOFF_T(pdata,0,allocation_size);
4552 case SMB_FILE_END_OF_FILE_INFORMATION:
4553 case SMB_QUERY_FILE_END_OF_FILEINFO:
4554 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4556 SOFF_T(pdata,0,file_size);
4559 case SMB_QUERY_FILE_ALL_INFO:
4560 case SMB_FILE_ALL_INFORMATION:
4563 unsigned int ea_size =
4564 estimate_ea_size(conn, fsp, smb_fname->base_name);
4565 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4566 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4567 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4568 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4569 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4570 SIVAL(pdata,32,mode);
4571 SIVAL(pdata,36,0); /* padding. */
4573 SOFF_T(pdata,0,allocation_size);
4574 SOFF_T(pdata,8,file_size);
4575 SIVAL(pdata,16,nlink);
4576 SCVAL(pdata,20,delete_pending);
4577 SCVAL(pdata,21,(mode&aDIR)?1:0);
4580 SIVAL(pdata,0,ea_size);
4581 pdata += 4; /* EA info */
4582 len = srvstr_push(dstart, flags2,
4584 PTR_DIFF(dend, pdata+4),
4588 data_size = PTR_DIFF(pdata,(*ppdata));
4592 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4595 unsigned int ea_size =
4596 estimate_ea_size(conn, fsp, smb_fname->base_name);
4597 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4598 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4599 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4600 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4601 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4602 SIVAL(pdata, 0x20, mode);
4603 SIVAL(pdata, 0x24, 0); /* padding. */
4604 SBVAL(pdata, 0x28, allocation_size);
4605 SBVAL(pdata, 0x30, file_size);
4606 SIVAL(pdata, 0x38, nlink);
4607 SCVAL(pdata, 0x3C, delete_pending);
4608 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4609 SSVAL(pdata, 0x3E, 0); /* padding */
4610 SBVAL(pdata, 0x40, file_index);
4611 SIVAL(pdata, 0x48, ea_size);
4612 SIVAL(pdata, 0x4C, access_mask);
4613 SBVAL(pdata, 0x50, pos);
4614 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4615 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4619 len = srvstr_push(dstart, flags2,
4621 PTR_DIFF(dend, pdata+4),
4625 data_size = PTR_DIFF(pdata,(*ppdata));
4628 case SMB_FILE_INTERNAL_INFORMATION:
4630 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4631 SBVAL(pdata, 0, file_index);
4635 case SMB_FILE_ACCESS_INFORMATION:
4636 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4637 SIVAL(pdata, 0, access_mask);
4641 case SMB_FILE_NAME_INFORMATION:
4642 /* Pathname with leading '\'. */
4645 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4646 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4647 SIVAL(pdata,0,byte_len);
4648 data_size = 4 + byte_len;
4652 case SMB_FILE_DISPOSITION_INFORMATION:
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4655 SCVAL(pdata,0,delete_pending);
4658 case SMB_FILE_POSITION_INFORMATION:
4659 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4661 SOFF_T(pdata,0,pos);
4664 case SMB_FILE_MODE_INFORMATION:
4665 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4666 SIVAL(pdata,0,mode);
4670 case SMB_FILE_ALIGNMENT_INFORMATION:
4671 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4672 SIVAL(pdata,0,0); /* No alignment needed. */
4677 * NT4 server just returns "invalid query" to this - if we try
4678 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4681 /* The first statement above is false - verified using Thursby
4682 * client against NT4 -- gcolley.
4684 case SMB_QUERY_FILE_STREAM_INFO:
4685 case SMB_FILE_STREAM_INFORMATION: {
4686 unsigned int num_streams;
4687 struct stream_struct *streams;
4689 DEBUG(10,("smbd_do_qfilepathinfo: "
4690 "SMB_FILE_STREAM_INFORMATION\n"));
4692 if (is_ntfs_stream_smb_fname(smb_fname)) {
4693 return NT_STATUS_INVALID_PARAMETER;
4696 status = SMB_VFS_STREAMINFO(
4697 conn, fsp, smb_fname->base_name, talloc_tos(),
4698 &num_streams, &streams);
4700 if (!NT_STATUS_IS_OK(status)) {
4701 DEBUG(10, ("could not get stream info: %s\n",
4702 nt_errstr(status)));
4706 status = marshall_stream_info(num_streams, streams,
4707 pdata, max_data_bytes,
4710 if (!NT_STATUS_IS_OK(status)) {
4711 DEBUG(10, ("marshall_stream_info failed: %s\n",
4712 nt_errstr(status)));
4716 TALLOC_FREE(streams);
4720 case SMB_QUERY_COMPRESSION_INFO:
4721 case SMB_FILE_COMPRESSION_INFORMATION:
4722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4723 SOFF_T(pdata,0,file_size);
4724 SIVAL(pdata,8,0); /* ??? */
4725 SIVAL(pdata,12,0); /* ??? */
4729 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4730 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4731 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4732 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4733 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4734 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4735 SOFF_T(pdata,32,allocation_size);
4736 SOFF_T(pdata,40,file_size);
4737 SIVAL(pdata,48,mode);
4738 SIVAL(pdata,52,0); /* ??? */
4742 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4743 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4744 SIVAL(pdata,0,mode);
4750 * CIFS UNIX Extensions.
4753 case SMB_QUERY_FILE_UNIX_BASIC:
4755 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4756 data_size = PTR_DIFF(pdata,(*ppdata));
4758 DEBUG(4,("smbd_do_qfilepathinfo: "
4759 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4760 dump_data(4, (uint8_t *)(*ppdata), data_size);
4764 case SMB_QUERY_FILE_UNIX_INFO2:
4766 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4767 data_size = PTR_DIFF(pdata,(*ppdata));
4771 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4773 for (i=0; i<100; i++)
4774 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4780 case SMB_QUERY_FILE_UNIX_LINK:
4783 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4786 return NT_STATUS_NO_MEMORY;
4789 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4791 if(!S_ISLNK(psbuf->st_ex_mode)) {
4792 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4795 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4797 len = SMB_VFS_READLINK(conn,
4798 smb_fname->base_name,
4801 return map_nt_error_from_unix(errno);
4804 len = srvstr_push(dstart, flags2,
4806 PTR_DIFF(dend, pdata),
4809 data_size = PTR_DIFF(pdata,(*ppdata));
4814 #if defined(HAVE_POSIX_ACLS)
4815 case SMB_QUERY_POSIX_ACL:
4817 SMB_ACL_T file_acl = NULL;
4818 SMB_ACL_T def_acl = NULL;
4819 uint16 num_file_acls = 0;
4820 uint16 num_def_acls = 0;
4822 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4823 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4826 SMB_VFS_SYS_ACL_GET_FILE(conn,
4827 smb_fname->base_name,
4828 SMB_ACL_TYPE_ACCESS);
4831 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4832 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4833 "not implemented on "
4834 "filesystem containing %s\n",
4835 smb_fname->base_name));
4836 return NT_STATUS_NOT_IMPLEMENTED;
4839 if (S_ISDIR(psbuf->st_ex_mode)) {
4840 if (fsp && fsp->is_directory) {
4842 SMB_VFS_SYS_ACL_GET_FILE(
4844 fsp->fsp_name->base_name,
4845 SMB_ACL_TYPE_DEFAULT);
4848 SMB_VFS_SYS_ACL_GET_FILE(
4850 smb_fname->base_name,
4851 SMB_ACL_TYPE_DEFAULT);
4853 def_acl = free_empty_sys_acl(conn, def_acl);
4856 num_file_acls = count_acl_entries(conn, file_acl);
4857 num_def_acls = count_acl_entries(conn, def_acl);
4859 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4860 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4862 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4863 SMB_POSIX_ACL_HEADER_SIZE) ));
4865 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4868 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4870 return NT_STATUS_BUFFER_TOO_SMALL;
4873 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4874 SSVAL(pdata,2,num_file_acls);
4875 SSVAL(pdata,4,num_def_acls);
4876 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4878 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4881 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4883 return NT_STATUS_INTERNAL_ERROR;
4885 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4887 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4890 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4892 return NT_STATUS_INTERNAL_ERROR;
4896 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4899 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4901 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4907 case SMB_QUERY_POSIX_LOCK:
4912 enum brl_type lock_type;
4914 /* We need an open file with a real fd for this. */
4915 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4916 return NT_STATUS_INVALID_LEVEL;
4919 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4920 return NT_STATUS_INVALID_PARAMETER;
4923 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4924 case POSIX_LOCK_TYPE_READ:
4925 lock_type = READ_LOCK;
4927 case POSIX_LOCK_TYPE_WRITE:
4928 lock_type = WRITE_LOCK;
4930 case POSIX_LOCK_TYPE_UNLOCK:
4932 /* There's no point in asking for an unlock... */
4933 return NT_STATUS_INVALID_PARAMETER;
4936 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4937 #if defined(HAVE_LONGLONG)
4938 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4939 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4940 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4941 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4942 #else /* HAVE_LONGLONG */
4943 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4944 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4945 #endif /* HAVE_LONGLONG */
4947 status = query_lock(fsp,
4954 if (ERROR_WAS_LOCK_DENIED(status)) {
4955 /* Here we need to report who has it locked... */
4956 data_size = POSIX_LOCK_DATA_SIZE;
4958 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4959 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4960 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4961 #if defined(HAVE_LONGLONG)
4962 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4963 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4964 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4965 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4966 #else /* HAVE_LONGLONG */
4967 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4968 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4969 #endif /* HAVE_LONGLONG */
4971 } else if (NT_STATUS_IS_OK(status)) {
4972 /* For success we just return a copy of what we sent
4973 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4974 data_size = POSIX_LOCK_DATA_SIZE;
4975 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4976 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4984 return NT_STATUS_INVALID_LEVEL;
4987 *pdata_size = data_size;
4988 return NT_STATUS_OK;
4991 /****************************************************************************
4992 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4993 file name or file id).
4994 ****************************************************************************/
4996 static void call_trans2qfilepathinfo(connection_struct *conn,
4997 struct smb_request *req,
4998 unsigned int tran_call,
4999 char **pparams, int total_params,
5000 char **ppdata, int total_data,
5001 unsigned int max_data_bytes)
5003 char *params = *pparams;
5004 char *pdata = *ppdata;
5006 unsigned int data_size = 0;
5007 unsigned int param_size = 2;
5008 struct smb_filename *smb_fname = NULL;
5009 bool delete_pending = False;
5010 struct timespec write_time_ts;
5011 files_struct *fsp = NULL;
5012 struct file_id fileid;
5013 struct ea_list *ea_list = NULL;
5014 int lock_data_count = 0;
5015 char *lock_data = NULL;
5016 NTSTATUS status = NT_STATUS_OK;
5019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5023 ZERO_STRUCT(write_time_ts);
5025 if (tran_call == TRANSACT2_QFILEINFO) {
5026 if (total_params < 4) {
5027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5032 call_trans2qpipeinfo(conn, req, tran_call,
5033 pparams, total_params,
5039 fsp = file_fsp(req, SVAL(params,0));
5040 info_level = SVAL(params,2);
5042 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5044 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5045 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5049 /* Initial check for valid fsp ptr. */
5050 if (!check_fsp_open(conn, req, fsp)) {
5054 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5056 if (!NT_STATUS_IS_OK(status)) {
5057 reply_nterror(req, status);
5061 if(fsp->fake_file_handle) {
5063 * This is actually for the QUOTA_FAKE_FILE --metze
5066 /* We know this name is ok, it's already passed the checks. */
5068 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5070 * This is actually a QFILEINFO on a directory
5071 * handle (returned from an NT SMB). NT5.0 seems
5072 * to do this call. JRA.
5075 if (INFO_LEVEL_IS_UNIX(info_level)) {
5076 /* Always do lstat for UNIX calls. */
5077 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5078 DEBUG(3,("call_trans2qfilepathinfo: "
5079 "SMB_VFS_LSTAT of %s failed "
5081 smb_fname_str_dbg(smb_fname),
5084 map_nt_error_from_unix(errno));
5087 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5088 DEBUG(3,("call_trans2qfilepathinfo: "
5089 "SMB_VFS_STAT of %s failed (%s)\n",
5090 smb_fname_str_dbg(smb_fname),
5093 map_nt_error_from_unix(errno));
5097 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5098 get_file_infos(fileid, &delete_pending, &write_time_ts);
5101 * Original code - this is an open file.
5103 if (!check_fsp(conn, req, fsp)) {
5107 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5108 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5109 fsp->fnum, strerror(errno)));
5111 map_nt_error_from_unix(errno));
5114 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5115 get_file_infos(fileid, &delete_pending, &write_time_ts);
5122 if (total_params < 7) {
5123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5127 info_level = SVAL(params,0);
5129 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5131 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5132 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5136 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5138 STR_TERMINATE, &status);
5139 if (!NT_STATUS_IS_OK(status)) {
5140 reply_nterror(req, status);
5144 status = filename_convert(req,
5146 req->flags2 & FLAGS2_DFS_PATHNAMES,
5151 if (!NT_STATUS_IS_OK(status)) {
5152 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5153 reply_botherror(req,
5154 NT_STATUS_PATH_NOT_COVERED,
5155 ERRSRV, ERRbadpath);
5158 reply_nterror(req, status);
5162 /* If this is a stream, check if there is a delete_pending. */
5163 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5164 && is_ntfs_stream_smb_fname(smb_fname)) {
5165 struct smb_filename *smb_fname_base = NULL;
5167 /* Create an smb_filename with stream_name == NULL. */
5169 create_synthetic_smb_fname(talloc_tos(),
5170 smb_fname->base_name,
5173 if (!NT_STATUS_IS_OK(status)) {
5174 reply_nterror(req, status);
5178 if (INFO_LEVEL_IS_UNIX(info_level)) {
5179 /* Always do lstat for UNIX calls. */
5180 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5181 DEBUG(3,("call_trans2qfilepathinfo: "
5182 "SMB_VFS_LSTAT of %s failed "
5184 smb_fname_str_dbg(smb_fname_base),
5186 TALLOC_FREE(smb_fname_base);
5188 map_nt_error_from_unix(errno));
5192 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5193 DEBUG(3,("call_trans2qfilepathinfo: "
5194 "fileinfo of %s failed "
5196 smb_fname_str_dbg(smb_fname_base),
5198 TALLOC_FREE(smb_fname_base);
5200 map_nt_error_from_unix(errno));
5205 fileid = vfs_file_id_from_sbuf(conn,
5206 &smb_fname_base->st);
5207 TALLOC_FREE(smb_fname_base);
5208 get_file_infos(fileid, &delete_pending, NULL);
5209 if (delete_pending) {
5210 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5215 if (INFO_LEVEL_IS_UNIX(info_level)) {
5216 /* Always do lstat for UNIX calls. */
5217 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5218 DEBUG(3,("call_trans2qfilepathinfo: "
5219 "SMB_VFS_LSTAT of %s failed (%s)\n",
5220 smb_fname_str_dbg(smb_fname),
5223 map_nt_error_from_unix(errno));
5228 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5229 DEBUG(3,("call_trans2qfilepathinfo: "
5230 "SMB_VFS_STAT of %s failed (%s)\n",
5231 smb_fname_str_dbg(smb_fname),
5234 map_nt_error_from_unix(errno));
5239 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5240 get_file_infos(fileid, &delete_pending, &write_time_ts);
5241 if (delete_pending) {
5242 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5247 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5248 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5249 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5251 /* Pull out any data sent here before we realloc. */
5252 switch (info_level) {
5253 case SMB_INFO_QUERY_EAS_FROM_LIST:
5255 /* Pull any EA list from the data portion. */
5258 if (total_data < 4) {
5260 req, NT_STATUS_INVALID_PARAMETER);
5263 ea_size = IVAL(pdata,0);
5265 if (total_data > 0 && ea_size != total_data) {
5266 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5267 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5269 req, NT_STATUS_INVALID_PARAMETER);
5273 if (!lp_ea_support(SNUM(conn))) {
5274 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5278 /* Pull out the list of names. */
5279 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5282 req, NT_STATUS_INVALID_PARAMETER);
5288 case SMB_QUERY_POSIX_LOCK:
5290 if (fsp == NULL || fsp->fh->fd == -1) {
5291 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5295 if (total_data != POSIX_LOCK_DATA_SIZE) {
5297 req, NT_STATUS_INVALID_PARAMETER);
5301 /* Copy the lock range data. */
5302 lock_data = (char *)TALLOC_MEMDUP(
5303 req, pdata, total_data);
5305 reply_nterror(req, NT_STATUS_NO_MEMORY);
5308 lock_data_count = total_data;
5314 *pparams = (char *)SMB_REALLOC(*pparams,2);
5315 if (*pparams == NULL) {
5316 reply_nterror(req, NT_STATUS_NO_MEMORY);
5323 * draft-leach-cifs-v1-spec-02.txt
5324 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5327 * The requested information is placed in the Data portion of the
5328 * transaction response. For the information levels greater than 0x100,
5329 * the transaction response has 1 parameter word which should be
5330 * ignored by the client.
5332 * However Windows only follows this rule for the IS_NAME_VALID call.
5334 switch (info_level) {
5335 case SMB_INFO_IS_NAME_VALID:
5340 if ((info_level & 0xFF00) == 0xFF00) {
5342 * We use levels that start with 0xFF00
5343 * internally to represent SMB2 specific levels
5345 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5349 status = smbd_do_qfilepathinfo(conn, req, info_level,
5351 delete_pending, write_time_ts,
5353 lock_data_count, lock_data,
5354 req->flags2, max_data_bytes,
5355 ppdata, &data_size);
5356 if (!NT_STATUS_IS_OK(status)) {
5357 reply_nterror(req, status);
5361 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5367 /****************************************************************************
5368 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5370 ****************************************************************************/
5372 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5373 connection_struct *conn,
5374 struct smb_request *req,
5375 bool overwrite_if_exists,
5376 const struct smb_filename *smb_fname_old,
5377 struct smb_filename *smb_fname_new)
5379 NTSTATUS status = NT_STATUS_OK;
5381 /* source must already exist. */
5382 if (!VALID_STAT(smb_fname_old->st)) {
5383 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5386 if (VALID_STAT(smb_fname_new->st)) {
5387 if (overwrite_if_exists) {
5388 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5389 return NT_STATUS_FILE_IS_A_DIRECTORY;
5391 status = unlink_internals(conn,
5393 FILE_ATTRIBUTE_NORMAL,
5396 if (!NT_STATUS_IS_OK(status)) {
5400 /* Disallow if newname already exists. */
5401 return NT_STATUS_OBJECT_NAME_COLLISION;
5405 /* No links from a directory. */
5406 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5407 return NT_STATUS_FILE_IS_A_DIRECTORY;
5410 /* Setting a hardlink to/from a stream isn't currently supported. */
5411 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5412 is_ntfs_stream_smb_fname(smb_fname_new)) {
5413 return NT_STATUS_INVALID_PARAMETER;
5416 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5417 smb_fname_old->base_name, smb_fname_new->base_name));
5419 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5420 smb_fname_new->base_name) != 0) {
5421 status = map_nt_error_from_unix(errno);
5422 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5423 nt_errstr(status), smb_fname_old->base_name,
5424 smb_fname_new->base_name));
5429 /****************************************************************************
5430 Deal with setting the time from any of the setfilepathinfo functions.
5431 ****************************************************************************/
5433 NTSTATUS smb_set_file_time(connection_struct *conn,
5435 const struct smb_filename *smb_fname,
5436 struct smb_file_time *ft,
5437 bool setting_write_time)
5439 struct smb_filename smb_fname_base;
5441 FILE_NOTIFY_CHANGE_LAST_ACCESS
5442 |FILE_NOTIFY_CHANGE_LAST_WRITE
5443 |FILE_NOTIFY_CHANGE_CREATION;
5445 if (!VALID_STAT(smb_fname->st)) {
5446 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5449 /* get some defaults (no modifications) if any info is zero or -1. */
5450 if (null_timespec(ft->create_time)) {
5451 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5454 if (null_timespec(ft->atime)) {
5455 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5458 if (null_timespec(ft->mtime)) {
5459 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5462 if (!setting_write_time) {
5463 /* ft->mtime comes from change time, not write time. */
5464 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5467 /* Ensure the resolution is the correct for
5468 * what we can store on this filesystem. */
5470 round_timespec(conn->ts_res, &ft->create_time);
5471 round_timespec(conn->ts_res, &ft->ctime);
5472 round_timespec(conn->ts_res, &ft->atime);
5473 round_timespec(conn->ts_res, &ft->mtime);
5475 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5476 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5477 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5478 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5479 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5480 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5481 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5482 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5484 if (setting_write_time) {
5486 * This was a Windows setfileinfo on an open file.
5487 * NT does this a lot. We also need to
5488 * set the time here, as it can be read by
5489 * FindFirst/FindNext and with the patch for bug #2045
5490 * in smbd/fileio.c it ensures that this timestamp is
5491 * kept sticky even after a write. We save the request
5492 * away and will set it on file close and after a write. JRA.
5495 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5496 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5499 if (fsp->base_fsp) {
5500 set_sticky_write_time_fsp(fsp->base_fsp,
5503 set_sticky_write_time_fsp(fsp, ft->mtime);
5506 set_sticky_write_time_path(
5507 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5512 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5514 /* Always call ntimes on the base, even if a stream was passed in. */
5515 smb_fname_base = *smb_fname;
5516 smb_fname_base.stream_name = NULL;
5518 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5519 return map_nt_error_from_unix(errno);
5522 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5523 smb_fname->base_name);
5524 return NT_STATUS_OK;
5527 /****************************************************************************
5528 Deal with setting the dosmode from any of the setfilepathinfo functions.
5529 ****************************************************************************/
5531 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5532 const struct smb_filename *smb_fname,
5535 struct smb_filename *smb_fname_base = NULL;
5538 if (!VALID_STAT(smb_fname->st)) {
5539 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5542 /* Always operate on the base_name, even if a stream was passed in. */
5543 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5544 NULL, &smb_fname->st,
5546 if (!NT_STATUS_IS_OK(status)) {
5551 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5558 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5560 /* check the mode isn't different, before changing it */
5561 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5562 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5563 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5564 (unsigned int)dosmode));
5566 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5568 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5570 smb_fname_str_dbg(smb_fname_base),
5572 status = map_nt_error_from_unix(errno);
5576 status = NT_STATUS_OK;
5578 TALLOC_FREE(smb_fname_base);
5582 /****************************************************************************
5583 Deal with setting the size from any of the setfilepathinfo functions.
5584 ****************************************************************************/
5586 static NTSTATUS smb_set_file_size(connection_struct *conn,
5587 struct smb_request *req,
5589 const struct smb_filename *smb_fname,
5590 const SMB_STRUCT_STAT *psbuf,
5592 bool fail_after_createfile)
5594 NTSTATUS status = NT_STATUS_OK;
5595 struct smb_filename *smb_fname_tmp = NULL;
5596 files_struct *new_fsp = NULL;
5598 if (!VALID_STAT(*psbuf)) {
5599 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5602 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5604 if (size == get_file_size_stat(psbuf)) {
5605 return NT_STATUS_OK;
5608 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5609 smb_fname_str_dbg(smb_fname), (double)size));
5611 if (fsp && fsp->fh->fd != -1) {
5612 /* Handle based call. */
5613 if (vfs_set_filelen(fsp, size) == -1) {
5614 return map_nt_error_from_unix(errno);
5616 trigger_write_time_update_immediate(fsp);
5617 return NT_STATUS_OK;
5620 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5621 if (!NT_STATUS_IS_OK(status)) {
5625 smb_fname_tmp->st = *psbuf;
5627 status = SMB_VFS_CREATE_FILE(
5630 0, /* root_dir_fid */
5631 smb_fname_tmp, /* fname */
5632 FILE_WRITE_DATA, /* access_mask */
5633 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5635 FILE_OPEN, /* create_disposition*/
5636 0, /* create_options */
5637 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5638 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5639 0, /* allocation_size */
5640 0, /* private_flags */
5643 &new_fsp, /* result */
5646 TALLOC_FREE(smb_fname_tmp);
5648 if (!NT_STATUS_IS_OK(status)) {
5649 /* NB. We check for open_was_deferred in the caller. */
5653 /* See RAW-SFILEINFO-END-OF-FILE */
5654 if (fail_after_createfile) {
5655 close_file(req, new_fsp,NORMAL_CLOSE);
5656 return NT_STATUS_INVALID_LEVEL;
5659 if (vfs_set_filelen(new_fsp, size) == -1) {
5660 status = map_nt_error_from_unix(errno);
5661 close_file(req, new_fsp,NORMAL_CLOSE);
5665 trigger_write_time_update_immediate(new_fsp);
5666 close_file(req, new_fsp,NORMAL_CLOSE);
5667 return NT_STATUS_OK;
5670 /****************************************************************************
5671 Deal with SMB_INFO_SET_EA.
5672 ****************************************************************************/
5674 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5678 const struct smb_filename *smb_fname)
5680 struct ea_list *ea_list = NULL;
5681 TALLOC_CTX *ctx = NULL;
5682 NTSTATUS status = NT_STATUS_OK;
5684 if (total_data < 10) {
5686 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5687 length. They seem to have no effect. Bug #3212. JRA */
5689 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5690 /* We're done. We only get EA info in this call. */
5691 return NT_STATUS_OK;
5694 return NT_STATUS_INVALID_PARAMETER;
5697 if (IVAL(pdata,0) > total_data) {
5698 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5699 IVAL(pdata,0), (unsigned int)total_data));
5700 return NT_STATUS_INVALID_PARAMETER;
5704 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5706 return NT_STATUS_INVALID_PARAMETER;
5708 status = set_ea(conn, fsp, smb_fname, ea_list);
5713 /****************************************************************************
5714 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5715 ****************************************************************************/
5717 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5722 struct ea_list *ea_list = NULL;
5726 return NT_STATUS_INVALID_HANDLE;
5729 if (!lp_ea_support(SNUM(conn))) {
5730 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5731 "EA's not supported.\n",
5732 (unsigned int)total_data));
5733 return NT_STATUS_EAS_NOT_SUPPORTED;
5736 if (total_data < 10) {
5737 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5739 (unsigned int)total_data));
5740 return NT_STATUS_INVALID_PARAMETER;
5743 ea_list = read_nttrans_ea_list(talloc_tos(),
5748 return NT_STATUS_INVALID_PARAMETER;
5750 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5752 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5753 smb_fname_str_dbg(fsp->fsp_name),
5754 nt_errstr(status) ));
5760 /****************************************************************************
5761 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5762 ****************************************************************************/
5764 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5768 struct smb_filename *smb_fname)
5770 NTSTATUS status = NT_STATUS_OK;
5771 bool delete_on_close;
5774 if (total_data < 1) {
5775 return NT_STATUS_INVALID_PARAMETER;
5779 return NT_STATUS_INVALID_HANDLE;
5782 delete_on_close = (CVAL(pdata,0) ? True : False);
5783 dosmode = dos_mode(conn, smb_fname);
5785 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5786 "delete_on_close = %u\n",
5787 smb_fname_str_dbg(smb_fname),
5788 (unsigned int)dosmode,
5789 (unsigned int)delete_on_close ));
5791 if (delete_on_close) {
5792 status = can_set_delete_on_close(fsp, dosmode);
5793 if (!NT_STATUS_IS_OK(status)) {
5798 /* The set is across all open files on this dev/inode pair. */
5799 if (!set_delete_on_close(fsp, delete_on_close,
5800 &conn->server_info->utok)) {
5801 return NT_STATUS_ACCESS_DENIED;
5803 return NT_STATUS_OK;
5806 /****************************************************************************
5807 Deal with SMB_FILE_POSITION_INFORMATION.
5808 ****************************************************************************/
5810 static NTSTATUS smb_file_position_information(connection_struct *conn,
5815 uint64_t position_information;
5817 if (total_data < 8) {
5818 return NT_STATUS_INVALID_PARAMETER;
5822 /* Ignore on pathname based set. */
5823 return NT_STATUS_OK;
5826 position_information = (uint64_t)IVAL(pdata,0);
5827 #ifdef LARGE_SMB_OFF_T
5828 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5829 #else /* LARGE_SMB_OFF_T */
5830 if (IVAL(pdata,4) != 0) {
5831 /* more than 32 bits? */
5832 return NT_STATUS_INVALID_PARAMETER;
5834 #endif /* LARGE_SMB_OFF_T */
5836 DEBUG(10,("smb_file_position_information: Set file position "
5837 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5838 (double)position_information));
5839 fsp->fh->position_information = position_information;
5840 return NT_STATUS_OK;
5843 /****************************************************************************
5844 Deal with SMB_FILE_MODE_INFORMATION.
5845 ****************************************************************************/
5847 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5853 if (total_data < 4) {
5854 return NT_STATUS_INVALID_PARAMETER;
5856 mode = IVAL(pdata,0);
5857 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5858 return NT_STATUS_INVALID_PARAMETER;
5860 return NT_STATUS_OK;
5863 /****************************************************************************
5864 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5865 ****************************************************************************/
5867 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5868 struct smb_request *req,
5871 const struct smb_filename *smb_fname)
5873 char *link_target = NULL;
5874 const char *newname = smb_fname->base_name;
5875 TALLOC_CTX *ctx = talloc_tos();
5877 /* Set a symbolic link. */
5878 /* Don't allow this if follow links is false. */
5880 if (total_data == 0) {
5881 return NT_STATUS_INVALID_PARAMETER;
5884 if (!lp_symlinks(SNUM(conn))) {
5885 return NT_STATUS_ACCESS_DENIED;
5888 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5889 total_data, STR_TERMINATE);
5892 return NT_STATUS_INVALID_PARAMETER;
5895 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5896 newname, link_target ));
5898 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5899 return map_nt_error_from_unix(errno);
5902 return NT_STATUS_OK;
5905 /****************************************************************************
5906 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5907 ****************************************************************************/
5909 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5910 struct smb_request *req,
5911 const char *pdata, int total_data,
5912 struct smb_filename *smb_fname_new)
5914 char *oldname = NULL;
5915 struct smb_filename *smb_fname_old = NULL;
5916 TALLOC_CTX *ctx = talloc_tos();
5917 NTSTATUS status = NT_STATUS_OK;
5919 /* Set a hard link. */
5920 if (total_data == 0) {
5921 return NT_STATUS_INVALID_PARAMETER;
5924 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5925 total_data, STR_TERMINATE, &status);
5926 if (!NT_STATUS_IS_OK(status)) {
5930 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5931 smb_fname_str_dbg(smb_fname_new), oldname));
5933 status = filename_convert(ctx,
5935 req->flags2 & FLAGS2_DFS_PATHNAMES,
5940 if (!NT_STATUS_IS_OK(status)) {
5944 return hardlink_internals(ctx, conn, req, false,
5945 smb_fname_old, smb_fname_new);
5948 /****************************************************************************
5949 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5950 ****************************************************************************/
5952 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5953 struct smb_request *req,
5957 struct smb_filename *smb_fname_src)
5961 char *newname = NULL;
5962 struct smb_filename *smb_fname_dst = NULL;
5963 NTSTATUS status = NT_STATUS_OK;
5964 TALLOC_CTX *ctx = talloc_tos();
5967 return NT_STATUS_INVALID_HANDLE;
5970 if (total_data < 20) {
5971 return NT_STATUS_INVALID_PARAMETER;
5974 overwrite = (CVAL(pdata,0) ? True : False);
5975 len = IVAL(pdata,16);
5977 if (len > (total_data - 20) || (len == 0)) {
5978 return NT_STATUS_INVALID_PARAMETER;
5981 srvstr_get_path(ctx, pdata, req->flags2, &newname,
5982 &pdata[20], len, STR_TERMINATE,
5984 if (!NT_STATUS_IS_OK(status)) {
5988 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5991 status = filename_convert(ctx,
5993 req->flags2 & FLAGS2_DFS_PATHNAMES,
5998 if (!NT_STATUS_IS_OK(status)) {
6002 if (fsp->base_fsp) {
6003 /* newname must be a stream name. */
6004 if (newname[0] != ':') {
6005 return NT_STATUS_NOT_SUPPORTED;
6008 /* Create an smb_fname to call rename_internals_fsp() with. */
6009 status = create_synthetic_smb_fname(talloc_tos(),
6010 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6012 if (!NT_STATUS_IS_OK(status)) {
6017 * Set the original last component, since
6018 * rename_internals_fsp() requires it.
6020 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6022 if (smb_fname_dst->original_lcomp == NULL) {
6023 status = NT_STATUS_NO_MEMORY;
6029 DEBUG(10,("smb2_file_rename_information: "
6030 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6031 fsp->fnum, fsp_str_dbg(fsp),
6032 smb_fname_str_dbg(smb_fname_dst)));
6033 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6037 TALLOC_FREE(smb_fname_dst);
6041 static NTSTATUS smb_file_link_information(connection_struct *conn,
6042 struct smb_request *req,
6046 struct smb_filename *smb_fname_src)
6050 char *newname = NULL;
6051 struct smb_filename *smb_fname_dst = NULL;
6052 NTSTATUS status = NT_STATUS_OK;
6053 TALLOC_CTX *ctx = talloc_tos();
6056 return NT_STATUS_INVALID_HANDLE;
6059 if (total_data < 20) {
6060 return NT_STATUS_INVALID_PARAMETER;
6063 overwrite = (CVAL(pdata,0) ? true : false);
6064 len = IVAL(pdata,16);
6066 if (len > (total_data - 20) || (len == 0)) {
6067 return NT_STATUS_INVALID_PARAMETER;
6070 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6071 &pdata[20], len, STR_TERMINATE,
6073 if (!NT_STATUS_IS_OK(status)) {
6077 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6080 status = filename_convert(ctx,
6082 req->flags2 & FLAGS2_DFS_PATHNAMES,
6087 if (!NT_STATUS_IS_OK(status)) {
6091 if (fsp->base_fsp) {
6092 /* No stream names. */
6093 return NT_STATUS_NOT_SUPPORTED;
6096 DEBUG(10,("smb_file_link_information: "
6097 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6098 fsp->fnum, fsp_str_dbg(fsp),
6099 smb_fname_str_dbg(smb_fname_dst)));
6100 status = hardlink_internals(ctx,
6107 TALLOC_FREE(smb_fname_dst);
6111 /****************************************************************************
6112 Deal with SMB_FILE_RENAME_INFORMATION.
6113 ****************************************************************************/
6115 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6116 struct smb_request *req,
6120 struct smb_filename *smb_fname_src)
6125 char *newname = NULL;
6126 struct smb_filename *smb_fname_dst = NULL;
6127 bool dest_has_wcard = False;
6128 NTSTATUS status = NT_STATUS_OK;
6130 TALLOC_CTX *ctx = talloc_tos();
6132 if (total_data < 13) {
6133 return NT_STATUS_INVALID_PARAMETER;
6136 overwrite = (CVAL(pdata,0) ? True : False);
6137 root_fid = IVAL(pdata,4);
6138 len = IVAL(pdata,8);
6140 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6141 return NT_STATUS_INVALID_PARAMETER;
6144 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6147 if (!NT_STATUS_IS_OK(status)) {
6151 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6154 status = resolve_dfspath_wcard(ctx, conn,
6155 req->flags2 & FLAGS2_DFS_PATHNAMES,
6160 if (!NT_STATUS_IS_OK(status)) {
6164 /* Check the new name has no '/' characters. */
6165 if (strchr_m(newname, '/')) {
6166 return NT_STATUS_NOT_SUPPORTED;
6169 if (fsp && fsp->base_fsp) {
6170 /* newname must be a stream name. */
6171 if (newname[0] != ':') {
6172 return NT_STATUS_NOT_SUPPORTED;
6175 /* Create an smb_fname to call rename_internals_fsp() with. */
6176 status = create_synthetic_smb_fname(talloc_tos(),
6177 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6179 if (!NT_STATUS_IS_OK(status)) {
6184 * Set the original last component, since
6185 * rename_internals_fsp() requires it.
6187 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6189 if (smb_fname_dst->original_lcomp == NULL) {
6190 status = NT_STATUS_NO_MEMORY;
6196 * Build up an smb_fname_dst based on the filename passed in.
6197 * We basically just strip off the last component, and put on
6198 * the newname instead.
6200 char *base_name = NULL;
6202 /* newname must *not* be a stream name. */
6203 if (newname[0] == ':') {
6204 return NT_STATUS_NOT_SUPPORTED;
6208 * Strip off the last component (filename) of the path passed
6211 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6213 return NT_STATUS_NO_MEMORY;
6215 p = strrchr_m(base_name, '/');
6219 base_name = talloc_strdup(ctx, "./");
6221 return NT_STATUS_NO_MEMORY;
6224 /* Append the new name. */
6225 base_name = talloc_asprintf_append(base_name,
6229 return NT_STATUS_NO_MEMORY;
6232 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6235 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6238 /* If an error we expect this to be
6239 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6241 if (!NT_STATUS_IS_OK(status)) {
6242 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6246 /* Create an smb_fname to call rename_internals_fsp() */
6247 status = create_synthetic_smb_fname(ctx,
6251 if (!NT_STATUS_IS_OK(status)) {
6258 DEBUG(10,("smb_file_rename_information: "
6259 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6260 fsp->fnum, fsp_str_dbg(fsp),
6261 smb_fname_str_dbg(smb_fname_dst)));
6262 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6265 DEBUG(10,("smb_file_rename_information: "
6266 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6267 smb_fname_str_dbg(smb_fname_src),
6268 smb_fname_str_dbg(smb_fname_dst)));
6269 status = rename_internals(ctx, conn, req, smb_fname_src,
6270 smb_fname_dst, 0, overwrite, false,
6272 FILE_WRITE_ATTRIBUTES);
6275 TALLOC_FREE(smb_fname_dst);
6279 /****************************************************************************
6280 Deal with SMB_SET_POSIX_ACL.
6281 ****************************************************************************/
6283 #if defined(HAVE_POSIX_ACLS)
6284 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6288 const struct smb_filename *smb_fname)
6290 uint16 posix_acl_version;
6291 uint16 num_file_acls;
6292 uint16 num_def_acls;
6293 bool valid_file_acls = True;
6294 bool valid_def_acls = True;
6296 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6297 return NT_STATUS_INVALID_PARAMETER;
6299 posix_acl_version = SVAL(pdata,0);
6300 num_file_acls = SVAL(pdata,2);
6301 num_def_acls = SVAL(pdata,4);
6303 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6304 valid_file_acls = False;
6308 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6309 valid_def_acls = False;
6313 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6314 return NT_STATUS_INVALID_PARAMETER;
6317 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6318 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6319 return NT_STATUS_INVALID_PARAMETER;
6322 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6323 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6324 (unsigned int)num_file_acls,
6325 (unsigned int)num_def_acls));
6327 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6328 smb_fname->base_name, num_file_acls,
6329 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6330 return map_nt_error_from_unix(errno);
6333 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6334 smb_fname->base_name, &smb_fname->st, num_def_acls,
6335 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6336 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6337 return map_nt_error_from_unix(errno);
6339 return NT_STATUS_OK;
6343 /****************************************************************************
6344 Deal with SMB_SET_POSIX_LOCK.
6345 ****************************************************************************/
6347 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6348 struct smb_request *req,
6356 bool blocking_lock = False;
6357 enum brl_type lock_type;
6359 NTSTATUS status = NT_STATUS_OK;
6361 if (fsp == NULL || fsp->fh->fd == -1) {
6362 return NT_STATUS_INVALID_HANDLE;
6365 if (total_data != POSIX_LOCK_DATA_SIZE) {
6366 return NT_STATUS_INVALID_PARAMETER;
6369 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6370 case POSIX_LOCK_TYPE_READ:
6371 lock_type = READ_LOCK;
6373 case POSIX_LOCK_TYPE_WRITE:
6374 /* Return the right POSIX-mappable error code for files opened read-only. */
6375 if (!fsp->can_write) {
6376 return NT_STATUS_INVALID_HANDLE;
6378 lock_type = WRITE_LOCK;
6380 case POSIX_LOCK_TYPE_UNLOCK:
6381 lock_type = UNLOCK_LOCK;
6384 return NT_STATUS_INVALID_PARAMETER;
6387 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6388 blocking_lock = False;
6389 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6390 blocking_lock = True;
6392 return NT_STATUS_INVALID_PARAMETER;
6395 if (!lp_blocking_locks(SNUM(conn))) {
6396 blocking_lock = False;
6399 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6400 #if defined(HAVE_LONGLONG)
6401 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6402 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6403 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6404 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6405 #else /* HAVE_LONGLONG */
6406 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6407 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6408 #endif /* HAVE_LONGLONG */
6410 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6411 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6413 (unsigned int)lock_type,
6414 (unsigned long long)smblctx,
6418 if (lock_type == UNLOCK_LOCK) {
6419 status = do_unlock(req->sconn->msg_ctx,
6426 uint64_t block_smblctx;
6428 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6440 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6442 * A blocking lock was requested. Package up
6443 * this smb into a queued request and push it
6444 * onto the blocking lock queue.
6446 if(push_blocking_lock_request(br_lck,
6449 -1, /* infinite timeout. */
6457 TALLOC_FREE(br_lck);
6461 TALLOC_FREE(br_lck);
6467 /****************************************************************************
6468 Deal with SMB_SET_FILE_BASIC_INFO.
6469 ****************************************************************************/
6471 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6475 const struct smb_filename *smb_fname)
6477 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6478 struct smb_file_time ft;
6480 NTSTATUS status = NT_STATUS_OK;
6484 if (total_data < 36) {
6485 return NT_STATUS_INVALID_PARAMETER;
6488 /* Set the attributes */
6489 dosmode = IVAL(pdata,32);
6490 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6491 if (!NT_STATUS_IS_OK(status)) {
6496 ft.create_time = interpret_long_date(pdata);
6499 ft.atime = interpret_long_date(pdata+8);
6502 ft.mtime = interpret_long_date(pdata+16);
6505 ft.ctime = interpret_long_date(pdata+24);
6507 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6508 smb_fname_str_dbg(smb_fname)));
6510 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6514 /****************************************************************************
6515 Deal with SMB_INFO_STANDARD.
6516 ****************************************************************************/
6518 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6522 const struct smb_filename *smb_fname)
6524 struct smb_file_time ft;
6528 if (total_data < 12) {
6529 return NT_STATUS_INVALID_PARAMETER;
6533 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6535 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6537 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6539 DEBUG(10,("smb_set_info_standard: file %s\n",
6540 smb_fname_str_dbg(smb_fname)));
6542 return smb_set_file_time(conn,
6549 /****************************************************************************
6550 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6551 ****************************************************************************/
6553 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6554 struct smb_request *req,
6558 struct smb_filename *smb_fname)
6560 uint64_t allocation_size = 0;
6561 NTSTATUS status = NT_STATUS_OK;
6562 files_struct *new_fsp = NULL;
6564 if (!VALID_STAT(smb_fname->st)) {
6565 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6568 if (total_data < 8) {
6569 return NT_STATUS_INVALID_PARAMETER;
6572 allocation_size = (uint64_t)IVAL(pdata,0);
6573 #ifdef LARGE_SMB_OFF_T
6574 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6575 #else /* LARGE_SMB_OFF_T */
6576 if (IVAL(pdata,4) != 0) {
6577 /* more than 32 bits? */
6578 return NT_STATUS_INVALID_PARAMETER;
6580 #endif /* LARGE_SMB_OFF_T */
6582 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6583 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6584 (double)allocation_size));
6586 if (allocation_size) {
6587 allocation_size = smb_roundup(conn, allocation_size);
6590 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6591 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6592 (double)allocation_size));
6594 if (fsp && fsp->fh->fd != -1) {
6595 /* Open file handle. */
6596 /* Only change if needed. */
6597 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6598 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6599 return map_nt_error_from_unix(errno);
6602 /* But always update the time. */
6604 * This is equivalent to a write. Ensure it's seen immediately
6605 * if there are no pending writes.
6607 trigger_write_time_update_immediate(fsp);
6608 return NT_STATUS_OK;
6611 /* Pathname or stat or directory file. */
6612 status = SMB_VFS_CREATE_FILE(
6615 0, /* root_dir_fid */
6616 smb_fname, /* fname */
6617 FILE_WRITE_DATA, /* access_mask */
6618 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6620 FILE_OPEN, /* create_disposition*/
6621 0, /* create_options */
6622 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6623 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6624 0, /* allocation_size */
6625 0, /* private_flags */
6628 &new_fsp, /* result */
6631 if (!NT_STATUS_IS_OK(status)) {
6632 /* NB. We check for open_was_deferred in the caller. */
6636 /* Only change if needed. */
6637 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6638 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6639 status = map_nt_error_from_unix(errno);
6640 close_file(req, new_fsp, NORMAL_CLOSE);
6645 /* Changing the allocation size should set the last mod time. */
6647 * This is equivalent to a write. Ensure it's seen immediately
6648 * if there are no pending writes.
6650 trigger_write_time_update_immediate(new_fsp);
6652 close_file(req, new_fsp, NORMAL_CLOSE);
6653 return NT_STATUS_OK;
6656 /****************************************************************************
6657 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6658 ****************************************************************************/
6660 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6661 struct smb_request *req,
6665 const struct smb_filename *smb_fname,
6666 bool fail_after_createfile)
6670 if (total_data < 8) {
6671 return NT_STATUS_INVALID_PARAMETER;
6674 size = IVAL(pdata,0);
6675 #ifdef LARGE_SMB_OFF_T
6676 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6677 #else /* LARGE_SMB_OFF_T */
6678 if (IVAL(pdata,4) != 0) {
6679 /* more than 32 bits? */
6680 return NT_STATUS_INVALID_PARAMETER;
6682 #endif /* LARGE_SMB_OFF_T */
6683 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6684 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6687 return smb_set_file_size(conn, req,
6692 fail_after_createfile);
6695 /****************************************************************************
6696 Allow a UNIX info mknod.
6697 ****************************************************************************/
6699 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6702 const struct smb_filename *smb_fname)
6704 uint32 file_type = IVAL(pdata,56);
6705 #if defined(HAVE_MAKEDEV)
6706 uint32 dev_major = IVAL(pdata,60);
6707 uint32 dev_minor = IVAL(pdata,68);
6709 SMB_DEV_T dev = (SMB_DEV_T)0;
6710 uint32 raw_unixmode = IVAL(pdata,84);
6714 if (total_data < 100) {
6715 return NT_STATUS_INVALID_PARAMETER;
6718 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6719 PERM_NEW_FILE, &unixmode);
6720 if (!NT_STATUS_IS_OK(status)) {
6724 #if defined(HAVE_MAKEDEV)
6725 dev = makedev(dev_major, dev_minor);
6728 switch (file_type) {
6729 #if defined(S_IFIFO)
6730 case UNIX_TYPE_FIFO:
6731 unixmode |= S_IFIFO;
6734 #if defined(S_IFSOCK)
6735 case UNIX_TYPE_SOCKET:
6736 unixmode |= S_IFSOCK;
6739 #if defined(S_IFCHR)
6740 case UNIX_TYPE_CHARDEV:
6741 unixmode |= S_IFCHR;
6744 #if defined(S_IFBLK)
6745 case UNIX_TYPE_BLKDEV:
6746 unixmode |= S_IFBLK;
6750 return NT_STATUS_INVALID_PARAMETER;
6753 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6754 "%.0f mode 0%o for file %s\n", (double)dev,
6755 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6757 /* Ok - do the mknod. */
6758 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6759 return map_nt_error_from_unix(errno);
6762 /* If any of the other "set" calls fail we
6763 * don't want to end up with a half-constructed mknod.
6766 if (lp_inherit_perms(SNUM(conn))) {
6768 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6770 return NT_STATUS_NO_MEMORY;
6772 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6774 TALLOC_FREE(parent);
6777 return NT_STATUS_OK;
6780 /****************************************************************************
6781 Deal with SMB_SET_FILE_UNIX_BASIC.
6782 ****************************************************************************/
6784 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6785 struct smb_request *req,
6789 const struct smb_filename *smb_fname)
6791 struct smb_file_time ft;
6792 uint32 raw_unixmode;
6795 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6796 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6797 NTSTATUS status = NT_STATUS_OK;
6798 bool delete_on_fail = False;
6799 enum perm_type ptype;
6800 files_struct *all_fsps = NULL;
6801 bool modify_mtime = true;
6803 struct smb_filename *smb_fname_tmp = NULL;
6804 SMB_STRUCT_STAT sbuf;
6808 if (total_data < 100) {
6809 return NT_STATUS_INVALID_PARAMETER;
6812 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6813 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6814 size=IVAL(pdata,0); /* first 8 Bytes are size */
6815 #ifdef LARGE_SMB_OFF_T
6816 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6817 #else /* LARGE_SMB_OFF_T */
6818 if (IVAL(pdata,4) != 0) {
6819 /* more than 32 bits? */
6820 return NT_STATUS_INVALID_PARAMETER;
6822 #endif /* LARGE_SMB_OFF_T */
6825 ft.atime = interpret_long_date(pdata+24); /* access_time */
6826 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6827 set_owner = (uid_t)IVAL(pdata,40);
6828 set_grp = (gid_t)IVAL(pdata,48);
6829 raw_unixmode = IVAL(pdata,84);
6831 if (VALID_STAT(smb_fname->st)) {
6832 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6833 ptype = PERM_EXISTING_DIR;
6835 ptype = PERM_EXISTING_FILE;
6838 ptype = PERM_NEW_FILE;
6841 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6843 if (!NT_STATUS_IS_OK(status)) {
6847 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6848 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6849 smb_fname_str_dbg(smb_fname), (double)size,
6850 (unsigned int)set_owner, (unsigned int)set_grp,
6851 (int)raw_unixmode));
6853 sbuf = smb_fname->st;
6855 if (!VALID_STAT(sbuf)) {
6857 * The only valid use of this is to create character and block
6858 * devices, and named pipes. This is deprecated (IMHO) and
6859 * a new info level should be used for mknod. JRA.
6862 status = smb_unix_mknod(conn,
6866 if (!NT_STATUS_IS_OK(status)) {
6870 status = copy_smb_filename(talloc_tos(), smb_fname,
6872 if (!NT_STATUS_IS_OK(status)) {
6876 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6877 status = map_nt_error_from_unix(errno);
6878 TALLOC_FREE(smb_fname_tmp);
6879 SMB_VFS_UNLINK(conn, smb_fname);
6883 sbuf = smb_fname_tmp->st;
6884 smb_fname = smb_fname_tmp;
6886 /* Ensure we don't try and change anything else. */
6887 raw_unixmode = SMB_MODE_NO_CHANGE;
6888 size = get_file_size_stat(&sbuf);
6889 ft.atime = sbuf.st_ex_atime;
6890 ft.mtime = sbuf.st_ex_mtime;
6892 * We continue here as we might want to change the
6895 delete_on_fail = True;
6899 /* Horrible backwards compatibility hack as an old server bug
6900 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6904 size = get_file_size_stat(&sbuf);
6909 * Deal with the UNIX specific mode set.
6912 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6913 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6914 "setting mode 0%o for file %s\n",
6915 (unsigned int)unixmode,
6916 smb_fname_str_dbg(smb_fname)));
6917 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6918 return map_nt_error_from_unix(errno);
6923 * Deal with the UNIX specific uid set.
6926 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6927 (sbuf.st_ex_uid != set_owner)) {
6930 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6931 "changing owner %u for path %s\n",
6932 (unsigned int)set_owner,
6933 smb_fname_str_dbg(smb_fname)));
6935 if (S_ISLNK(sbuf.st_ex_mode)) {
6936 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6937 set_owner, (gid_t)-1);
6939 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6940 set_owner, (gid_t)-1);
6944 status = map_nt_error_from_unix(errno);
6945 if (delete_on_fail) {
6946 SMB_VFS_UNLINK(conn, smb_fname);
6953 * Deal with the UNIX specific gid set.
6956 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6957 (sbuf.st_ex_gid != set_grp)) {
6958 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6959 "changing group %u for file %s\n",
6960 (unsigned int)set_owner,
6961 smb_fname_str_dbg(smb_fname)));
6962 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6964 status = map_nt_error_from_unix(errno);
6965 if (delete_on_fail) {
6966 SMB_VFS_UNLINK(conn, smb_fname);
6972 /* Deal with any size changes. */
6974 status = smb_set_file_size(conn, req,
6980 if (!NT_STATUS_IS_OK(status)) {
6984 /* Deal with any time changes. */
6985 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6986 /* No change, don't cancel anything. */
6990 id = vfs_file_id_from_sbuf(conn, &sbuf);
6991 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
6992 all_fsps = file_find_di_next(all_fsps)) {
6994 * We're setting the time explicitly for UNIX.
6995 * Cancel any pending changes over all handles.
6997 all_fsps->update_write_time_on_close = false;
6998 TALLOC_FREE(all_fsps->update_write_time_event);
7002 * Override the "setting_write_time"
7003 * parameter here as it almost does what
7004 * we need. Just remember if we modified
7005 * mtime and send the notify ourselves.
7007 if (null_timespec(ft.mtime)) {
7008 modify_mtime = false;
7011 status = smb_set_file_time(conn,
7017 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7018 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7023 /****************************************************************************
7024 Deal with SMB_SET_FILE_UNIX_INFO2.
7025 ****************************************************************************/
7027 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7028 struct smb_request *req,
7032 const struct smb_filename *smb_fname)
7038 if (total_data < 116) {
7039 return NT_STATUS_INVALID_PARAMETER;
7042 /* Start by setting all the fields that are common between UNIX_BASIC
7045 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7047 if (!NT_STATUS_IS_OK(status)) {
7051 smb_fflags = IVAL(pdata, 108);
7052 smb_fmask = IVAL(pdata, 112);
7054 /* NB: We should only attempt to alter the file flags if the client
7055 * sends a non-zero mask.
7057 if (smb_fmask != 0) {
7058 int stat_fflags = 0;
7060 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7061 smb_fmask, &stat_fflags)) {
7062 /* Client asked to alter a flag we don't understand. */
7063 return NT_STATUS_INVALID_PARAMETER;
7066 if (fsp && fsp->fh->fd != -1) {
7067 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7068 return NT_STATUS_NOT_SUPPORTED;
7070 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7071 stat_fflags) != 0) {
7072 return map_nt_error_from_unix(errno);
7077 /* XXX: need to add support for changing the create_time here. You
7078 * can do this for paths on Darwin with setattrlist(2). The right way
7079 * to hook this up is probably by extending the VFS utimes interface.
7082 return NT_STATUS_OK;
7085 /****************************************************************************
7086 Create a directory with POSIX semantics.
7087 ****************************************************************************/
7089 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7090 struct smb_request *req,
7093 struct smb_filename *smb_fname,
7094 int *pdata_return_size)
7096 NTSTATUS status = NT_STATUS_OK;
7097 uint32 raw_unixmode = 0;
7098 uint32 mod_unixmode = 0;
7099 mode_t unixmode = (mode_t)0;
7100 files_struct *fsp = NULL;
7101 uint16 info_level_return = 0;
7103 char *pdata = *ppdata;
7105 if (total_data < 18) {
7106 return NT_STATUS_INVALID_PARAMETER;
7109 raw_unixmode = IVAL(pdata,8);
7110 /* Next 4 bytes are not yet defined. */
7112 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7113 PERM_NEW_DIR, &unixmode);
7114 if (!NT_STATUS_IS_OK(status)) {
7118 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7120 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7121 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7123 status = SMB_VFS_CREATE_FILE(
7126 0, /* root_dir_fid */
7127 smb_fname, /* fname */
7128 FILE_READ_ATTRIBUTES, /* access_mask */
7129 FILE_SHARE_NONE, /* share_access */
7130 FILE_CREATE, /* create_disposition*/
7131 FILE_DIRECTORY_FILE, /* create_options */
7132 mod_unixmode, /* file_attributes */
7133 0, /* oplock_request */
7134 0, /* allocation_size */
7135 0, /* private_flags */
7141 if (NT_STATUS_IS_OK(status)) {
7142 close_file(req, fsp, NORMAL_CLOSE);
7145 info_level_return = SVAL(pdata,16);
7147 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7148 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7149 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7150 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7152 *pdata_return_size = 12;
7155 /* Realloc the data size */
7156 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7157 if (*ppdata == NULL) {
7158 *pdata_return_size = 0;
7159 return NT_STATUS_NO_MEMORY;
7163 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7164 SSVAL(pdata,2,0); /* No fnum. */
7165 SIVAL(pdata,4,info); /* Was directory created. */
7167 switch (info_level_return) {
7168 case SMB_QUERY_FILE_UNIX_BASIC:
7169 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7170 SSVAL(pdata,10,0); /* Padding. */
7171 store_file_unix_basic(conn, pdata + 12, fsp,
7174 case SMB_QUERY_FILE_UNIX_INFO2:
7175 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7176 SSVAL(pdata,10,0); /* Padding. */
7177 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7181 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7182 SSVAL(pdata,10,0); /* Padding. */
7189 /****************************************************************************
7190 Open/Create a file with POSIX semantics.
7191 ****************************************************************************/
7193 static NTSTATUS smb_posix_open(connection_struct *conn,
7194 struct smb_request *req,
7197 struct smb_filename *smb_fname,
7198 int *pdata_return_size)
7200 bool extended_oplock_granted = False;
7201 char *pdata = *ppdata;
7203 uint32 wire_open_mode = 0;
7204 uint32 raw_unixmode = 0;
7205 uint32 mod_unixmode = 0;
7206 uint32 create_disp = 0;
7207 uint32 access_mask = 0;
7208 uint32 create_options = 0;
7209 NTSTATUS status = NT_STATUS_OK;
7210 mode_t unixmode = (mode_t)0;
7211 files_struct *fsp = NULL;
7212 int oplock_request = 0;
7214 uint16 info_level_return = 0;
7216 if (total_data < 18) {
7217 return NT_STATUS_INVALID_PARAMETER;
7220 flags = IVAL(pdata,0);
7221 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7222 if (oplock_request) {
7223 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7226 wire_open_mode = IVAL(pdata,4);
7228 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7229 return smb_posix_mkdir(conn, req,
7236 switch (wire_open_mode & SMB_ACCMODE) {
7238 access_mask = FILE_READ_DATA;
7241 access_mask = FILE_WRITE_DATA;
7244 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7247 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7248 (unsigned int)wire_open_mode ));
7249 return NT_STATUS_INVALID_PARAMETER;
7252 wire_open_mode &= ~SMB_ACCMODE;
7254 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7255 create_disp = FILE_CREATE;
7256 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7257 create_disp = FILE_OVERWRITE_IF;
7258 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7259 create_disp = FILE_OPEN_IF;
7260 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7261 create_disp = FILE_OPEN;
7263 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7264 (unsigned int)wire_open_mode ));
7265 return NT_STATUS_INVALID_PARAMETER;
7268 raw_unixmode = IVAL(pdata,8);
7269 /* Next 4 bytes are not yet defined. */
7271 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7272 (VALID_STAT(smb_fname->st) ?
7273 PERM_EXISTING_FILE : PERM_NEW_FILE),
7276 if (!NT_STATUS_IS_OK(status)) {
7280 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7282 if (wire_open_mode & SMB_O_SYNC) {
7283 create_options |= FILE_WRITE_THROUGH;
7285 if (wire_open_mode & SMB_O_APPEND) {
7286 access_mask |= FILE_APPEND_DATA;
7288 if (wire_open_mode & SMB_O_DIRECT) {
7289 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7292 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7293 smb_fname_str_dbg(smb_fname),
7294 (unsigned int)wire_open_mode,
7295 (unsigned int)unixmode ));
7297 status = SMB_VFS_CREATE_FILE(
7300 0, /* root_dir_fid */
7301 smb_fname, /* fname */
7302 access_mask, /* access_mask */
7303 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7305 create_disp, /* create_disposition*/
7306 FILE_NON_DIRECTORY_FILE, /* create_options */
7307 mod_unixmode, /* file_attributes */
7308 oplock_request, /* oplock_request */
7309 0, /* allocation_size */
7310 0, /* private_flags */
7316 if (!NT_STATUS_IS_OK(status)) {
7320 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7321 extended_oplock_granted = True;
7324 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7325 extended_oplock_granted = True;
7328 info_level_return = SVAL(pdata,16);
7330 /* Allocate the correct return size. */
7332 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7333 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7334 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7335 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7337 *pdata_return_size = 12;
7340 /* Realloc the data size */
7341 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7342 if (*ppdata == NULL) {
7343 close_file(req, fsp, ERROR_CLOSE);
7344 *pdata_return_size = 0;
7345 return NT_STATUS_NO_MEMORY;
7349 if (extended_oplock_granted) {
7350 if (flags & REQUEST_BATCH_OPLOCK) {
7351 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7353 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7355 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7356 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7358 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7361 SSVAL(pdata,2,fsp->fnum);
7362 SIVAL(pdata,4,info); /* Was file created etc. */
7364 switch (info_level_return) {
7365 case SMB_QUERY_FILE_UNIX_BASIC:
7366 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7367 SSVAL(pdata,10,0); /* padding. */
7368 store_file_unix_basic(conn, pdata + 12, fsp,
7371 case SMB_QUERY_FILE_UNIX_INFO2:
7372 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7373 SSVAL(pdata,10,0); /* padding. */
7374 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7378 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7379 SSVAL(pdata,10,0); /* padding. */
7382 return NT_STATUS_OK;
7385 /****************************************************************************
7386 Delete a file with POSIX semantics.
7387 ****************************************************************************/
7389 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7390 struct smb_request *req,
7393 struct smb_filename *smb_fname)
7395 NTSTATUS status = NT_STATUS_OK;
7396 files_struct *fsp = NULL;
7400 int create_options = 0;
7402 struct share_mode_lock *lck = NULL;
7404 if (total_data < 2) {
7405 return NT_STATUS_INVALID_PARAMETER;
7408 flags = SVAL(pdata,0);
7410 if (!VALID_STAT(smb_fname->st)) {
7411 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7414 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7415 !VALID_STAT_OF_DIR(smb_fname->st)) {
7416 return NT_STATUS_NOT_A_DIRECTORY;
7419 DEBUG(10,("smb_posix_unlink: %s %s\n",
7420 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7421 smb_fname_str_dbg(smb_fname)));
7423 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7424 create_options |= FILE_DIRECTORY_FILE;
7427 status = SMB_VFS_CREATE_FILE(
7430 0, /* root_dir_fid */
7431 smb_fname, /* fname */
7432 DELETE_ACCESS, /* access_mask */
7433 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7435 FILE_OPEN, /* create_disposition*/
7436 create_options, /* create_options */
7437 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7438 0, /* oplock_request */
7439 0, /* allocation_size */
7440 0, /* private_flags */
7446 if (!NT_STATUS_IS_OK(status)) {
7451 * Don't lie to client. If we can't really delete due to
7452 * non-POSIX opens return SHARING_VIOLATION.
7455 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7458 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7459 "lock for file %s\n", fsp_str_dbg(fsp)));
7460 close_file(req, fsp, NORMAL_CLOSE);
7461 return NT_STATUS_INVALID_PARAMETER;
7465 * See if others still have the file open. If this is the case, then
7466 * don't delete. If all opens are POSIX delete we can set the delete
7467 * on close disposition.
7469 for (i=0; i<lck->num_share_modes; i++) {
7470 struct share_mode_entry *e = &lck->share_modes[i];
7471 if (is_valid_share_mode_entry(e)) {
7472 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7475 /* Fail with sharing violation. */
7476 close_file(req, fsp, NORMAL_CLOSE);
7478 return NT_STATUS_SHARING_VIOLATION;
7483 * Set the delete on close.
7485 status = smb_set_file_disposition_info(conn,
7491 if (!NT_STATUS_IS_OK(status)) {
7492 close_file(req, fsp, NORMAL_CLOSE);
7497 return close_file(req, fsp, NORMAL_CLOSE);
7500 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7501 struct smb_request *req,
7502 TALLOC_CTX *mem_ctx,
7503 uint16_t info_level,
7505 struct smb_filename *smb_fname,
7506 char **ppdata, int total_data,
7509 char *pdata = *ppdata;
7510 NTSTATUS status = NT_STATUS_OK;
7511 int data_return_size = 0;
7515 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7516 return NT_STATUS_INVALID_LEVEL;
7519 if (!CAN_WRITE(conn)) {
7520 /* Allow POSIX opens. The open path will deny
7521 * any non-readonly opens. */
7522 if (info_level != SMB_POSIX_PATH_OPEN) {
7523 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7527 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7528 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7529 fsp ? fsp->fnum : -1, info_level, total_data));
7531 switch (info_level) {
7533 case SMB_INFO_STANDARD:
7535 status = smb_set_info_standard(conn,
7543 case SMB_INFO_SET_EA:
7545 status = smb_info_set_ea(conn,
7553 case SMB_SET_FILE_BASIC_INFO:
7554 case SMB_FILE_BASIC_INFORMATION:
7556 status = smb_set_file_basic_info(conn,
7564 case SMB_FILE_ALLOCATION_INFORMATION:
7565 case SMB_SET_FILE_ALLOCATION_INFO:
7567 status = smb_set_file_allocation_info(conn, req,
7575 case SMB_FILE_END_OF_FILE_INFORMATION:
7576 case SMB_SET_FILE_END_OF_FILE_INFO:
7579 * XP/Win7 both fail after the createfile with
7580 * SMB_SET_FILE_END_OF_FILE_INFO but not
7581 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7582 * The level is known here, so pass it down
7586 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7588 status = smb_set_file_end_of_file_info(conn, req,
7597 case SMB_FILE_DISPOSITION_INFORMATION:
7598 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7601 /* JRA - We used to just ignore this on a path ?
7602 * Shouldn't this be invalid level on a pathname
7605 if (tran_call != TRANSACT2_SETFILEINFO) {
7606 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7609 status = smb_set_file_disposition_info(conn,
7617 case SMB_FILE_POSITION_INFORMATION:
7619 status = smb_file_position_information(conn,
7626 case SMB_FILE_FULL_EA_INFORMATION:
7628 status = smb_set_file_full_ea_info(conn,
7635 /* From tridge Samba4 :
7636 * MODE_INFORMATION in setfileinfo (I have no
7637 * idea what "mode information" on a file is - it takes a value of 0,
7638 * 2, 4 or 6. What could it be?).
7641 case SMB_FILE_MODE_INFORMATION:
7643 status = smb_file_mode_information(conn,
7650 * CIFS UNIX extensions.
7653 case SMB_SET_FILE_UNIX_BASIC:
7655 status = smb_set_file_unix_basic(conn, req,
7663 case SMB_SET_FILE_UNIX_INFO2:
7665 status = smb_set_file_unix_info2(conn, req,
7673 case SMB_SET_FILE_UNIX_LINK:
7676 /* We must have a pathname for this. */
7677 return NT_STATUS_INVALID_LEVEL;
7679 status = smb_set_file_unix_link(conn, req, pdata,
7680 total_data, smb_fname);
7684 case SMB_SET_FILE_UNIX_HLINK:
7687 /* We must have a pathname for this. */
7688 return NT_STATUS_INVALID_LEVEL;
7690 status = smb_set_file_unix_hlink(conn, req,
7696 case SMB_FILE_RENAME_INFORMATION:
7698 status = smb_file_rename_information(conn, req,
7704 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7706 /* SMB2 rename information. */
7707 status = smb2_file_rename_information(conn, req,
7713 case SMB_FILE_LINK_INFORMATION:
7715 status = smb_file_link_information(conn, req,
7721 #if defined(HAVE_POSIX_ACLS)
7722 case SMB_SET_POSIX_ACL:
7724 status = smb_set_posix_acl(conn,
7733 case SMB_SET_POSIX_LOCK:
7736 return NT_STATUS_INVALID_LEVEL;
7738 status = smb_set_posix_lock(conn, req,
7739 pdata, total_data, fsp);
7743 case SMB_POSIX_PATH_OPEN:
7746 /* We must have a pathname for this. */
7747 return NT_STATUS_INVALID_LEVEL;
7750 status = smb_posix_open(conn, req,
7758 case SMB_POSIX_PATH_UNLINK:
7761 /* We must have a pathname for this. */
7762 return NT_STATUS_INVALID_LEVEL;
7765 status = smb_posix_unlink(conn, req,
7773 return NT_STATUS_INVALID_LEVEL;
7776 if (!NT_STATUS_IS_OK(status)) {
7780 *ret_data_size = data_return_size;
7781 return NT_STATUS_OK;
7784 /****************************************************************************
7785 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7786 ****************************************************************************/
7788 static void call_trans2setfilepathinfo(connection_struct *conn,
7789 struct smb_request *req,
7790 unsigned int tran_call,
7791 char **pparams, int total_params,
7792 char **ppdata, int total_data,
7793 unsigned int max_data_bytes)
7795 char *params = *pparams;
7796 char *pdata = *ppdata;
7798 struct smb_filename *smb_fname = NULL;
7799 files_struct *fsp = NULL;
7800 NTSTATUS status = NT_STATUS_OK;
7801 int data_return_size = 0;
7804 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7808 if (tran_call == TRANSACT2_SETFILEINFO) {
7809 if (total_params < 4) {
7810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7814 fsp = file_fsp(req, SVAL(params,0));
7815 /* Basic check for non-null fsp. */
7816 if (!check_fsp_open(conn, req, fsp)) {
7819 info_level = SVAL(params,2);
7821 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7823 if (!NT_STATUS_IS_OK(status)) {
7824 reply_nterror(req, status);
7828 if(fsp->is_directory || fsp->fh->fd == -1) {
7830 * This is actually a SETFILEINFO on a directory
7831 * handle (returned from an NT SMB). NT5.0 seems
7832 * to do this call. JRA.
7834 if (INFO_LEVEL_IS_UNIX(info_level)) {
7835 /* Always do lstat for UNIX calls. */
7836 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7837 DEBUG(3,("call_trans2setfilepathinfo: "
7838 "SMB_VFS_LSTAT of %s failed "
7840 smb_fname_str_dbg(smb_fname),
7842 reply_nterror(req, map_nt_error_from_unix(errno));
7846 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7847 DEBUG(3,("call_trans2setfilepathinfo: "
7848 "fileinfo of %s failed (%s)\n",
7849 smb_fname_str_dbg(smb_fname),
7851 reply_nterror(req, map_nt_error_from_unix(errno));
7855 } else if (fsp->print_file) {
7857 * Doing a DELETE_ON_CLOSE should cancel a print job.
7859 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7860 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7862 DEBUG(3,("call_trans2setfilepathinfo: "
7863 "Cancelling print job (%s)\n",
7867 send_trans2_replies(conn, req, params, 2,
7873 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7878 * Original code - this is an open file.
7880 if (!check_fsp(conn, req, fsp)) {
7884 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7885 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7886 "of fnum %d failed (%s)\n", fsp->fnum,
7888 reply_nterror(req, map_nt_error_from_unix(errno));
7896 if (total_params < 7) {
7897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7901 info_level = SVAL(params,0);
7902 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7903 total_params - 6, STR_TERMINATE,
7905 if (!NT_STATUS_IS_OK(status)) {
7906 reply_nterror(req, status);
7910 status = filename_convert(req, conn,
7911 req->flags2 & FLAGS2_DFS_PATHNAMES,
7916 if (!NT_STATUS_IS_OK(status)) {
7917 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7918 reply_botherror(req,
7919 NT_STATUS_PATH_NOT_COVERED,
7920 ERRSRV, ERRbadpath);
7923 reply_nterror(req, status);
7927 if (INFO_LEVEL_IS_UNIX(info_level)) {
7929 * For CIFS UNIX extensions the target name may not exist.
7932 /* Always do lstat for UNIX calls. */
7933 SMB_VFS_LSTAT(conn, smb_fname);
7935 } else if (!VALID_STAT(smb_fname->st) &&
7936 SMB_VFS_STAT(conn, smb_fname)) {
7937 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7939 smb_fname_str_dbg(smb_fname),
7941 reply_nterror(req, map_nt_error_from_unix(errno));
7946 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7947 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7948 fsp ? fsp->fnum : -1, info_level,total_data));
7950 /* Realloc the parameter size */
7951 *pparams = (char *)SMB_REALLOC(*pparams,2);
7952 if (*pparams == NULL) {
7953 reply_nterror(req, NT_STATUS_NO_MEMORY);
7960 status = smbd_do_setfilepathinfo(conn, req, req,
7966 if (!NT_STATUS_IS_OK(status)) {
7967 if (open_was_deferred(req->mid)) {
7968 /* We have re-scheduled this call. */
7971 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
7972 /* We have re-scheduled this call. */
7975 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7976 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7977 ERRSRV, ERRbadpath);
7980 if (info_level == SMB_POSIX_PATH_OPEN) {
7981 reply_openerror(req, status);
7985 reply_nterror(req, status);
7989 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7995 /****************************************************************************
7996 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7997 ****************************************************************************/
7999 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8000 char **pparams, int total_params,
8001 char **ppdata, int total_data,
8002 unsigned int max_data_bytes)
8004 struct smb_filename *smb_dname = NULL;
8005 char *params = *pparams;
8006 char *pdata = *ppdata;
8007 char *directory = NULL;
8008 NTSTATUS status = NT_STATUS_OK;
8009 struct ea_list *ea_list = NULL;
8010 TALLOC_CTX *ctx = talloc_tos();
8012 if (!CAN_WRITE(conn)) {
8013 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8017 if (total_params < 5) {
8018 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8022 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8023 total_params - 4, STR_TERMINATE,
8025 if (!NT_STATUS_IS_OK(status)) {
8026 reply_nterror(req, status);
8030 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8032 status = filename_convert(ctx,
8034 req->flags2 & FLAGS2_DFS_PATHNAMES,
8040 if (!NT_STATUS_IS_OK(status)) {
8041 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8042 reply_botherror(req,
8043 NT_STATUS_PATH_NOT_COVERED,
8044 ERRSRV, ERRbadpath);
8047 reply_nterror(req, status);
8052 * OS/2 workplace shell seems to send SET_EA requests of "null"
8053 * length (4 bytes containing IVAL 4).
8054 * They seem to have no effect. Bug #3212. JRA.
8057 if (total_data && (total_data != 4)) {
8058 /* Any data in this call is an EA list. */
8059 if (total_data < 10) {
8060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8064 if (IVAL(pdata,0) > total_data) {
8065 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8066 IVAL(pdata,0), (unsigned int)total_data));
8067 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8071 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8078 if (!lp_ea_support(SNUM(conn))) {
8079 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8083 /* If total_data == 4 Windows doesn't care what values
8084 * are placed in that field, it just ignores them.
8085 * The System i QNTC IBM SMB client puts bad values here,
8086 * so ignore them. */
8088 status = create_directory(conn, req, smb_dname);
8090 if (!NT_STATUS_IS_OK(status)) {
8091 reply_nterror(req, status);
8095 /* Try and set any given EA. */
8097 status = set_ea(conn, NULL, smb_dname, ea_list);
8098 if (!NT_STATUS_IS_OK(status)) {
8099 reply_nterror(req, status);
8104 /* Realloc the parameter and data sizes */
8105 *pparams = (char *)SMB_REALLOC(*pparams,2);
8106 if(*pparams == NULL) {
8107 reply_nterror(req, NT_STATUS_NO_MEMORY);
8114 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8117 TALLOC_FREE(smb_dname);
8121 /****************************************************************************
8122 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8123 We don't actually do this - we just send a null response.
8124 ****************************************************************************/
8126 static void call_trans2findnotifyfirst(connection_struct *conn,
8127 struct smb_request *req,
8128 char **pparams, int total_params,
8129 char **ppdata, int total_data,
8130 unsigned int max_data_bytes)
8132 char *params = *pparams;
8135 if (total_params < 6) {
8136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8140 info_level = SVAL(params,4);
8141 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8143 switch (info_level) {
8148 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8152 /* Realloc the parameter and data sizes */
8153 *pparams = (char *)SMB_REALLOC(*pparams,6);
8154 if (*pparams == NULL) {
8155 reply_nterror(req, NT_STATUS_NO_MEMORY);
8160 SSVAL(params,0,fnf_handle);
8161 SSVAL(params,2,0); /* No changes */
8162 SSVAL(params,4,0); /* No EA errors */
8169 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8174 /****************************************************************************
8175 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8176 changes). Currently this does nothing.
8177 ****************************************************************************/
8179 static void call_trans2findnotifynext(connection_struct *conn,
8180 struct smb_request *req,
8181 char **pparams, int total_params,
8182 char **ppdata, int total_data,
8183 unsigned int max_data_bytes)
8185 char *params = *pparams;
8187 DEBUG(3,("call_trans2findnotifynext\n"));
8189 /* Realloc the parameter and data sizes */
8190 *pparams = (char *)SMB_REALLOC(*pparams,4);
8191 if (*pparams == NULL) {
8192 reply_nterror(req, NT_STATUS_NO_MEMORY);
8197 SSVAL(params,0,0); /* No changes */
8198 SSVAL(params,2,0); /* No EA errors */
8200 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8205 /****************************************************************************
8206 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8207 ****************************************************************************/
8209 static void call_trans2getdfsreferral(connection_struct *conn,
8210 struct smb_request *req,
8211 char **pparams, int total_params,
8212 char **ppdata, int total_data,
8213 unsigned int max_data_bytes)
8215 char *params = *pparams;
8216 char *pathname = NULL;
8218 int max_referral_level;
8219 NTSTATUS status = NT_STATUS_OK;
8220 TALLOC_CTX *ctx = talloc_tos();
8222 DEBUG(10,("call_trans2getdfsreferral\n"));
8224 if (total_params < 3) {
8225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8229 max_referral_level = SVAL(params,0);
8231 if(!lp_host_msdfs()) {
8232 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8236 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8237 total_params - 2, STR_TERMINATE);
8239 reply_nterror(req, NT_STATUS_NOT_FOUND);
8242 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8243 ppdata,&status)) < 0) {
8244 reply_nterror(req, status);
8248 SSVAL(req->inbuf, smb_flg2,
8249 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8250 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8255 #define LMCAT_SPL 0x53
8256 #define LMFUNC_GETJOBID 0x60
8258 /****************************************************************************
8259 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8260 ****************************************************************************/
8262 static void call_trans2ioctl(connection_struct *conn,
8263 struct smb_request *req,
8264 char **pparams, int total_params,
8265 char **ppdata, int total_data,
8266 unsigned int max_data_bytes)
8268 char *pdata = *ppdata;
8269 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8271 /* check for an invalid fid before proceeding */
8274 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8278 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8279 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8280 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8281 if (*ppdata == NULL) {
8282 reply_nterror(req, NT_STATUS_NO_MEMORY);
8287 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8288 CAN ACCEPT THIS IN UNICODE. JRA. */
8291 if (fsp->print_file) {
8292 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8296 srvstr_push(pdata, req->flags2, pdata + 2,
8297 global_myname(), 15,
8298 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8299 srvstr_push(pdata, req->flags2, pdata+18,
8300 lp_servicename(SNUM(conn)), 13,
8301 STR_ASCII|STR_TERMINATE); /* Service name */
8302 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8307 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8308 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8311 /****************************************************************************
8312 Reply to a SMBfindclose (stop trans2 directory search).
8313 ****************************************************************************/
8315 void reply_findclose(struct smb_request *req)
8318 struct smbd_server_connection *sconn = req->sconn;
8320 START_PROFILE(SMBfindclose);
8323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8324 END_PROFILE(SMBfindclose);
8328 dptr_num = SVALS(req->vwv+0, 0);
8330 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8332 dptr_close(sconn, &dptr_num);
8334 reply_outbuf(req, 0, 0);
8336 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8338 END_PROFILE(SMBfindclose);
8342 /****************************************************************************
8343 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8344 ****************************************************************************/
8346 void reply_findnclose(struct smb_request *req)
8350 START_PROFILE(SMBfindnclose);
8353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8354 END_PROFILE(SMBfindnclose);
8358 dptr_num = SVAL(req->vwv+0, 0);
8360 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8362 /* We never give out valid handles for a
8363 findnotifyfirst - so any dptr_num is ok here.
8366 reply_outbuf(req, 0, 0);
8368 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8370 END_PROFILE(SMBfindnclose);
8374 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8375 struct trans_state *state)
8377 if (get_Protocol() >= PROTOCOL_NT1) {
8378 req->flags2 |= 0x40; /* IS_LONG_NAME */
8379 SSVAL(req->inbuf,smb_flg2,req->flags2);
8382 if (conn->encrypt_level == Required && !req->encrypted) {
8383 if (state->call != TRANSACT2_QFSINFO &&
8384 state->call != TRANSACT2_SETFSINFO) {
8385 DEBUG(0,("handle_trans2: encryption required "
8387 (unsigned int)state->call));
8388 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8393 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8395 /* Now we must call the relevant TRANS2 function */
8396 switch(state->call) {
8397 case TRANSACT2_OPEN:
8399 START_PROFILE(Trans2_open);
8400 call_trans2open(conn, req,
8401 &state->param, state->total_param,
8402 &state->data, state->total_data,
8403 state->max_data_return);
8404 END_PROFILE(Trans2_open);
8408 case TRANSACT2_FINDFIRST:
8410 START_PROFILE(Trans2_findfirst);
8411 call_trans2findfirst(conn, req,
8412 &state->param, state->total_param,
8413 &state->data, state->total_data,
8414 state->max_data_return);
8415 END_PROFILE(Trans2_findfirst);
8419 case TRANSACT2_FINDNEXT:
8421 START_PROFILE(Trans2_findnext);
8422 call_trans2findnext(conn, req,
8423 &state->param, state->total_param,
8424 &state->data, state->total_data,
8425 state->max_data_return);
8426 END_PROFILE(Trans2_findnext);
8430 case TRANSACT2_QFSINFO:
8432 START_PROFILE(Trans2_qfsinfo);
8433 call_trans2qfsinfo(conn, req,
8434 &state->param, state->total_param,
8435 &state->data, state->total_data,
8436 state->max_data_return);
8437 END_PROFILE(Trans2_qfsinfo);
8441 case TRANSACT2_SETFSINFO:
8443 START_PROFILE(Trans2_setfsinfo);
8444 call_trans2setfsinfo(conn, req,
8445 &state->param, state->total_param,
8446 &state->data, state->total_data,
8447 state->max_data_return);
8448 END_PROFILE(Trans2_setfsinfo);
8452 case TRANSACT2_QPATHINFO:
8453 case TRANSACT2_QFILEINFO:
8455 START_PROFILE(Trans2_qpathinfo);
8456 call_trans2qfilepathinfo(conn, req, state->call,
8457 &state->param, state->total_param,
8458 &state->data, state->total_data,
8459 state->max_data_return);
8460 END_PROFILE(Trans2_qpathinfo);
8464 case TRANSACT2_SETPATHINFO:
8465 case TRANSACT2_SETFILEINFO:
8467 START_PROFILE(Trans2_setpathinfo);
8468 call_trans2setfilepathinfo(conn, req, state->call,
8469 &state->param, state->total_param,
8470 &state->data, state->total_data,
8471 state->max_data_return);
8472 END_PROFILE(Trans2_setpathinfo);
8476 case TRANSACT2_FINDNOTIFYFIRST:
8478 START_PROFILE(Trans2_findnotifyfirst);
8479 call_trans2findnotifyfirst(conn, req,
8480 &state->param, state->total_param,
8481 &state->data, state->total_data,
8482 state->max_data_return);
8483 END_PROFILE(Trans2_findnotifyfirst);
8487 case TRANSACT2_FINDNOTIFYNEXT:
8489 START_PROFILE(Trans2_findnotifynext);
8490 call_trans2findnotifynext(conn, req,
8491 &state->param, state->total_param,
8492 &state->data, state->total_data,
8493 state->max_data_return);
8494 END_PROFILE(Trans2_findnotifynext);
8498 case TRANSACT2_MKDIR:
8500 START_PROFILE(Trans2_mkdir);
8501 call_trans2mkdir(conn, req,
8502 &state->param, state->total_param,
8503 &state->data, state->total_data,
8504 state->max_data_return);
8505 END_PROFILE(Trans2_mkdir);
8509 case TRANSACT2_GET_DFS_REFERRAL:
8511 START_PROFILE(Trans2_get_dfs_referral);
8512 call_trans2getdfsreferral(conn, req,
8513 &state->param, state->total_param,
8514 &state->data, state->total_data,
8515 state->max_data_return);
8516 END_PROFILE(Trans2_get_dfs_referral);
8520 case TRANSACT2_IOCTL:
8522 START_PROFILE(Trans2_ioctl);
8523 call_trans2ioctl(conn, req,
8524 &state->param, state->total_param,
8525 &state->data, state->total_data,
8526 state->max_data_return);
8527 END_PROFILE(Trans2_ioctl);
8532 /* Error in request */
8533 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8534 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8538 /****************************************************************************
8539 Reply to a SMBtrans2.
8540 ****************************************************************************/
8542 void reply_trans2(struct smb_request *req)
8544 connection_struct *conn = req->conn;
8549 unsigned int tran_call;
8550 struct trans_state *state;
8553 START_PROFILE(SMBtrans2);
8555 if (req->wct < 14) {
8556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8557 END_PROFILE(SMBtrans2);
8561 dsoff = SVAL(req->vwv+12, 0);
8562 dscnt = SVAL(req->vwv+11, 0);
8563 psoff = SVAL(req->vwv+10, 0);
8564 pscnt = SVAL(req->vwv+9, 0);
8565 tran_call = SVAL(req->vwv+14, 0);
8567 result = allow_new_trans(conn->pending_trans, req->mid);
8568 if (!NT_STATUS_IS_OK(result)) {
8569 DEBUG(2, ("Got invalid trans2 request: %s\n",
8570 nt_errstr(result)));
8571 reply_nterror(req, result);
8572 END_PROFILE(SMBtrans2);
8577 switch (tran_call) {
8578 /* List the allowed trans2 calls on IPC$ */
8579 case TRANSACT2_OPEN:
8580 case TRANSACT2_GET_DFS_REFERRAL:
8581 case TRANSACT2_QFILEINFO:
8582 case TRANSACT2_QFSINFO:
8583 case TRANSACT2_SETFSINFO:
8586 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8587 END_PROFILE(SMBtrans2);
8592 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8593 DEBUG(0, ("talloc failed\n"));
8594 reply_nterror(req, NT_STATUS_NO_MEMORY);
8595 END_PROFILE(SMBtrans2);
8599 state->cmd = SMBtrans2;
8601 state->mid = req->mid;
8602 state->vuid = req->vuid;
8603 state->setup_count = SVAL(req->vwv+13, 0);
8604 state->setup = NULL;
8605 state->total_param = SVAL(req->vwv+0, 0);
8606 state->param = NULL;
8607 state->total_data = SVAL(req->vwv+1, 0);
8609 state->max_param_return = SVAL(req->vwv+2, 0);
8610 state->max_data_return = SVAL(req->vwv+3, 0);
8611 state->max_setup_return = SVAL(req->vwv+4, 0);
8612 state->close_on_completion = BITSETW(req->vwv+5, 0);
8613 state->one_way = BITSETW(req->vwv+5, 1);
8615 state->call = tran_call;
8617 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8618 is so as a sanity check */
8619 if (state->setup_count != 1) {
8621 * Need to have rc=0 for ioctl to get job id for OS/2.
8622 * Network printing will fail if function is not successful.
8623 * Similar function in reply.c will be used if protocol
8624 * is LANMAN1.0 instead of LM1.2X002.
8625 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8626 * outbuf doesn't have to be set(only job id is used).
8628 if ( (state->setup_count == 4)
8629 && (tran_call == TRANSACT2_IOCTL)
8630 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8631 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8632 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8634 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8635 DEBUG(2,("Transaction is %d\n",tran_call));
8637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8638 END_PROFILE(SMBtrans2);
8643 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8646 if (state->total_data) {
8648 if (trans_oob(state->total_data, 0, dscnt)
8649 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8653 /* Can't use talloc here, the core routines do realloc on the
8654 * params and data. */
8655 state->data = (char *)SMB_MALLOC(state->total_data);
8656 if (state->data == NULL) {
8657 DEBUG(0,("reply_trans2: data malloc fail for %u "
8658 "bytes !\n", (unsigned int)state->total_data));
8660 reply_nterror(req, NT_STATUS_NO_MEMORY);
8661 END_PROFILE(SMBtrans2);
8665 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8668 if (state->total_param) {
8670 if (trans_oob(state->total_param, 0, pscnt)
8671 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8675 /* Can't use talloc here, the core routines do realloc on the
8676 * params and data. */
8677 state->param = (char *)SMB_MALLOC(state->total_param);
8678 if (state->param == NULL) {
8679 DEBUG(0,("reply_trans: param malloc fail for %u "
8680 "bytes !\n", (unsigned int)state->total_param));
8681 SAFE_FREE(state->data);
8683 reply_nterror(req, NT_STATUS_NO_MEMORY);
8684 END_PROFILE(SMBtrans2);
8688 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8691 state->received_data = dscnt;
8692 state->received_param = pscnt;
8694 if ((state->received_param == state->total_param) &&
8695 (state->received_data == state->total_data)) {
8697 handle_trans2(conn, req, state);
8699 SAFE_FREE(state->data);
8700 SAFE_FREE(state->param);
8702 END_PROFILE(SMBtrans2);
8706 DLIST_ADD(conn->pending_trans, state);
8708 /* We need to send an interim response then receive the rest
8709 of the parameter/data bytes */
8710 reply_outbuf(req, 0, 0);
8711 show_msg((char *)req->outbuf);
8712 END_PROFILE(SMBtrans2);
8717 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8718 SAFE_FREE(state->data);
8719 SAFE_FREE(state->param);
8721 END_PROFILE(SMBtrans2);
8722 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8726 /****************************************************************************
8727 Reply to a SMBtranss2
8728 ****************************************************************************/
8730 void reply_transs2(struct smb_request *req)
8732 connection_struct *conn = req->conn;
8733 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8734 struct trans_state *state;
8736 START_PROFILE(SMBtranss2);
8738 show_msg((char *)req->inbuf);
8741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8742 END_PROFILE(SMBtranss2);
8746 for (state = conn->pending_trans; state != NULL;
8747 state = state->next) {
8748 if (state->mid == req->mid) {
8753 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8755 END_PROFILE(SMBtranss2);
8759 /* Revise state->total_param and state->total_data in case they have
8760 changed downwards */
8762 if (SVAL(req->vwv+0, 0) < state->total_param)
8763 state->total_param = SVAL(req->vwv+0, 0);
8764 if (SVAL(req->vwv+1, 0) < state->total_data)
8765 state->total_data = SVAL(req->vwv+1, 0);
8767 pcnt = SVAL(req->vwv+2, 0);
8768 poff = SVAL(req->vwv+3, 0);
8769 pdisp = SVAL(req->vwv+4, 0);
8771 dcnt = SVAL(req->vwv+5, 0);
8772 doff = SVAL(req->vwv+6, 0);
8773 ddisp = SVAL(req->vwv+7, 0);
8775 state->received_param += pcnt;
8776 state->received_data += dcnt;
8778 if ((state->received_data > state->total_data) ||
8779 (state->received_param > state->total_param))
8783 if (trans_oob(state->total_param, pdisp, pcnt)
8784 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8787 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8791 if (trans_oob(state->total_data, ddisp, dcnt)
8792 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8795 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8798 if ((state->received_param < state->total_param) ||
8799 (state->received_data < state->total_data)) {
8800 END_PROFILE(SMBtranss2);
8804 handle_trans2(conn, req, state);
8806 DLIST_REMOVE(conn->pending_trans, state);
8807 SAFE_FREE(state->data);
8808 SAFE_FREE(state->param);
8811 END_PROFILE(SMBtranss2);
8816 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8817 DLIST_REMOVE(conn->pending_trans, state);
8818 SAFE_FREE(state->data);
8819 SAFE_FREE(state->param);
8821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8822 END_PROFILE(SMBtranss2);