2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
41 #define DIR_ENTRY_SAFETY_MARGIN 4096
43 static char *store_file_unix_basic(connection_struct *conn,
46 const SMB_STRUCT_STAT *psbuf);
48 static char *store_file_unix_basic_info2(connection_struct *conn,
51 const SMB_STRUCT_STAT *psbuf);
53 /********************************************************************
54 The canonical "check access" based on object handle or path function.
55 ********************************************************************/
57 NTSTATUS check_access(connection_struct *conn,
59 const struct smb_filename *smb_fname,
63 if (!(fsp->access_mask & access_mask)) {
64 return NT_STATUS_ACCESS_DENIED;
67 NTSTATUS status = smbd_check_access_rights(conn,
70 if (!NT_STATUS_IS_OK(status)) {
77 /********************************************************************
78 Roundup a value to the nearest allocation roundup size boundary.
79 Only do this for Windows clients.
80 ********************************************************************/
82 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
84 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
86 /* Only roundup for Windows clients. */
87 enum remote_arch_types ra_type = get_remote_arch();
88 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
89 val = SMB_ROUNDUP(val,rval);
94 /********************************************************************
95 Create a 64 bit FileIndex. If the file is on the same device as
96 the root of the share, just return the 64-bit inode. If it isn't,
97 mangle as we used to do.
98 ********************************************************************/
100 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
103 if (conn->base_share_dev == psbuf->st_ex_dev) {
104 return (uint64_t)psbuf->st_ex_ino;
106 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
107 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
111 /****************************************************************************
112 Utility functions for dealing with extended attributes.
113 ****************************************************************************/
115 /****************************************************************************
116 Refuse to allow clients to overwrite our private xattrs.
117 ****************************************************************************/
119 static bool samba_private_attr_name(const char *unix_ea_name)
121 static const char * const prohibited_ea_names[] = {
122 SAMBA_POSIX_INHERITANCE_EA_NAME,
123 SAMBA_XATTR_DOS_ATTRIB,
131 for (i = 0; prohibited_ea_names[i]; i++) {
132 if (strequal( prohibited_ea_names[i], unix_ea_name))
135 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
136 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
142 /****************************************************************************
143 Get one EA value. Fill in a struct ea_struct.
144 ****************************************************************************/
146 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
147 files_struct *fsp, const char *fname,
148 const char *ea_name, struct ea_struct *pea)
150 /* Get the value of this xattr. Max size is 64k. */
151 size_t attr_size = 256;
157 val = talloc_realloc(mem_ctx, val, char, attr_size);
159 return NT_STATUS_NO_MEMORY;
162 if (fsp && fsp->fh->fd != -1) {
163 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
165 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
168 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
174 return map_nt_error_from_unix(errno);
177 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
178 dump_data(10, (uint8 *)val, sizeret);
181 if (strnequal(ea_name, "user.", 5)) {
182 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
184 pea->name = talloc_strdup(mem_ctx, ea_name);
186 if (pea->name == NULL) {
188 return NT_STATUS_NO_MEMORY;
190 pea->value.data = (unsigned char *)val;
191 pea->value.length = (size_t)sizeret;
195 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
196 files_struct *fsp, const char *fname,
197 char ***pnames, size_t *pnum_names)
199 /* Get a list of all xattrs. Max namesize is 64k. */
200 size_t ea_namelist_size = 1024;
201 char *ea_namelist = NULL;
206 ssize_t sizeret = -1;
208 if (!lp_ea_support(SNUM(conn))) {
217 * TALLOC the result early to get the talloc hierarchy right.
220 names = talloc_array(mem_ctx, char *, 1);
222 DEBUG(0, ("talloc failed\n"));
223 return NT_STATUS_NO_MEMORY;
226 while (ea_namelist_size <= 65536) {
228 ea_namelist = talloc_realloc(
229 names, ea_namelist, char, ea_namelist_size);
230 if (ea_namelist == NULL) {
231 DEBUG(0, ("talloc failed\n"));
233 return NT_STATUS_NO_MEMORY;
236 if (fsp && fsp->fh->fd != -1) {
237 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
240 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
244 if ((sizeret == -1) && (errno == ERANGE)) {
245 ea_namelist_size *= 2;
254 return map_nt_error_from_unix(errno);
257 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
258 (unsigned int)sizeret));
270 * Ensure the result is 0-terminated
273 if (ea_namelist[sizeret-1] != '\0') {
275 return NT_STATUS_INTERNAL_ERROR;
283 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
287 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
289 DEBUG(0, ("talloc failed\n"));
291 return NT_STATUS_NO_MEMORY;
297 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
298 names[num_names++] = p;
306 *pnum_names = num_names;
310 /****************************************************************************
311 Return a linked list of the total EA's. Plus the total size
312 ****************************************************************************/
314 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
315 const char *fname, size_t *pea_total_len)
317 /* Get a list of all xattrs. Max namesize is 64k. */
320 struct ea_list *ea_list_head = NULL;
325 if (!lp_ea_support(SNUM(conn))) {
329 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
332 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
336 for (i=0; i<num_names; i++) {
337 struct ea_list *listp;
340 if (strnequal(names[i], "system.", 7)
341 || samba_private_attr_name(names[i]))
344 listp = talloc(mem_ctx, struct ea_list);
349 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
355 push_ascii_fstring(dos_ea_name, listp->ea.name);
358 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
360 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
361 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
362 (unsigned int)listp->ea.value.length));
364 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
368 /* Add on 4 for total length. */
369 if (*pea_total_len) {
373 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
374 (unsigned int)*pea_total_len));
379 /****************************************************************************
380 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
382 ****************************************************************************/
384 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
385 connection_struct *conn, struct ea_list *ea_list)
387 unsigned int ret_data_size = 4;
390 SMB_ASSERT(total_data_size >= 4);
392 if (!lp_ea_support(SNUM(conn))) {
397 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
400 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
401 dos_namelen = strlen(dos_ea_name);
402 if (dos_namelen > 255 || dos_namelen == 0) {
405 if (ea_list->ea.value.length > 65535) {
408 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
412 /* We know we have room. */
413 SCVAL(p,0,ea_list->ea.flags);
414 SCVAL(p,1,dos_namelen);
415 SSVAL(p,2,ea_list->ea.value.length);
416 strlcpy(p+4, dos_ea_name, dos_namelen+1);
417 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
419 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
420 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
423 ret_data_size = PTR_DIFF(p, pdata);
424 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
425 SIVAL(pdata,0,ret_data_size);
426 return ret_data_size;
429 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
431 unsigned int total_data_size,
432 unsigned int *ret_data_size,
433 connection_struct *conn,
434 struct ea_list *ea_list)
436 uint8_t *p = (uint8_t *)pdata;
437 uint8_t *last_start = NULL;
441 if (!lp_ea_support(SNUM(conn))) {
442 return NT_STATUS_NO_EAS_ON_FILE;
445 for (; ea_list; ea_list = ea_list->next) {
451 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
455 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
456 dos_namelen = strlen(dos_ea_name);
457 if (dos_namelen > 255 || dos_namelen == 0) {
458 return NT_STATUS_INTERNAL_ERROR;
460 if (ea_list->ea.value.length > 65535) {
461 return NT_STATUS_INTERNAL_ERROR;
464 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
467 size_t pad = 4 - (this_size % 4);
471 if (this_size > total_data_size) {
472 return NT_STATUS_INFO_LENGTH_MISMATCH;
475 /* We know we have room. */
476 SIVAL(p, 0x00, 0); /* next offset */
477 SCVAL(p, 0x04, ea_list->ea.flags);
478 SCVAL(p, 0x05, dos_namelen);
479 SSVAL(p, 0x06, ea_list->ea.value.length);
480 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
481 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
483 total_data_size -= this_size;
487 *ret_data_size = PTR_DIFF(p, pdata);
488 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
492 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
494 size_t total_ea_len = 0;
495 TALLOC_CTX *mem_ctx = NULL;
497 if (!lp_ea_support(SNUM(conn))) {
500 mem_ctx = talloc_tos();
501 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
505 /****************************************************************************
506 Ensure the EA name is case insensitive by matching any existing EA name.
507 ****************************************************************************/
509 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
512 TALLOC_CTX *mem_ctx = talloc_tos();
513 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
515 for (; ea_list; ea_list = ea_list->next) {
516 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
517 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
518 &unix_ea_name[5], ea_list->ea.name));
519 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
525 /****************************************************************************
526 Set or delete an extended attribute.
527 ****************************************************************************/
529 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
530 const struct smb_filename *smb_fname, struct ea_list *ea_list)
535 if (!lp_ea_support(SNUM(conn))) {
536 return NT_STATUS_EAS_NOT_SUPPORTED;
539 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
540 if (!NT_STATUS_IS_OK(status)) {
544 /* For now setting EAs on streams isn't supported. */
545 fname = smb_fname->base_name;
547 for (;ea_list; ea_list = ea_list->next) {
549 fstring unix_ea_name;
551 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
552 fstrcat(unix_ea_name, ea_list->ea.name);
554 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
556 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
558 if (samba_private_attr_name(unix_ea_name)) {
559 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
560 return NT_STATUS_ACCESS_DENIED;
563 if (ea_list->ea.value.length == 0) {
564 /* Remove the attribute. */
565 if (fsp && (fsp->fh->fd != -1)) {
566 DEBUG(10,("set_ea: deleting ea name %s on "
567 "file %s by file descriptor.\n",
568 unix_ea_name, fsp_str_dbg(fsp)));
569 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
571 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
572 unix_ea_name, fname));
573 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
576 /* Removing a non existent attribute always succeeds. */
577 if (ret == -1 && errno == ENOATTR) {
578 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
584 if (fsp && (fsp->fh->fd != -1)) {
585 DEBUG(10,("set_ea: setting ea name %s on file "
586 "%s by file descriptor.\n",
587 unix_ea_name, fsp_str_dbg(fsp)));
588 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
589 ea_list->ea.value.data, ea_list->ea.value.length, 0);
591 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
592 unix_ea_name, fname));
593 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
594 ea_list->ea.value.data, ea_list->ea.value.length, 0);
600 if (errno == ENOTSUP) {
601 return NT_STATUS_EAS_NOT_SUPPORTED;
604 return map_nt_error_from_unix(errno);
610 /****************************************************************************
611 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
612 ****************************************************************************/
614 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
616 struct ea_list *ea_list_head = NULL;
617 size_t converted_size, offset = 0;
619 while (offset + 2 < data_size) {
620 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
621 unsigned int namelen = CVAL(pdata,offset);
623 offset++; /* Go past the namelen byte. */
625 /* integer wrap paranioa. */
626 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
627 (offset > data_size) || (namelen > data_size) ||
628 (offset + namelen >= data_size)) {
631 /* Ensure the name is null terminated. */
632 if (pdata[offset + namelen] != '\0') {
635 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
637 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
638 "failed: %s", strerror(errno)));
644 offset += (namelen + 1); /* Go past the name + terminating zero. */
645 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
646 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
652 /****************************************************************************
653 Read one EA list entry from the buffer.
654 ****************************************************************************/
656 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
658 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
660 unsigned int namelen;
661 size_t converted_size;
671 eal->ea.flags = CVAL(pdata,0);
672 namelen = CVAL(pdata,1);
673 val_len = SVAL(pdata,2);
675 if (4 + namelen + 1 + val_len > data_size) {
679 /* Ensure the name is null terminated. */
680 if (pdata[namelen + 4] != '\0') {
683 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
684 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
691 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
692 if (!eal->ea.value.data) {
696 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
698 /* Ensure we're null terminated just in case we print the value. */
699 eal->ea.value.data[val_len] = '\0';
700 /* But don't count the null. */
701 eal->ea.value.length--;
704 *pbytes_used = 4 + namelen + 1 + val_len;
707 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
708 dump_data(10, eal->ea.value.data, eal->ea.value.length);
713 /****************************************************************************
714 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
715 ****************************************************************************/
717 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
719 struct ea_list *ea_list_head = NULL;
721 size_t bytes_used = 0;
723 while (offset < data_size) {
724 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
730 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
731 offset += bytes_used;
737 /****************************************************************************
738 Count the total EA size needed.
739 ****************************************************************************/
741 static size_t ea_list_size(struct ea_list *ealist)
744 struct ea_list *listp;
747 for (listp = ealist; listp; listp = listp->next) {
748 push_ascii_fstring(dos_ea_name, listp->ea.name);
749 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
751 /* Add on 4 for total length. */
759 /****************************************************************************
760 Return a union of EA's from a file list and a list of names.
761 The TALLOC context for the two lists *MUST* be identical as we steal
762 memory from one list to add to another. JRA.
763 ****************************************************************************/
765 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
767 struct ea_list *nlistp, *flistp;
769 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
770 for (flistp = file_list; flistp; flistp = flistp->next) {
771 if (strequal(nlistp->ea.name, flistp->ea.name)) {
777 /* Copy the data from this entry. */
778 nlistp->ea.flags = flistp->ea.flags;
779 nlistp->ea.value = flistp->ea.value;
782 nlistp->ea.flags = 0;
783 ZERO_STRUCT(nlistp->ea.value);
787 *total_ea_len = ea_list_size(name_list);
791 /****************************************************************************
792 Send the required number of replies back.
793 We assume all fields other than the data fields are
794 set correctly for the type of call.
795 HACK ! Always assumes smb_setup field is zero.
796 ****************************************************************************/
798 void send_trans2_replies(connection_struct *conn,
799 struct smb_request *req,
806 /* As we are using a protocol > LANMAN1 then the max_send
807 variable must have been set in the sessetupX call.
808 This takes precedence over the max_xmit field in the
809 global struct. These different max_xmit variables should
810 be merged as this is now too confusing */
812 int data_to_send = datasize;
813 int params_to_send = paramsize;
815 const char *pp = params;
816 const char *pd = pdata;
817 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
818 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
819 int data_alignment_offset = 0;
820 bool overflow = False;
821 struct smbd_server_connection *sconn = req->sconn;
822 int max_send = sconn->smb1.sessions.max_send;
824 /* Modify the data_to_send and datasize and set the error if
825 we're trying to send more than max_data_bytes. We still send
826 the part of the packet(s) that fit. Strange, but needed
829 if (max_data_bytes > 0 && datasize > max_data_bytes) {
830 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
831 max_data_bytes, datasize ));
832 datasize = data_to_send = max_data_bytes;
836 /* If there genuinely are no parameters or data to send just send the empty packet */
838 if(params_to_send == 0 && data_to_send == 0) {
839 reply_outbuf(req, 10, 0);
840 show_msg((char *)req->outbuf);
841 if (!srv_send_smb(sconn,
844 IS_CONN_ENCRYPTED(conn),
846 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
848 TALLOC_FREE(req->outbuf);
852 /* When sending params and data ensure that both are nicely aligned */
853 /* Only do this alignment when there is also data to send - else
854 can cause NT redirector problems. */
856 if (((params_to_send % 4) != 0) && (data_to_send != 0))
857 data_alignment_offset = 4 - (params_to_send % 4);
859 /* Space is bufsize minus Netbios over TCP header minus SMB header */
860 /* The alignment_offset is to align the param bytes on an even byte
861 boundary. NT 4.0 Beta needs this to work correctly. */
863 useable_space = max_send - (smb_size
866 + data_alignment_offset);
868 if (useable_space < 0) {
869 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
870 "= %d!!!", useable_space));
871 exit_server_cleanly("send_trans2_replies: Not enough space");
874 while (params_to_send || data_to_send) {
875 /* Calculate whether we will totally or partially fill this packet */
877 total_sent_thistime = params_to_send + data_to_send;
879 /* We can never send more than useable_space */
881 * Note that 'useable_space' does not include the alignment offsets,
882 * but we must include the alignment offsets in the calculation of
883 * the length of the data we send over the wire, as the alignment offsets
884 * are sent here. Fix from Marc_Jacobsen@hp.com.
887 total_sent_thistime = MIN(total_sent_thistime, useable_space);
889 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
890 + data_alignment_offset);
893 * We might have SMBtrans2s in req which was transferred to
894 * the outbuf, fix that.
896 SCVAL(req->outbuf, smb_com, SMBtrans2);
898 /* Set total params and data to be sent */
899 SSVAL(req->outbuf,smb_tprcnt,paramsize);
900 SSVAL(req->outbuf,smb_tdrcnt,datasize);
902 /* Calculate how many parameters and data we can fit into
903 * this packet. Parameters get precedence
906 params_sent_thistime = MIN(params_to_send,useable_space);
907 data_sent_thistime = useable_space - params_sent_thistime;
908 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
910 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
912 /* smb_proff is the offset from the start of the SMB header to the
913 parameter bytes, however the first 4 bytes of outbuf are
914 the Netbios over TCP header. Thus use smb_base() to subtract
915 them from the calculation */
917 SSVAL(req->outbuf,smb_proff,
918 ((smb_buf(req->outbuf)+alignment_offset)
919 - smb_base(req->outbuf)));
921 if(params_sent_thistime == 0)
922 SSVAL(req->outbuf,smb_prdisp,0);
924 /* Absolute displacement of param bytes sent in this packet */
925 SSVAL(req->outbuf,smb_prdisp,pp - params);
927 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
928 if(data_sent_thistime == 0) {
929 SSVAL(req->outbuf,smb_droff,0);
930 SSVAL(req->outbuf,smb_drdisp, 0);
932 /* The offset of the data bytes is the offset of the
933 parameter bytes plus the number of parameters being sent this time */
934 SSVAL(req->outbuf, smb_droff,
935 ((smb_buf(req->outbuf)+alignment_offset)
936 - smb_base(req->outbuf))
937 + params_sent_thistime + data_alignment_offset);
938 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
941 /* Initialize the padding for alignment */
943 if (alignment_offset != 0) {
944 memset(smb_buf(req->outbuf), 0, alignment_offset);
947 /* Copy the param bytes into the packet */
949 if(params_sent_thistime) {
950 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
951 params_sent_thistime);
954 /* Copy in the data bytes */
955 if(data_sent_thistime) {
956 if (data_alignment_offset != 0) {
957 memset((smb_buf(req->outbuf)+alignment_offset+
958 params_sent_thistime), 0,
959 data_alignment_offset);
961 memcpy(smb_buf(req->outbuf)+alignment_offset
962 +params_sent_thistime+data_alignment_offset,
963 pd,data_sent_thistime);
966 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
967 params_sent_thistime, data_sent_thistime, useable_space));
968 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
969 params_to_send, data_to_send, paramsize, datasize));
972 error_packet_set((char *)req->outbuf,
973 ERRDOS,ERRbufferoverflow,
974 STATUS_BUFFER_OVERFLOW,
978 /* Send the packet */
979 show_msg((char *)req->outbuf);
980 if (!srv_send_smb(sconn,
983 IS_CONN_ENCRYPTED(conn),
985 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
987 TALLOC_FREE(req->outbuf);
989 pp += params_sent_thistime;
990 pd += data_sent_thistime;
992 params_to_send -= params_sent_thistime;
993 data_to_send -= data_sent_thistime;
996 if(params_to_send < 0 || data_to_send < 0) {
997 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
998 params_to_send, data_to_send));
1006 /****************************************************************************
1007 Reply to a TRANSACT2_OPEN.
1008 ****************************************************************************/
1010 static void call_trans2open(connection_struct *conn,
1011 struct smb_request *req,
1012 char **pparams, int total_params,
1013 char **ppdata, int total_data,
1014 unsigned int max_data_bytes)
1016 struct smb_filename *smb_fname = NULL;
1017 char *params = *pparams;
1018 char *pdata = *ppdata;
1021 bool oplock_request;
1023 bool return_additional_info;
1032 int fattr=0,mtime=0;
1033 SMB_INO_T inode = 0;
1036 struct ea_list *ea_list = NULL;
1041 uint32 create_disposition;
1042 uint32 create_options = 0;
1043 uint32_t private_flags = 0;
1044 TALLOC_CTX *ctx = talloc_tos();
1047 * Ensure we have enough parameters to perform the operation.
1050 if (total_params < 29) {
1051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1055 flags = SVAL(params, 0);
1056 deny_mode = SVAL(params, 2);
1057 open_attr = SVAL(params,6);
1058 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1059 if (oplock_request) {
1060 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1064 return_additional_info = BITSETW(params,0);
1065 open_sattr = SVAL(params, 4);
1066 open_time = make_unix_date3(params+8);
1068 open_ofun = SVAL(params,12);
1069 open_size = IVAL(params,14);
1070 pname = ¶ms[28];
1073 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1077 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1078 total_params - 28, STR_TERMINATE,
1080 if (!NT_STATUS_IS_OK(status)) {
1081 reply_nterror(req, status);
1085 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1086 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1087 (unsigned int)open_ofun, open_size));
1089 status = filename_convert(ctx,
1091 req->flags2 & FLAGS2_DFS_PATHNAMES,
1096 if (!NT_STATUS_IS_OK(status)) {
1097 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1098 reply_botherror(req,
1099 NT_STATUS_PATH_NOT_COVERED,
1100 ERRSRV, ERRbadpath);
1103 reply_nterror(req, status);
1107 if (open_ofun == 0) {
1108 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1112 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1114 &access_mask, &share_mode,
1115 &create_disposition,
1118 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1122 /* Any data in this call is an EA list. */
1123 if (total_data && (total_data != 4)) {
1124 if (total_data < 10) {
1125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1129 if (IVAL(pdata,0) > total_data) {
1130 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1131 IVAL(pdata,0), (unsigned int)total_data));
1132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1136 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1143 if (!lp_ea_support(SNUM(conn))) {
1144 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1149 status = SMB_VFS_CREATE_FILE(
1152 0, /* root_dir_fid */
1153 smb_fname, /* fname */
1154 access_mask, /* access_mask */
1155 share_mode, /* share_access */
1156 create_disposition, /* create_disposition*/
1157 create_options, /* create_options */
1158 open_attr, /* file_attributes */
1159 oplock_request, /* oplock_request */
1160 open_size, /* allocation_size */
1163 ea_list, /* ea_list */
1165 &smb_action); /* psbuf */
1167 if (!NT_STATUS_IS_OK(status)) {
1168 if (open_was_deferred(req->sconn, req->mid)) {
1169 /* We have re-scheduled this call. */
1172 reply_openerror(req, status);
1176 size = get_file_size_stat(&smb_fname->st);
1177 fattr = dos_mode(conn, smb_fname);
1178 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1179 inode = smb_fname->st.st_ex_ino;
1180 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1181 close_file(req, fsp, ERROR_CLOSE);
1182 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1186 /* Realloc the size of parameters and data we will return */
1187 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1188 if(*pparams == NULL ) {
1189 reply_nterror(req, NT_STATUS_NO_MEMORY);
1194 SSVAL(params,0,fsp->fnum);
1195 SSVAL(params,2,fattr);
1196 srv_put_dos_date2(params,4, mtime);
1197 SIVAL(params,8, (uint32)size);
1198 SSVAL(params,12,deny_mode);
1199 SSVAL(params,14,0); /* open_type - file or directory. */
1200 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1202 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1203 smb_action |= EXTENDED_OPLOCK_GRANTED;
1206 SSVAL(params,18,smb_action);
1209 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1211 SIVAL(params,20,inode);
1212 SSVAL(params,24,0); /* Padding. */
1214 uint32 ea_size = estimate_ea_size(conn, fsp,
1215 fsp->fsp_name->base_name);
1216 SIVAL(params, 26, ea_size);
1218 SIVAL(params, 26, 0);
1221 /* Send the required number of replies */
1222 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1224 TALLOC_FREE(smb_fname);
1227 /*********************************************************
1228 Routine to check if a given string matches exactly.
1229 as a special case a mask of "." does NOT match. That
1230 is required for correct wildcard semantics
1231 Case can be significant or not.
1232 **********************************************************/
1234 static bool exact_match(bool has_wild,
1235 bool case_sensitive,
1239 if (mask[0] == '.' && mask[1] == 0) {
1247 if (case_sensitive) {
1248 return strcmp(str,mask)==0;
1250 return strcasecmp_m(str,mask) == 0;
1254 /****************************************************************************
1255 Return the filetype for UNIX extensions.
1256 ****************************************************************************/
1258 static uint32 unix_filetype(mode_t mode)
1261 return UNIX_TYPE_FILE;
1262 else if(S_ISDIR(mode))
1263 return UNIX_TYPE_DIR;
1265 else if(S_ISLNK(mode))
1266 return UNIX_TYPE_SYMLINK;
1269 else if(S_ISCHR(mode))
1270 return UNIX_TYPE_CHARDEV;
1273 else if(S_ISBLK(mode))
1274 return UNIX_TYPE_BLKDEV;
1277 else if(S_ISFIFO(mode))
1278 return UNIX_TYPE_FIFO;
1281 else if(S_ISSOCK(mode))
1282 return UNIX_TYPE_SOCKET;
1285 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1286 return UNIX_TYPE_UNKNOWN;
1289 /****************************************************************************
1290 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1291 ****************************************************************************/
1293 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1295 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1296 const SMB_STRUCT_STAT *psbuf,
1298 enum perm_type ptype,
1303 if (perms == SMB_MODE_NO_CHANGE) {
1304 if (!VALID_STAT(*psbuf)) {
1305 return NT_STATUS_INVALID_PARAMETER;
1307 *ret_perms = psbuf->st_ex_mode;
1308 return NT_STATUS_OK;
1312 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1313 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1314 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1315 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1316 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1317 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1318 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1319 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1320 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1322 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1325 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1328 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1333 /* Apply mode mask */
1334 ret &= lp_create_mask(SNUM(conn));
1335 /* Add in force bits */
1336 ret |= lp_force_create_mode(SNUM(conn));
1339 ret &= lp_dir_mask(SNUM(conn));
1340 /* Add in force bits */
1341 ret |= lp_force_dir_mode(SNUM(conn));
1343 case PERM_EXISTING_FILE:
1344 /* Apply mode mask */
1345 ret &= lp_security_mask(SNUM(conn));
1346 /* Add in force bits */
1347 ret |= lp_force_security_mode(SNUM(conn));
1349 case PERM_EXISTING_DIR:
1350 /* Apply mode mask */
1351 ret &= lp_dir_security_mask(SNUM(conn));
1352 /* Add in force bits */
1353 ret |= lp_force_dir_security_mode(SNUM(conn));
1358 return NT_STATUS_OK;
1361 /****************************************************************************
1362 Needed to show the msdfs symlinks as directories. Modifies psbuf
1363 to be a directory if it's a msdfs link.
1364 ****************************************************************************/
1366 static bool check_msdfs_link(connection_struct *conn,
1367 const char *pathname,
1368 SMB_STRUCT_STAT *psbuf)
1370 int saved_errno = errno;
1371 if(lp_host_msdfs() &&
1372 lp_msdfs_root(SNUM(conn)) &&
1373 is_msdfs_link(conn, pathname, psbuf)) {
1375 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1378 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1379 errno = saved_errno;
1382 errno = saved_errno;
1387 /****************************************************************************
1388 Get a level dependent lanman2 dir entry.
1389 ****************************************************************************/
1391 struct smbd_dirptr_lanman2_state {
1392 connection_struct *conn;
1393 uint32_t info_level;
1394 bool check_mangled_names;
1396 bool got_exact_match;
1399 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1405 struct smbd_dirptr_lanman2_state *state =
1406 (struct smbd_dirptr_lanman2_state *)private_data;
1408 char mangled_name[13]; /* mangled 8.3 name. */
1412 /* Mangle fname if it's an illegal name. */
1413 if (mangle_must_mangle(dname, state->conn->params)) {
1414 ok = name_to_8_3(dname, mangled_name,
1415 true, state->conn->params);
1419 fname = mangled_name;
1424 got_match = exact_match(state->has_wild,
1425 state->conn->case_sensitive,
1427 state->got_exact_match = got_match;
1429 got_match = mask_match(fname, mask,
1430 state->conn->case_sensitive);
1433 if(!got_match && state->check_mangled_names &&
1434 !mangle_is_8_3(fname, false, state->conn->params)) {
1436 * It turns out that NT matches wildcards against
1437 * both long *and* short names. This may explain some
1438 * of the wildcard wierdness from old DOS clients
1439 * that some people have been seeing.... JRA.
1441 /* Force the mangling into 8.3. */
1442 ok = name_to_8_3(fname, mangled_name,
1443 false, state->conn->params);
1448 got_match = exact_match(state->has_wild,
1449 state->conn->case_sensitive,
1450 mangled_name, mask);
1451 state->got_exact_match = got_match;
1453 got_match = mask_match(mangled_name, mask,
1454 state->conn->case_sensitive);
1462 *_fname = talloc_strdup(ctx, fname);
1463 if (*_fname == NULL) {
1470 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1472 struct smb_filename *smb_fname,
1475 struct smbd_dirptr_lanman2_state *state =
1476 (struct smbd_dirptr_lanman2_state *)private_data;
1477 bool ms_dfs_link = false;
1480 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1481 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1482 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1483 "Couldn't lstat [%s] (%s)\n",
1484 smb_fname_str_dbg(smb_fname),
1488 } else if (!VALID_STAT(smb_fname->st) &&
1489 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1490 /* Needed to show the msdfs symlinks as
1493 ms_dfs_link = check_msdfs_link(state->conn,
1494 smb_fname->base_name,
1497 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1498 "Couldn't stat [%s] (%s)\n",
1499 smb_fname_str_dbg(smb_fname),
1506 mode = dos_mode_msdfs(state->conn, smb_fname);
1508 mode = dos_mode(state->conn, smb_fname);
1515 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1516 connection_struct *conn,
1518 uint32_t info_level,
1519 struct ea_list *name_list,
1520 bool check_mangled_names,
1521 bool requires_resume_key,
1524 const struct smb_filename *smb_fname,
1525 int space_remaining,
1532 uint64_t *last_entry_off)
1534 char *p, *q, *pdata = *ppdata;
1536 uint64_t file_size = 0;
1537 uint64_t allocation_size = 0;
1538 uint64_t file_index = 0;
1540 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1541 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1543 char *last_entry_ptr;
1548 *out_of_space = false;
1550 ZERO_STRUCT(mdate_ts);
1551 ZERO_STRUCT(adate_ts);
1552 ZERO_STRUCT(create_date_ts);
1553 ZERO_STRUCT(cdate_ts);
1555 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1556 file_size = get_file_size_stat(&smb_fname->st);
1558 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1560 file_index = get_FileIndex(conn, &smb_fname->st);
1562 mdate_ts = smb_fname->st.st_ex_mtime;
1563 adate_ts = smb_fname->st.st_ex_atime;
1564 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1565 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1567 if (lp_dos_filetime_resolution(SNUM(conn))) {
1568 dos_filetime_timespec(&create_date_ts);
1569 dos_filetime_timespec(&mdate_ts);
1570 dos_filetime_timespec(&adate_ts);
1571 dos_filetime_timespec(&cdate_ts);
1574 create_date = convert_timespec_to_time_t(create_date_ts);
1575 mdate = convert_timespec_to_time_t(mdate_ts);
1576 adate = convert_timespec_to_time_t(adate_ts);
1578 /* align the record */
1579 SMB_ASSERT(align >= 1);
1581 off = (int)PTR_DIFF(pdata, base_data);
1582 pad = (off + (align-1)) & ~(align-1);
1585 if (pad && pad > space_remaining) {
1586 *out_of_space = true;
1587 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1588 "for padding (wanted %u, had %d)\n",
1591 return false; /* Not finished - just out of space */
1595 /* initialize padding to 0 */
1597 memset(pdata, 0, pad);
1599 space_remaining -= pad;
1601 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1611 switch (info_level) {
1612 case SMB_FIND_INFO_STANDARD:
1613 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\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);
1626 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1627 p += ucs2_align(base_data, p, 0);
1629 len = srvstr_push(base_data, flags2, p,
1630 fname, PTR_DIFF(end_data, p),
1632 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1634 SCVAL(nameptr, -1, len - 2);
1636 SCVAL(nameptr, -1, 0);
1640 SCVAL(nameptr, -1, len - 1);
1642 SCVAL(nameptr, -1, 0);
1648 case SMB_FIND_EA_SIZE:
1649 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1650 if (requires_resume_key) {
1654 srv_put_dos_date2(p,0,create_date);
1655 srv_put_dos_date2(p,4,adate);
1656 srv_put_dos_date2(p,8,mdate);
1657 SIVAL(p,12,(uint32)file_size);
1658 SIVAL(p,16,(uint32)allocation_size);
1661 unsigned int ea_size = estimate_ea_size(conn, NULL,
1662 smb_fname->base_name);
1663 SIVAL(p,22,ea_size); /* Extended attributes */
1667 len = srvstr_push(base_data, flags2,
1668 p, fname, PTR_DIFF(end_data, p),
1669 STR_TERMINATE | STR_NOALIGN);
1670 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1683 SCVAL(nameptr,0,len);
1685 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1688 case SMB_FIND_EA_LIST:
1690 struct ea_list *file_list = NULL;
1693 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1697 if (requires_resume_key) {
1701 srv_put_dos_date2(p,0,create_date);
1702 srv_put_dos_date2(p,4,adate);
1703 srv_put_dos_date2(p,8,mdate);
1704 SIVAL(p,12,(uint32)file_size);
1705 SIVAL(p,16,(uint32)allocation_size);
1707 p += 22; /* p now points to the EA area. */
1709 file_list = get_ea_list_from_file(ctx, conn, NULL,
1710 smb_fname->base_name,
1712 name_list = ea_list_union(name_list, file_list, &ea_len);
1714 /* We need to determine if this entry will fit in the space available. */
1715 /* Max string size is 255 bytes. */
1716 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1717 *out_of_space = true;
1718 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1719 "(wanted %u, had %d)\n",
1720 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1722 return False; /* Not finished - just out of space */
1725 /* Push the ea_data followed by the name. */
1726 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1728 len = srvstr_push(base_data, flags2,
1729 p + 1, fname, PTR_DIFF(end_data, p+1),
1730 STR_TERMINATE | STR_NOALIGN);
1731 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1744 SCVAL(nameptr,0,len);
1746 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1750 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1751 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1752 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1754 SIVAL(p,0,reskey); p += 4;
1755 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1756 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1757 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1758 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1759 SOFF_T(p,0,file_size); p += 8;
1760 SOFF_T(p,0,allocation_size); p += 8;
1761 SIVAL(p,0,mode); p += 4;
1762 q = p; p += 4; /* q is placeholder for name length. */
1764 unsigned int ea_size = estimate_ea_size(conn, NULL,
1765 smb_fname->base_name);
1766 SIVAL(p,0,ea_size); /* Extended attributes */
1769 /* Clear the short name buffer. This is
1770 * IMPORTANT as not doing so will trigger
1771 * a Win2k client bug. JRA.
1773 if (!was_8_3 && check_mangled_names) {
1774 char mangled_name[13]; /* mangled 8.3 name. */
1775 if (!name_to_8_3(fname,mangled_name,True,
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1785 memset(p + 2 + len,'\0',24 - len);
1792 len = srvstr_push(base_data, flags2, p,
1793 fname, PTR_DIFF(end_data, p),
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_DIRECTORY_INFO:
1818 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_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 len = srvstr_push(base_data, flags2,
1829 p + 4, fname, PTR_DIFF(end_data, p+4),
1830 STR_TERMINATE_ASCII);
1834 len = PTR_DIFF(p, pdata);
1835 pad = (len + (align-1)) & ~(align-1);
1837 * offset to the next entry, the caller
1838 * will overwrite it for the last entry
1839 * that's why we always include the padding
1843 * set padding to zero
1846 memset(p, 0, pad - len);
1853 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1854 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1856 SIVAL(p,0,reskey); p += 4;
1857 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1858 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1859 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1861 SOFF_T(p,0,file_size); p += 8;
1862 SOFF_T(p,0,allocation_size); p += 8;
1863 SIVAL(p,0,mode); p += 4;
1864 q = p; p += 4; /* q is placeholder for name length. */
1866 unsigned int ea_size = estimate_ea_size(conn, NULL,
1867 smb_fname->base_name);
1868 SIVAL(p,0,ea_size); /* Extended attributes */
1871 len = srvstr_push(base_data, flags2, p,
1872 fname, PTR_DIFF(end_data, p),
1873 STR_TERMINATE_ASCII);
1877 len = PTR_DIFF(p, pdata);
1878 pad = (len + (align-1)) & ~(align-1);
1880 * offset to the next entry, the caller
1881 * will overwrite it for the last entry
1882 * that's why we always include the padding
1886 * set padding to zero
1889 memset(p, 0, pad - len);
1896 case SMB_FIND_FILE_NAMES_INFO:
1897 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1899 SIVAL(p,0,reskey); p += 4;
1901 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1902 acl on a dir (tridge) */
1903 len = srvstr_push(base_data, flags2, p,
1904 fname, PTR_DIFF(end_data, p),
1905 STR_TERMINATE_ASCII);
1909 len = PTR_DIFF(p, pdata);
1910 pad = (len + (align-1)) & ~(align-1);
1912 * offset to the next entry, the caller
1913 * will overwrite it for the last entry
1914 * that's why we always include the padding
1918 * set padding to zero
1921 memset(p, 0, pad - len);
1928 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1929 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1931 SIVAL(p,0,reskey); p += 4;
1932 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1933 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1934 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1935 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1936 SOFF_T(p,0,file_size); p += 8;
1937 SOFF_T(p,0,allocation_size); p += 8;
1938 SIVAL(p,0,mode); p += 4;
1939 q = p; p += 4; /* q is placeholder for name length. */
1941 unsigned int ea_size = estimate_ea_size(conn, NULL,
1942 smb_fname->base_name);
1943 SIVAL(p,0,ea_size); /* Extended attributes */
1946 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1947 SBVAL(p,0,file_index); p += 8;
1948 len = srvstr_push(base_data, flags2, p,
1949 fname, PTR_DIFF(end_data, p),
1950 STR_TERMINATE_ASCII);
1954 len = PTR_DIFF(p, pdata);
1955 pad = (len + (align-1)) & ~(align-1);
1957 * offset to the next entry, the caller
1958 * will overwrite it for the last entry
1959 * that's why we always include the padding
1963 * set padding to zero
1966 memset(p, 0, pad - len);
1973 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1974 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1975 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1977 SIVAL(p,0,reskey); p += 4;
1978 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1979 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1980 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1981 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1982 SOFF_T(p,0,file_size); p += 8;
1983 SOFF_T(p,0,allocation_size); p += 8;
1984 SIVAL(p,0,mode); p += 4;
1985 q = p; p += 4; /* q is placeholder for name length */
1987 unsigned int ea_size = estimate_ea_size(conn, NULL,
1988 smb_fname->base_name);
1989 SIVAL(p,0,ea_size); /* Extended attributes */
1992 /* Clear the short name buffer. This is
1993 * IMPORTANT as not doing so will trigger
1994 * a Win2k client bug. JRA.
1996 if (!was_8_3 && check_mangled_names) {
1997 char mangled_name[13]; /* mangled 8.3 name. */
1998 if (!name_to_8_3(fname,mangled_name,True,
2000 /* Error - mangle failed ! */
2001 memset(mangled_name,'\0',12);
2003 mangled_name[12] = 0;
2004 len = srvstr_push(base_data, flags2,
2005 p+2, mangled_name, 24,
2006 STR_UPPER|STR_UNICODE);
2009 memset(p + 2 + len,'\0',24 - len);
2016 SSVAL(p,0,0); p += 2; /* Reserved ? */
2017 SBVAL(p,0,file_index); p += 8;
2018 len = srvstr_push(base_data, flags2, p,
2019 fname, PTR_DIFF(end_data, p),
2020 STR_TERMINATE_ASCII);
2024 len = PTR_DIFF(p, pdata);
2025 pad = (len + (align-1)) & ~(align-1);
2027 * offset to the next entry, the caller
2028 * will overwrite it for the last entry
2029 * that's why we always include the padding
2033 * set padding to zero
2036 memset(p, 0, pad - len);
2043 /* CIFS UNIX Extension. */
2045 case SMB_FIND_FILE_UNIX:
2046 case SMB_FIND_FILE_UNIX_INFO2:
2048 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2050 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2052 if (info_level == SMB_FIND_FILE_UNIX) {
2053 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2054 p = store_file_unix_basic(conn, p,
2055 NULL, &smb_fname->st);
2056 len = srvstr_push(base_data, flags2, p,
2057 fname, PTR_DIFF(end_data, p),
2060 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2061 p = store_file_unix_basic_info2(conn, p,
2062 NULL, &smb_fname->st);
2065 len = srvstr_push(base_data, flags2, p, fname,
2066 PTR_DIFF(end_data, p), 0);
2067 SIVAL(nameptr, 0, len);
2072 len = PTR_DIFF(p, pdata);
2073 pad = (len + (align-1)) & ~(align-1);
2075 * offset to the next entry, the caller
2076 * will overwrite it for the last entry
2077 * that's why we always include the padding
2081 * set padding to zero
2084 memset(p, 0, pad - len);
2089 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2097 if (PTR_DIFF(p,pdata) > space_remaining) {
2098 *out_of_space = true;
2099 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2100 "(wanted %u, had %d)\n",
2101 (unsigned int)PTR_DIFF(p,pdata),
2103 return false; /* Not finished - just out of space */
2106 /* Setup the last entry pointer, as an offset from base_data */
2107 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2108 /* Advance the data pointer to the next slot */
2114 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2115 connection_struct *conn,
2116 struct dptr_struct *dirptr,
2118 const char *path_mask,
2121 int requires_resume_key,
2129 int space_remaining,
2131 bool *got_exact_match,
2132 int *_last_entry_off,
2133 struct ea_list *name_list)
2136 const char *mask = NULL;
2137 long prev_dirpos = 0;
2140 struct smb_filename *smb_fname = NULL;
2141 struct smbd_dirptr_lanman2_state state;
2143 uint64_t last_entry_off = 0;
2147 state.info_level = info_level;
2148 state.check_mangled_names = lp_manglednames(conn->params);
2149 state.has_wild = dptr_has_wild(dirptr);
2150 state.got_exact_match = false;
2152 *out_of_space = false;
2153 *got_exact_match = false;
2155 p = strrchr_m(path_mask,'/');
2166 ok = smbd_dirptr_get_entry(ctx,
2172 smbd_dirptr_lanman2_match_fn,
2173 smbd_dirptr_lanman2_mode_fn,
2183 *got_exact_match = state.got_exact_match;
2185 ok = smbd_marshall_dir_entry(ctx,
2190 state.check_mangled_names,
2191 requires_resume_key,
2204 TALLOC_FREE(smb_fname);
2205 if (*out_of_space) {
2206 dptr_SeekDir(dirptr, prev_dirpos);
2213 *_last_entry_off = last_entry_off;
2217 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2218 connection_struct *conn,
2219 struct dptr_struct *dirptr,
2221 const char *path_mask,
2224 bool requires_resume_key,
2230 int space_remaining,
2232 bool *got_exact_match,
2233 int *last_entry_off,
2234 struct ea_list *name_list)
2237 const bool do_pad = true;
2239 if (info_level >= 1 && info_level <= 3) {
2240 /* No alignment on earlier info levels. */
2244 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2245 path_mask, dirtype, info_level,
2246 requires_resume_key, dont_descend, ask_sharemode,
2248 ppdata, base_data, end_data,
2250 out_of_space, got_exact_match,
2251 last_entry_off, name_list);
2254 /****************************************************************************
2255 Reply to a TRANS2_FINDFIRST.
2256 ****************************************************************************/
2258 static void call_trans2findfirst(connection_struct *conn,
2259 struct smb_request *req,
2260 char **pparams, int total_params,
2261 char **ppdata, int total_data,
2262 unsigned int max_data_bytes)
2264 /* We must be careful here that we don't return more than the
2265 allowed number of data bytes. If this means returning fewer than
2266 maxentries then so be it. We assume that the redirector has
2267 enough room for the fixed number of parameter bytes it has
2269 struct smb_filename *smb_dname = NULL;
2270 char *params = *pparams;
2271 char *pdata = *ppdata;
2275 uint16 findfirst_flags;
2276 bool close_after_first;
2278 bool requires_resume_key;
2280 char *directory = NULL;
2283 int last_entry_off=0;
2287 bool finished = False;
2288 bool dont_descend = False;
2289 bool out_of_space = False;
2290 int space_remaining;
2291 bool mask_contains_wcard = False;
2292 struct ea_list *ea_list = NULL;
2293 NTSTATUS ntstatus = NT_STATUS_OK;
2294 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2295 TALLOC_CTX *ctx = talloc_tos();
2296 struct dptr_struct *dirptr = NULL;
2297 struct smbd_server_connection *sconn = req->sconn;
2298 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2300 if (total_params < 13) {
2301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2305 dirtype = SVAL(params,0);
2306 maxentries = SVAL(params,2);
2307 findfirst_flags = SVAL(params,4);
2308 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2309 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2310 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2311 info_level = SVAL(params,6);
2313 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2314 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2315 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2316 info_level, max_data_bytes));
2319 /* W2K3 seems to treat zero as 1. */
2323 switch (info_level) {
2324 case SMB_FIND_INFO_STANDARD:
2325 case SMB_FIND_EA_SIZE:
2326 case SMB_FIND_EA_LIST:
2327 case SMB_FIND_FILE_DIRECTORY_INFO:
2328 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2329 case SMB_FIND_FILE_NAMES_INFO:
2330 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2331 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2332 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2334 case SMB_FIND_FILE_UNIX:
2335 case SMB_FIND_FILE_UNIX_INFO2:
2336 /* Always use filesystem for UNIX mtime query. */
2337 ask_sharemode = false;
2338 if (!lp_unix_extensions()) {
2339 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2342 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2345 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2349 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2350 params+12, total_params - 12,
2351 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2352 if (!NT_STATUS_IS_OK(ntstatus)) {
2353 reply_nterror(req, ntstatus);
2357 ntstatus = filename_convert(ctx, conn,
2358 req->flags2 & FLAGS2_DFS_PATHNAMES,
2361 &mask_contains_wcard,
2363 if (!NT_STATUS_IS_OK(ntstatus)) {
2364 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2365 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2366 ERRSRV, ERRbadpath);
2369 reply_nterror(req, ntstatus);
2373 mask = smb_dname->original_lcomp;
2375 directory = smb_dname->base_name;
2377 p = strrchr_m(directory,'/');
2379 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2380 if((directory[0] == '.') && (directory[1] == '\0')) {
2381 mask = talloc_strdup(ctx,"*");
2383 reply_nterror(req, NT_STATUS_NO_MEMORY);
2386 mask_contains_wcard = True;
2392 if (p == NULL || p == directory) {
2393 /* Ensure we don't have a directory name of "". */
2394 directory = talloc_strdup(talloc_tos(), ".");
2396 reply_nterror(req, NT_STATUS_NO_MEMORY);
2401 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2403 if (info_level == SMB_FIND_EA_LIST) {
2406 if (total_data < 4) {
2407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2411 ea_size = IVAL(pdata,0);
2412 if (ea_size != total_data) {
2413 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2414 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2419 if (!lp_ea_support(SNUM(conn))) {
2420 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2424 /* Pull out the list of names. */
2425 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2432 *ppdata = (char *)SMB_REALLOC(
2433 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2434 if(*ppdata == NULL ) {
2435 reply_nterror(req, NT_STATUS_NO_MEMORY);
2439 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2441 /* Realloc the params space */
2442 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2443 if (*pparams == NULL) {
2444 reply_nterror(req, NT_STATUS_NO_MEMORY);
2449 /* Save the wildcard match and attribs we are using on this directory -
2450 needed as lanman2 assumes these are being saved between calls */
2452 ntstatus = dptr_create(conn,
2459 mask_contains_wcard,
2463 if (!NT_STATUS_IS_OK(ntstatus)) {
2464 reply_nterror(req, ntstatus);
2468 dptr_num = dptr_dnum(dirptr);
2469 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2471 /* Initialize per TRANS2_FIND_FIRST operation data */
2472 dptr_init_search_op(dirptr);
2474 /* We don't need to check for VOL here as this is returned by
2475 a different TRANS2 call. */
2477 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2478 directory,lp_dontdescend(SNUM(conn))));
2479 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2480 dont_descend = True;
2483 space_remaining = max_data_bytes;
2484 out_of_space = False;
2486 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2487 bool got_exact_match = False;
2489 /* this is a heuristic to avoid seeking the dirptr except when
2490 absolutely necessary. It allows for a filename of about 40 chars */
2491 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2492 out_of_space = True;
2495 finished = !get_lanman2_dir_entry(ctx,
2499 mask,dirtype,info_level,
2500 requires_resume_key,dont_descend,
2503 space_remaining, &out_of_space,
2505 &last_entry_off, ea_list);
2508 if (finished && out_of_space)
2511 if (!finished && !out_of_space)
2515 * As an optimisation if we know we aren't looking
2516 * for a wildcard name (ie. the name matches the wildcard exactly)
2517 * then we can finish on any (first) match.
2518 * This speeds up large directory searches. JRA.
2524 /* Ensure space_remaining never goes -ve. */
2525 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2526 space_remaining = 0;
2527 out_of_space = true;
2529 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2533 /* Check if we can close the dirptr */
2534 if(close_after_first || (finished && close_if_end)) {
2535 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2536 dptr_close(sconn, &dptr_num);
2540 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2541 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2542 * the protocol level is less than NT1. Tested with smbclient. JRA.
2543 * This should fix the OS/2 client bug #2335.
2546 if(numentries == 0) {
2547 dptr_close(sconn, &dptr_num);
2548 if (get_Protocol() < PROTOCOL_NT1) {
2549 reply_force_doserror(req, ERRDOS, ERRnofiles);
2552 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2553 ERRDOS, ERRbadfile);
2558 /* At this point pdata points to numentries directory entries. */
2560 /* Set up the return parameter block */
2561 SSVAL(params,0,dptr_num);
2562 SSVAL(params,2,numentries);
2563 SSVAL(params,4,finished);
2564 SSVAL(params,6,0); /* Never an EA error */
2565 SSVAL(params,8,last_entry_off);
2567 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2570 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2571 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2573 reply_nterror(req, NT_STATUS_NO_MEMORY);
2577 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2578 smb_fn_name(req->cmd),
2579 mask, directory, dirtype, numentries ) );
2582 * Force a name mangle here to ensure that the
2583 * mask as an 8.3 name is top of the mangled cache.
2584 * The reasons for this are subtle. Don't remove
2585 * this code unless you know what you are doing
2586 * (see PR#13758). JRA.
2589 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2590 char mangled_name[13];
2591 name_to_8_3(mask, mangled_name, True, conn->params);
2594 TALLOC_FREE(smb_dname);
2598 /****************************************************************************
2599 Reply to a TRANS2_FINDNEXT.
2600 ****************************************************************************/
2602 static void call_trans2findnext(connection_struct *conn,
2603 struct smb_request *req,
2604 char **pparams, int total_params,
2605 char **ppdata, int total_data,
2606 unsigned int max_data_bytes)
2608 /* We must be careful here that we don't return more than the
2609 allowed number of data bytes. If this means returning fewer than
2610 maxentries then so be it. We assume that the redirector has
2611 enough room for the fixed number of parameter bytes it has
2613 char *params = *pparams;
2614 char *pdata = *ppdata;
2620 uint16 findnext_flags;
2621 bool close_after_request;
2623 bool requires_resume_key;
2625 bool mask_contains_wcard = False;
2626 char *resume_name = NULL;
2627 const char *mask = NULL;
2628 const char *directory = NULL;
2632 int i, last_entry_off=0;
2633 bool finished = False;
2634 bool dont_descend = False;
2635 bool out_of_space = False;
2636 int space_remaining;
2637 struct ea_list *ea_list = NULL;
2638 NTSTATUS ntstatus = NT_STATUS_OK;
2639 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2640 TALLOC_CTX *ctx = talloc_tos();
2641 struct dptr_struct *dirptr;
2642 struct smbd_server_connection *sconn = req->sconn;
2644 if (total_params < 13) {
2645 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2649 dptr_num = SVAL(params,0);
2650 maxentries = SVAL(params,2);
2651 info_level = SVAL(params,4);
2652 resume_key = IVAL(params,6);
2653 findnext_flags = SVAL(params,10);
2654 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2655 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2656 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2657 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2659 if (!continue_bit) {
2660 /* We only need resume_name if continue_bit is zero. */
2661 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2663 total_params - 12, STR_TERMINATE, &ntstatus,
2664 &mask_contains_wcard);
2665 if (!NT_STATUS_IS_OK(ntstatus)) {
2666 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2667 complain (it thinks we're asking for the directory above the shared
2668 path or an invalid name). Catch this as the resume name is only compared, never used in
2669 a file access. JRA. */
2670 srvstr_pull_talloc(ctx, params, req->flags2,
2671 &resume_name, params+12,
2675 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2676 reply_nterror(req, ntstatus);
2682 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2683 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2684 resume_key = %d resume name = %s continue=%d level = %d\n",
2685 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2686 requires_resume_key, resume_key,
2687 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2690 /* W2K3 seems to treat zero as 1. */
2694 switch (info_level) {
2695 case SMB_FIND_INFO_STANDARD:
2696 case SMB_FIND_EA_SIZE:
2697 case SMB_FIND_EA_LIST:
2698 case SMB_FIND_FILE_DIRECTORY_INFO:
2699 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2700 case SMB_FIND_FILE_NAMES_INFO:
2701 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2702 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2703 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2705 case SMB_FIND_FILE_UNIX:
2706 case SMB_FIND_FILE_UNIX_INFO2:
2707 /* Always use filesystem for UNIX mtime query. */
2708 ask_sharemode = false;
2709 if (!lp_unix_extensions()) {
2710 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2715 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2719 if (info_level == SMB_FIND_EA_LIST) {
2722 if (total_data < 4) {
2723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2727 ea_size = IVAL(pdata,0);
2728 if (ea_size != total_data) {
2729 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2730 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2731 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2735 if (!lp_ea_support(SNUM(conn))) {
2736 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2740 /* Pull out the list of names. */
2741 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2743 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2748 *ppdata = (char *)SMB_REALLOC(
2749 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2750 if(*ppdata == NULL) {
2751 reply_nterror(req, NT_STATUS_NO_MEMORY);
2756 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2758 /* Realloc the params space */
2759 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2760 if(*pparams == NULL ) {
2761 reply_nterror(req, NT_STATUS_NO_MEMORY);
2767 /* Check that the dptr is valid */
2768 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2769 reply_nterror(req, STATUS_NO_MORE_FILES);
2773 directory = dptr_path(sconn, dptr_num);
2775 /* Get the wildcard mask from the dptr */
2776 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2777 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2778 reply_nterror(req, STATUS_NO_MORE_FILES);
2782 /* Get the attr mask from the dptr */
2783 dirtype = dptr_attr(sconn, dptr_num);
2785 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2786 dptr_num, mask, dirtype,
2788 dptr_TellDir(dirptr)));
2790 /* Initialize per TRANS2_FIND_NEXT operation data */
2791 dptr_init_search_op(dirptr);
2793 /* We don't need to check for VOL here as this is returned by
2794 a different TRANS2 call. */
2796 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2797 directory,lp_dontdescend(SNUM(conn))));
2798 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2799 dont_descend = True;
2802 space_remaining = max_data_bytes;
2803 out_of_space = False;
2806 * Seek to the correct position. We no longer use the resume key but
2807 * depend on the last file name instead.
2810 if(!continue_bit && resume_name && *resume_name) {
2813 long current_pos = 0;
2815 * Remember, name_to_8_3 is called by
2816 * get_lanman2_dir_entry(), so the resume name
2817 * could be mangled. Ensure we check the unmangled name.
2820 if (mangle_is_mangled(resume_name, conn->params)) {
2821 char *new_resume_name = NULL;
2822 mangle_lookup_name_from_8_3(ctx,
2826 if (new_resume_name) {
2827 resume_name = new_resume_name;
2832 * Fix for NT redirector problem triggered by resume key indexes
2833 * changing between directory scans. We now return a resume key of 0
2834 * and instead look for the filename to continue from (also given
2835 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2836 * findfirst/findnext (as is usual) then the directory pointer
2837 * should already be at the correct place.
2840 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2841 } /* end if resume_name && !continue_bit */
2843 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2844 bool got_exact_match = False;
2846 /* this is a heuristic to avoid seeking the dirptr except when
2847 absolutely necessary. It allows for a filename of about 40 chars */
2848 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2849 out_of_space = True;
2852 finished = !get_lanman2_dir_entry(ctx,
2856 mask,dirtype,info_level,
2857 requires_resume_key,dont_descend,
2860 space_remaining, &out_of_space,
2862 &last_entry_off, ea_list);
2865 if (finished && out_of_space)
2868 if (!finished && !out_of_space)
2872 * As an optimisation if we know we aren't looking
2873 * for a wildcard name (ie. the name matches the wildcard exactly)
2874 * then we can finish on any (first) match.
2875 * This speeds up large directory searches. JRA.
2881 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2884 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2885 smb_fn_name(req->cmd),
2886 mask, directory, dirtype, numentries ) );
2888 /* Check if we can close the dirptr */
2889 if(close_after_request || (finished && close_if_end)) {
2890 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2891 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2894 /* Set up the return parameter block */
2895 SSVAL(params,0,numentries);
2896 SSVAL(params,2,finished);
2897 SSVAL(params,4,0); /* Never an EA error */
2898 SSVAL(params,6,last_entry_off);
2900 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2906 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2908 E_md4hash(lp_servicename(SNUM(conn)),objid);
2912 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2914 SMB_ASSERT(extended_info != NULL);
2916 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2917 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2918 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2919 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2920 #ifdef SAMBA_VERSION_REVISION
2921 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2923 extended_info->samba_subversion = 0;
2924 #ifdef SAMBA_VERSION_RC_RELEASE
2925 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2927 #ifdef SAMBA_VERSION_PRE_RELEASE
2928 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2931 #ifdef SAMBA_VERSION_VENDOR_PATCH
2932 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2934 extended_info->samba_gitcommitdate = 0;
2935 #ifdef SAMBA_VERSION_COMMIT_TIME
2936 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2939 memset(extended_info->samba_version_string, 0,
2940 sizeof(extended_info->samba_version_string));
2942 snprintf (extended_info->samba_version_string,
2943 sizeof(extended_info->samba_version_string),
2944 "%s", samba_version_string());
2947 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2948 TALLOC_CTX *mem_ctx,
2949 uint16_t info_level,
2951 unsigned int max_data_bytes,
2955 char *pdata, *end_data;
2956 int data_len = 0, len;
2957 const char *vname = volume_label(SNUM(conn));
2958 int snum = SNUM(conn);
2959 char *fstype = lp_fstype(SNUM(conn));
2960 uint32 additional_flags = 0;
2961 struct smb_filename smb_fname_dot;
2965 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2966 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2967 "info level (0x%x) on IPC$.\n",
2968 (unsigned int)info_level));
2969 return NT_STATUS_ACCESS_DENIED;
2973 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2975 ZERO_STRUCT(smb_fname_dot);
2976 smb_fname_dot.base_name = discard_const_p(char, ".");
2978 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2979 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2980 return map_nt_error_from_unix(errno);
2983 st = smb_fname_dot.st;
2985 *ppdata = (char *)SMB_REALLOC(
2986 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2987 if (*ppdata == NULL) {
2988 return NT_STATUS_NO_MEMORY;
2992 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2993 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2995 switch (info_level) {
2996 case SMB_INFO_ALLOCATION:
2998 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3000 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3001 return map_nt_error_from_unix(errno);
3004 block_size = lp_block_size(snum);
3005 if (bsize < block_size) {
3006 uint64_t factor = block_size/bsize;
3011 if (bsize > block_size) {
3012 uint64_t factor = bsize/block_size;
3017 bytes_per_sector = 512;
3018 sectors_per_unit = bsize/bytes_per_sector;
3020 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3021 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3022 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3024 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3025 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3026 SIVAL(pdata,l1_cUnit,dsize);
3027 SIVAL(pdata,l1_cUnitAvail,dfree);
3028 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3032 case SMB_INFO_VOLUME:
3033 /* Return volume name */
3035 * Add volume serial number - hash of a combination of
3036 * the called hostname and the service name.
3038 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3040 * Win2k3 and previous mess this up by sending a name length
3041 * one byte short. I believe only older clients (OS/2 Win9x) use
3042 * this call so try fixing this by adding a terminating null to
3043 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3047 pdata+l2_vol_szVolLabel, vname,
3048 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3049 STR_NOALIGN|STR_TERMINATE);
3050 SCVAL(pdata,l2_vol_cch,len);
3051 data_len = l2_vol_szVolLabel + len;
3052 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3053 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3057 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3058 case SMB_FS_ATTRIBUTE_INFORMATION:
3060 additional_flags = 0;
3061 #if defined(HAVE_SYS_QUOTAS)
3062 additional_flags |= FILE_VOLUME_QUOTAS;
3065 if(lp_nt_acl_support(SNUM(conn))) {
3066 additional_flags |= FILE_PERSISTENT_ACLS;
3069 /* Capabilities are filled in at connection time through STATVFS call */
3070 additional_flags |= conn->fs_capabilities;
3071 additional_flags |= lp_parm_int(conn->params->service,
3072 "share", "fake_fscaps",
3075 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3076 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3077 additional_flags); /* FS ATTRIBUTES */
3079 SIVAL(pdata,4,255); /* Max filename component length */
3080 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3081 and will think we can't do long filenames */
3082 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3083 PTR_DIFF(end_data, pdata+12),
3086 data_len = 12 + len;
3089 case SMB_QUERY_FS_LABEL_INFO:
3090 case SMB_FS_LABEL_INFORMATION:
3091 len = srvstr_push(pdata, flags2, pdata+4, vname,
3092 PTR_DIFF(end_data, pdata+4), 0);
3097 case SMB_QUERY_FS_VOLUME_INFO:
3098 case SMB_FS_VOLUME_INFORMATION:
3101 * Add volume serial number - hash of a combination of
3102 * the called hostname and the service name.
3104 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3105 (str_checksum(get_local_machine_name())<<16));
3107 /* Max label len is 32 characters. */
3108 len = srvstr_push(pdata, flags2, pdata+18, vname,
3109 PTR_DIFF(end_data, pdata+18),
3111 SIVAL(pdata,12,len);
3114 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3115 (int)strlen(vname),vname, lp_servicename(snum)));
3118 case SMB_QUERY_FS_SIZE_INFO:
3119 case SMB_FS_SIZE_INFORMATION:
3121 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3123 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3124 return map_nt_error_from_unix(errno);
3126 block_size = lp_block_size(snum);
3127 if (bsize < block_size) {
3128 uint64_t factor = block_size/bsize;
3133 if (bsize > block_size) {
3134 uint64_t factor = bsize/block_size;
3139 bytes_per_sector = 512;
3140 sectors_per_unit = bsize/bytes_per_sector;
3141 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3142 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3143 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3144 SBIG_UINT(pdata,0,dsize);
3145 SBIG_UINT(pdata,8,dfree);
3146 SIVAL(pdata,16,sectors_per_unit);
3147 SIVAL(pdata,20,bytes_per_sector);
3151 case SMB_FS_FULL_SIZE_INFORMATION:
3153 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3155 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3156 return map_nt_error_from_unix(errno);
3158 block_size = lp_block_size(snum);
3159 if (bsize < block_size) {
3160 uint64_t factor = block_size/bsize;
3165 if (bsize > block_size) {
3166 uint64_t factor = bsize/block_size;
3171 bytes_per_sector = 512;
3172 sectors_per_unit = bsize/bytes_per_sector;
3173 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3174 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3175 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3176 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3177 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3178 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3179 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3180 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3184 case SMB_QUERY_FS_DEVICE_INFO:
3185 case SMB_FS_DEVICE_INFORMATION:
3187 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3189 if (!CAN_WRITE(conn)) {
3190 characteristics |= FILE_READ_ONLY_DEVICE;
3193 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3194 SIVAL(pdata,4,characteristics);
3198 #ifdef HAVE_SYS_QUOTAS
3199 case SMB_FS_QUOTA_INFORMATION:
3201 * what we have to send --metze:
3203 * Unknown1: 24 NULL bytes
3204 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3205 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3206 * Quota Flags: 2 byte :
3207 * Unknown3: 6 NULL bytes
3211 * details for Quota Flags:
3213 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3214 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3215 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3216 * 0x0001 Enable Quotas: enable quota for this fs
3220 /* we need to fake up a fsp here,
3221 * because its not send in this call
3224 SMB_NTQUOTA_STRUCT quotas;
3227 ZERO_STRUCT(quotas);
3233 if (get_current_uid(conn) != 0) {
3234 DEBUG(0,("set_user_quota: access_denied "
3235 "service [%s] user [%s]\n",
3236 lp_servicename(SNUM(conn)),
3237 conn->session_info->unix_info->unix_name));
3238 return NT_STATUS_ACCESS_DENIED;
3241 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3242 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3243 return map_nt_error_from_unix(errno);
3248 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3249 lp_servicename(SNUM(conn))));
3251 /* Unknown1 24 NULL bytes*/
3252 SBIG_UINT(pdata,0,(uint64_t)0);
3253 SBIG_UINT(pdata,8,(uint64_t)0);
3254 SBIG_UINT(pdata,16,(uint64_t)0);
3256 /* Default Soft Quota 8 bytes */
3257 SBIG_UINT(pdata,24,quotas.softlim);
3259 /* Default Hard Quota 8 bytes */
3260 SBIG_UINT(pdata,32,quotas.hardlim);
3262 /* Quota flag 2 bytes */
3263 SSVAL(pdata,40,quotas.qflags);
3265 /* Unknown3 6 NULL bytes */
3271 #endif /* HAVE_SYS_QUOTAS */
3272 case SMB_FS_OBJECTID_INFORMATION:
3274 unsigned char objid[16];
3275 struct smb_extended_info extended_info;
3276 memcpy(pdata,create_volume_objectid(conn, objid),16);
3277 samba_extended_info_version (&extended_info);
3278 SIVAL(pdata,16,extended_info.samba_magic);
3279 SIVAL(pdata,20,extended_info.samba_version);
3280 SIVAL(pdata,24,extended_info.samba_subversion);
3281 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3282 memcpy(pdata+36,extended_info.samba_version_string,28);
3288 * Query the version and capabilities of the CIFS UNIX extensions
3292 case SMB_QUERY_CIFS_UNIX_INFO:
3294 bool large_write = lp_min_receive_file_size() &&
3295 !srv_is_signing_active(conn->sconn);
3296 bool large_read = !srv_is_signing_active(conn->sconn);
3297 int encrypt_caps = 0;
3299 if (!lp_unix_extensions()) {
3300 return NT_STATUS_INVALID_LEVEL;
3303 switch (conn->encrypt_level) {
3309 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3312 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3313 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3314 large_write = false;
3320 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3321 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3323 /* We have POSIX ACLs, pathname, encryption,
3324 * large read/write, and locking capability. */
3326 SBIG_UINT(pdata,4,((uint64_t)(
3327 CIFS_UNIX_POSIX_ACLS_CAP|
3328 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3329 CIFS_UNIX_FCNTL_LOCKS_CAP|
3330 CIFS_UNIX_EXTATTR_CAP|
3331 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3333 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3335 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3339 case SMB_QUERY_POSIX_FS_INFO:
3342 vfs_statvfs_struct svfs;
3344 if (!lp_unix_extensions()) {
3345 return NT_STATUS_INVALID_LEVEL;
3348 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3352 SIVAL(pdata,0,svfs.OptimalTransferSize);
3353 SIVAL(pdata,4,svfs.BlockSize);
3354 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3355 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3356 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3357 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3358 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3359 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3360 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3362 } else if (rc == EOPNOTSUPP) {
3363 return NT_STATUS_INVALID_LEVEL;
3364 #endif /* EOPNOTSUPP */
3366 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3367 return NT_STATUS_DOS(ERRSRV, ERRerror);
3372 case SMB_QUERY_POSIX_WHOAMI:
3378 if (!lp_unix_extensions()) {
3379 return NT_STATUS_INVALID_LEVEL;
3382 if (max_data_bytes < 40) {
3383 return NT_STATUS_BUFFER_TOO_SMALL;
3386 /* We ARE guest if global_sid_Builtin_Guests is
3387 * in our list of SIDs.
3389 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3390 conn->session_info->security_token)) {
3391 flags |= SMB_WHOAMI_GUEST;
3394 /* We are NOT guest if global_sid_Authenticated_Users
3395 * is in our list of SIDs.
3397 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3398 conn->session_info->security_token)) {
3399 flags &= ~SMB_WHOAMI_GUEST;
3402 /* NOTE: 8 bytes for UID/GID, irrespective of native
3403 * platform size. This matches
3404 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3406 data_len = 4 /* flags */
3413 + 4 /* pad/reserved */
3414 + (conn->session_info->unix_token->ngroups * 8)
3416 + (conn->session_info->security_token->num_sids *
3420 SIVAL(pdata, 0, flags);
3421 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3423 (uint64_t)conn->session_info->unix_token->uid);
3424 SBIG_UINT(pdata, 16,
3425 (uint64_t)conn->session_info->unix_token->gid);
3428 if (data_len >= max_data_bytes) {
3429 /* Potential overflow, skip the GIDs and SIDs. */
3431 SIVAL(pdata, 24, 0); /* num_groups */
3432 SIVAL(pdata, 28, 0); /* num_sids */
3433 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3434 SIVAL(pdata, 36, 0); /* reserved */
3440 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3441 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3443 /* We walk the SID list twice, but this call is fairly
3444 * infrequent, and I don't expect that it's performance
3445 * sensitive -- jpeach
3447 for (i = 0, sid_bytes = 0;
3448 i < conn->session_info->security_token->num_sids; ++i) {
3449 sid_bytes += ndr_size_dom_sid(
3450 &conn->session_info->security_token->sids[i],
3454 /* SID list byte count */
3455 SIVAL(pdata, 32, sid_bytes);
3457 /* 4 bytes pad/reserved - must be zero */
3458 SIVAL(pdata, 36, 0);
3462 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3463 SBIG_UINT(pdata, data_len,
3464 (uint64_t)conn->session_info->unix_token->groups[i]);
3470 i < conn->session_info->security_token->num_sids; ++i) {
3471 int sid_len = ndr_size_dom_sid(
3472 &conn->session_info->security_token->sids[i],
3475 sid_linearize(pdata + data_len, sid_len,
3476 &conn->session_info->security_token->sids[i]);
3477 data_len += sid_len;
3483 case SMB_MAC_QUERY_FS_INFO:
3485 * Thursby MAC extension... ONLY on NTFS filesystems
3486 * once we do streams then we don't need this
3488 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3490 SIVAL(pdata,84,0x100); /* Don't support mac... */
3495 return NT_STATUS_INVALID_LEVEL;
3498 *ret_data_len = data_len;
3499 return NT_STATUS_OK;
3502 /****************************************************************************
3503 Reply to a TRANS2_QFSINFO (query filesystem info).
3504 ****************************************************************************/
3506 static void call_trans2qfsinfo(connection_struct *conn,
3507 struct smb_request *req,
3508 char **pparams, int total_params,
3509 char **ppdata, int total_data,
3510 unsigned int max_data_bytes)
3512 char *params = *pparams;
3513 uint16_t info_level;
3517 if (total_params < 2) {
3518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3522 info_level = SVAL(params,0);
3524 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3525 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3526 DEBUG(0,("call_trans2qfsinfo: encryption required "
3527 "and info level 0x%x sent.\n",
3528 (unsigned int)info_level));
3529 exit_server_cleanly("encryption required "
3535 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3537 status = smbd_do_qfsinfo(conn, req,
3542 if (!NT_STATUS_IS_OK(status)) {
3543 reply_nterror(req, status);
3547 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3550 DEBUG( 4, ( "%s info_level = %d\n",
3551 smb_fn_name(req->cmd), info_level) );
3556 /****************************************************************************
3557 Reply to a TRANS2_SETFSINFO (set filesystem info).
3558 ****************************************************************************/
3560 static void call_trans2setfsinfo(connection_struct *conn,
3561 struct smb_request *req,
3562 char **pparams, int total_params,
3563 char **ppdata, int total_data,
3564 unsigned int max_data_bytes)
3566 struct smbd_server_connection *sconn = req->sconn;
3567 char *pdata = *ppdata;
3568 char *params = *pparams;
3571 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3574 if (total_params < 4) {
3575 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3577 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3581 info_level = SVAL(params,2);
3584 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3585 info_level != SMB_SET_CIFS_UNIX_INFO) {
3586 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3587 "info level (0x%x) on IPC$.\n",
3588 (unsigned int)info_level));
3589 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3594 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3595 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3596 DEBUG(0,("call_trans2setfsinfo: encryption required "
3597 "and info level 0x%x sent.\n",
3598 (unsigned int)info_level));
3599 exit_server_cleanly("encryption required "
3605 switch(info_level) {
3606 case SMB_SET_CIFS_UNIX_INFO:
3607 if (!lp_unix_extensions()) {
3609 NT_STATUS_INVALID_LEVEL);
3613 /* There should be 12 bytes of capabilities set. */
3614 if (total_data < 8) {
3617 NT_STATUS_INVALID_PARAMETER);
3620 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3621 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3622 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3623 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3624 /* Just print these values for now. */
3625 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3626 "major = %u, minor = %u cap_low = 0x%x, "
3628 (unsigned int)sconn->
3629 smb1.unix_info.client_major,
3630 (unsigned int)sconn->
3631 smb1.unix_info.client_minor,
3632 (unsigned int)sconn->
3633 smb1.unix_info.client_cap_low,
3634 (unsigned int)sconn->
3635 smb1.unix_info.client_cap_high));
3637 /* Here is where we must switch to posix pathname processing... */
3638 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3639 lp_set_posix_pathnames();
3640 mangle_change_to_posix();
3643 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3644 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3645 /* Client that knows how to do posix locks,
3646 * but not posix open/mkdir operations. Set a
3647 * default type for read/write checks. */
3649 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3654 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3657 size_t param_len = 0;
3658 size_t data_len = total_data;
3660 if (!lp_unix_extensions()) {
3663 NT_STATUS_INVALID_LEVEL);
3667 if (lp_smb_encrypt(SNUM(conn)) == false) {
3670 NT_STATUS_NOT_SUPPORTED);
3674 if (req->sconn->smb1.echo_handler.trusted_fde) {
3675 DEBUG( 2,("call_trans2setfsinfo: "
3676 "request transport encryption disabled"
3677 "with 'fork echo handler = yes'\n"));
3680 NT_STATUS_NOT_SUPPORTED);
3684 DEBUG( 4,("call_trans2setfsinfo: "
3685 "request transport encryption.\n"));
3687 status = srv_request_encryption_setup(conn,
3688 (unsigned char **)ppdata,
3690 (unsigned char **)pparams,
3693 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3694 !NT_STATUS_IS_OK(status)) {
3695 reply_nterror(req, status);
3699 send_trans2_replies(conn, req,
3706 if (NT_STATUS_IS_OK(status)) {
3707 /* Server-side transport
3708 * encryption is now *on*. */
3709 status = srv_encryption_start(conn);
3710 if (!NT_STATUS_IS_OK(status)) {
3711 char *reason = talloc_asprintf(talloc_tos(),
3712 "Failure in setting "
3713 "up encrypted transport: %s",
3715 exit_server_cleanly(reason);
3721 case SMB_FS_QUOTA_INFORMATION:
3723 files_struct *fsp = NULL;
3724 SMB_NTQUOTA_STRUCT quotas;
3726 ZERO_STRUCT(quotas);
3729 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3730 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3731 lp_servicename(SNUM(conn)),
3732 conn->session_info->unix_info->unix_name));
3733 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3737 /* note: normaly there're 48 bytes,
3738 * but we didn't use the last 6 bytes for now
3741 fsp = file_fsp(req, SVAL(params,0));
3743 if (!check_fsp_ntquota_handle(conn, req,
3745 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3747 req, NT_STATUS_INVALID_HANDLE);
3751 if (total_data < 42) {
3752 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3756 NT_STATUS_INVALID_PARAMETER);
3760 /* unknown_1 24 NULL bytes in pdata*/
3762 /* the soft quotas 8 bytes (uint64_t)*/
3763 quotas.softlim = BVAL(pdata,24);
3765 /* the hard quotas 8 bytes (uint64_t)*/
3766 quotas.hardlim = BVAL(pdata,32);
3768 /* quota_flags 2 bytes **/
3769 quotas.qflags = SVAL(pdata,40);
3771 /* unknown_2 6 NULL bytes follow*/
3773 /* now set the quotas */
3774 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3775 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3776 reply_nterror(req, map_nt_error_from_unix(errno));
3783 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3785 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3791 * sending this reply works fine,
3792 * but I'm not sure it's the same
3793 * like windows do...
3796 reply_outbuf(req, 10, 0);
3799 #if defined(HAVE_POSIX_ACLS)
3800 /****************************************************************************
3801 Utility function to count the number of entries in a POSIX acl.
3802 ****************************************************************************/
3804 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3806 unsigned int ace_count = 0;
3807 int entry_id = SMB_ACL_FIRST_ENTRY;
3808 SMB_ACL_ENTRY_T entry;
3810 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3812 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3813 entry_id = SMB_ACL_NEXT_ENTRY;
3820 /****************************************************************************
3821 Utility function to marshall a POSIX acl into wire format.
3822 ****************************************************************************/
3824 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3826 int entry_id = SMB_ACL_FIRST_ENTRY;
3827 SMB_ACL_ENTRY_T entry;
3829 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3830 SMB_ACL_TAG_T tagtype;
3831 SMB_ACL_PERMSET_T permset;
3832 unsigned char perms = 0;
3833 unsigned int own_grp;
3836 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3837 entry_id = SMB_ACL_NEXT_ENTRY;
3840 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3841 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3845 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3846 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3850 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3851 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3852 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3854 SCVAL(pdata,1,perms);
3857 case SMB_ACL_USER_OBJ:
3858 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3859 own_grp = (unsigned int)pst->st_ex_uid;
3860 SIVAL(pdata,2,own_grp);
3865 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3867 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3870 own_grp = (unsigned int)*puid;
3871 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3872 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3873 SIVAL(pdata,2,own_grp);
3877 case SMB_ACL_GROUP_OBJ:
3878 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3879 own_grp = (unsigned int)pst->st_ex_gid;
3880 SIVAL(pdata,2,own_grp);
3885 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3887 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3890 own_grp = (unsigned int)*pgid;
3891 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3892 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3893 SIVAL(pdata,2,own_grp);
3898 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3899 SIVAL(pdata,2,0xFFFFFFFF);
3900 SIVAL(pdata,6,0xFFFFFFFF);
3903 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3904 SIVAL(pdata,2,0xFFFFFFFF);
3905 SIVAL(pdata,6,0xFFFFFFFF);
3908 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3911 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3918 /****************************************************************************
3919 Store the FILE_UNIX_BASIC info.
3920 ****************************************************************************/
3922 static char *store_file_unix_basic(connection_struct *conn,
3925 const SMB_STRUCT_STAT *psbuf)
3927 uint64_t file_index = get_FileIndex(conn, psbuf);
3929 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3930 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3932 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3935 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3938 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3939 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3940 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3943 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3947 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3951 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3954 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3958 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3962 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3965 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3969 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3976 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3977 * the chflags(2) (or equivalent) flags.
3979 * XXX: this really should be behind the VFS interface. To do this, we would
3980 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3981 * Each VFS module could then implement its own mapping as appropriate for the
3982 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3984 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3988 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3992 { UF_IMMUTABLE, EXT_IMMUTABLE },
3996 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4000 { UF_HIDDEN, EXT_HIDDEN },
4003 /* Do not remove. We need to guarantee that this array has at least one
4004 * entry to build on HP-UX.
4010 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4011 uint32 *smb_fflags, uint32 *smb_fmask)
4015 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4016 *smb_fmask |= info2_flags_map[i].smb_fflag;
4017 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4018 *smb_fflags |= info2_flags_map[i].smb_fflag;
4023 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4024 const uint32 smb_fflags,
4025 const uint32 smb_fmask,
4028 uint32 max_fmask = 0;
4031 *stat_fflags = psbuf->st_ex_flags;
4033 /* For each flags requested in smb_fmask, check the state of the
4034 * corresponding flag in smb_fflags and set or clear the matching
4038 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4039 max_fmask |= info2_flags_map[i].smb_fflag;
4040 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4041 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4042 *stat_fflags |= info2_flags_map[i].stat_fflag;
4044 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4049 /* If smb_fmask is asking to set any bits that are not supported by
4050 * our flag mappings, we should fail.
4052 if ((smb_fmask & max_fmask) != smb_fmask) {
4060 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4061 * of file flags and birth (create) time.
4063 static char *store_file_unix_basic_info2(connection_struct *conn,
4066 const SMB_STRUCT_STAT *psbuf)
4068 uint32 file_flags = 0;
4069 uint32 flags_mask = 0;
4071 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4073 /* Create (birth) time 64 bit */
4074 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4077 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4078 SIVAL(pdata, 0, file_flags); /* flags */
4079 SIVAL(pdata, 4, flags_mask); /* mask */
4085 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4086 const struct stream_struct *streams,
4088 unsigned int max_data_bytes,
4089 unsigned int *data_size)
4092 unsigned int ofs = 0;
4094 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4095 unsigned int next_offset;
4097 smb_ucs2_t *namebuf;
4099 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4100 streams[i].name, &namelen) ||
4103 return NT_STATUS_INVALID_PARAMETER;
4107 * name_buf is now null-terminated, we need to marshall as not
4113 SIVAL(data, ofs+4, namelen);
4114 SOFF_T(data, ofs+8, streams[i].size);
4115 SOFF_T(data, ofs+16, streams[i].alloc_size);
4116 memcpy(data+ofs+24, namebuf, namelen);
4117 TALLOC_FREE(namebuf);
4119 next_offset = ofs + 24 + namelen;
4121 if (i == num_streams-1) {
4122 SIVAL(data, ofs, 0);
4125 unsigned int align = ndr_align_size(next_offset, 8);
4127 memset(data+next_offset, 0, align);
4128 next_offset += align;
4130 SIVAL(data, ofs, next_offset - ofs);
4139 return NT_STATUS_OK;
4142 /****************************************************************************
4143 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4144 ****************************************************************************/
4146 static void call_trans2qpipeinfo(connection_struct *conn,
4147 struct smb_request *req,
4148 unsigned int tran_call,
4149 char **pparams, int total_params,
4150 char **ppdata, int total_data,
4151 unsigned int max_data_bytes)
4153 char *params = *pparams;
4154 char *pdata = *ppdata;
4155 unsigned int data_size = 0;
4156 unsigned int param_size = 2;
4161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4165 if (total_params < 4) {
4166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4170 fsp = file_fsp(req, SVAL(params,0));
4171 if (!fsp_is_np(fsp)) {
4172 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4176 info_level = SVAL(params,2);
4178 *pparams = (char *)SMB_REALLOC(*pparams,2);
4179 if (*pparams == NULL) {
4180 reply_nterror(req, NT_STATUS_NO_MEMORY);
4185 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4186 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4187 if (*ppdata == NULL ) {
4188 reply_nterror(req, NT_STATUS_NO_MEMORY);
4193 switch (info_level) {
4194 case SMB_FILE_STANDARD_INFORMATION:
4196 SOFF_T(pdata,0,4096LL);
4203 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4207 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4213 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4214 TALLOC_CTX *mem_ctx,
4215 uint16_t info_level,
4217 struct smb_filename *smb_fname,
4218 bool delete_pending,
4219 struct timespec write_time_ts,
4220 struct ea_list *ea_list,
4221 int lock_data_count,
4224 unsigned int max_data_bytes,
4226 unsigned int *pdata_size)
4228 char *pdata = *ppdata;
4229 char *dstart, *dend;
4230 unsigned int data_size;
4231 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4232 time_t create_time, mtime, atime, c_time;
4233 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4240 uint64_t file_size = 0;
4242 uint64_t allocation_size = 0;
4243 uint64_t file_index = 0;
4244 uint32_t access_mask = 0;
4246 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4247 return NT_STATUS_INVALID_LEVEL;
4250 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4251 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4252 info_level, max_data_bytes));
4254 mode = dos_mode(conn, smb_fname);
4255 nlink = psbuf->st_ex_nlink;
4257 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4261 if ((nlink > 0) && delete_pending) {
4265 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4266 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4267 if (*ppdata == NULL) {
4268 return NT_STATUS_NO_MEMORY;
4272 dend = dstart + data_size - 1;
4274 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4275 update_stat_ex_mtime(psbuf, write_time_ts);
4278 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4279 mtime_ts = psbuf->st_ex_mtime;
4280 atime_ts = psbuf->st_ex_atime;
4281 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4283 if (lp_dos_filetime_resolution(SNUM(conn))) {
4284 dos_filetime_timespec(&create_time_ts);
4285 dos_filetime_timespec(&mtime_ts);
4286 dos_filetime_timespec(&atime_ts);
4287 dos_filetime_timespec(&ctime_ts);
4290 create_time = convert_timespec_to_time_t(create_time_ts);
4291 mtime = convert_timespec_to_time_t(mtime_ts);
4292 atime = convert_timespec_to_time_t(atime_ts);
4293 c_time = convert_timespec_to_time_t(ctime_ts);
4295 p = strrchr_m(smb_fname->base_name,'/');
4297 base_name = smb_fname->base_name;
4301 /* NT expects the name to be in an exact form of the *full*
4302 filename. See the trans2 torture test */
4303 if (ISDOT(base_name)) {
4304 dos_fname = talloc_strdup(mem_ctx, "\\");
4306 return NT_STATUS_NO_MEMORY;
4309 dos_fname = talloc_asprintf(mem_ctx,
4311 smb_fname->base_name);
4313 return NT_STATUS_NO_MEMORY;
4315 if (is_ntfs_stream_smb_fname(smb_fname)) {
4316 dos_fname = talloc_asprintf(dos_fname, "%s",
4317 smb_fname->stream_name);
4319 return NT_STATUS_NO_MEMORY;
4323 string_replace(dos_fname, '/', '\\');
4326 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4329 /* Do we have this path open ? */
4331 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4332 fsp1 = file_find_di_first(conn->sconn, fileid);
4333 if (fsp1 && fsp1->initial_allocation_size) {
4334 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4338 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4339 file_size = get_file_size_stat(psbuf);
4343 pos = fsp->fh->position_information;
4347 access_mask = fsp->access_mask;
4349 /* GENERIC_EXECUTE mapping from Windows */
4350 access_mask = 0x12019F;
4353 /* This should be an index number - looks like
4356 I think this causes us to fail the IFSKIT
4357 BasicFileInformationTest. -tpot */
4358 file_index = get_FileIndex(conn, psbuf);
4360 switch (info_level) {
4361 case SMB_INFO_STANDARD:
4362 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4364 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4365 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4366 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4367 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4368 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4369 SSVAL(pdata,l1_attrFile,mode);
4372 case SMB_INFO_QUERY_EA_SIZE:
4374 unsigned int ea_size =
4375 estimate_ea_size(conn, fsp,
4376 smb_fname->base_name);
4377 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4379 srv_put_dos_date2(pdata,0,create_time);
4380 srv_put_dos_date2(pdata,4,atime);
4381 srv_put_dos_date2(pdata,8,mtime); /* write time */
4382 SIVAL(pdata,12,(uint32)file_size);
4383 SIVAL(pdata,16,(uint32)allocation_size);
4384 SSVAL(pdata,20,mode);
4385 SIVAL(pdata,22,ea_size);
4389 case SMB_INFO_IS_NAME_VALID:
4390 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4392 /* os/2 needs this ? really ?*/
4393 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4395 /* This is only reached for qpathinfo */
4399 case SMB_INFO_QUERY_EAS_FROM_LIST:
4401 size_t total_ea_len = 0;
4402 struct ea_list *ea_file_list = NULL;
4404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4407 get_ea_list_from_file(mem_ctx, conn, fsp,
4408 smb_fname->base_name,
4410 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4412 if (!ea_list || (total_ea_len > data_size)) {
4414 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4418 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4422 case SMB_INFO_QUERY_ALL_EAS:
4424 /* We have data_size bytes to put EA's into. */
4425 size_t total_ea_len = 0;
4427 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4429 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4430 smb_fname->base_name,
4432 if (!ea_list || (total_ea_len > data_size)) {
4434 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4438 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4442 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4444 /* This is FileFullEaInformation - 0xF which maps to
4445 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4447 /* We have data_size bytes to put EA's into. */
4448 size_t total_ea_len = 0;
4449 struct ea_list *ea_file_list = NULL;
4451 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4453 /*TODO: add filtering and index handling */
4456 get_ea_list_from_file(mem_ctx, conn, fsp,
4457 smb_fname->base_name,
4459 if (!ea_file_list) {
4460 return NT_STATUS_NO_EAS_ON_FILE;
4463 status = fill_ea_chained_buffer(mem_ctx,
4467 conn, ea_file_list);
4468 if (!NT_STATUS_IS_OK(status)) {
4474 case SMB_FILE_BASIC_INFORMATION:
4475 case SMB_QUERY_FILE_BASIC_INFO:
4477 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4478 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4479 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4481 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4485 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4486 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4487 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4488 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4489 SIVAL(pdata,32,mode);
4491 DEBUG(5,("SMB_QFBI - "));
4492 DEBUG(5,("create: %s ", ctime(&create_time)));
4493 DEBUG(5,("access: %s ", ctime(&atime)));
4494 DEBUG(5,("write: %s ", ctime(&mtime)));
4495 DEBUG(5,("change: %s ", ctime(&c_time)));
4496 DEBUG(5,("mode: %x\n", mode));
4499 case SMB_FILE_STANDARD_INFORMATION:
4500 case SMB_QUERY_FILE_STANDARD_INFO:
4502 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4504 SOFF_T(pdata,0,allocation_size);
4505 SOFF_T(pdata,8,file_size);
4506 SIVAL(pdata,16,nlink);
4507 SCVAL(pdata,20,delete_pending?1:0);
4508 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4509 SSVAL(pdata,22,0); /* Padding. */
4512 case SMB_FILE_EA_INFORMATION:
4513 case SMB_QUERY_FILE_EA_INFO:
4515 unsigned int ea_size =
4516 estimate_ea_size(conn, fsp, smb_fname->base_name);
4517 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4519 SIVAL(pdata,0,ea_size);
4523 /* Get the 8.3 name - used if NT SMB was negotiated. */
4524 case SMB_QUERY_FILE_ALT_NAME_INFO:
4525 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4528 char mangled_name[13];
4529 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4530 if (!name_to_8_3(base_name,mangled_name,
4531 True,conn->params)) {
4532 return NT_STATUS_NO_MEMORY;
4534 len = srvstr_push(dstart, flags2,
4535 pdata+4, mangled_name,
4536 PTR_DIFF(dend, pdata+4),
4538 data_size = 4 + len;
4543 case SMB_QUERY_FILE_NAME_INFO:
4547 this must be *exactly* right for ACLs on mapped drives to work
4549 len = srvstr_push(dstart, flags2,
4551 PTR_DIFF(dend, pdata+4),
4553 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4554 data_size = 4 + len;
4559 case SMB_FILE_ALLOCATION_INFORMATION:
4560 case SMB_QUERY_FILE_ALLOCATION_INFO:
4561 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4563 SOFF_T(pdata,0,allocation_size);
4566 case SMB_FILE_END_OF_FILE_INFORMATION:
4567 case SMB_QUERY_FILE_END_OF_FILEINFO:
4568 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4570 SOFF_T(pdata,0,file_size);
4573 case SMB_QUERY_FILE_ALL_INFO:
4574 case SMB_FILE_ALL_INFORMATION:
4577 unsigned int ea_size =
4578 estimate_ea_size(conn, fsp, smb_fname->base_name);
4579 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4580 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4581 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4582 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4583 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4584 SIVAL(pdata,32,mode);
4585 SIVAL(pdata,36,0); /* padding. */
4587 SOFF_T(pdata,0,allocation_size);
4588 SOFF_T(pdata,8,file_size);
4589 SIVAL(pdata,16,nlink);
4590 SCVAL(pdata,20,delete_pending);
4591 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4594 SIVAL(pdata,0,ea_size);
4595 pdata += 4; /* EA info */
4596 len = srvstr_push(dstart, flags2,
4598 PTR_DIFF(dend, pdata+4),
4602 data_size = PTR_DIFF(pdata,(*ppdata));
4606 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4609 unsigned int ea_size =
4610 estimate_ea_size(conn, fsp, smb_fname->base_name);
4611 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4612 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4613 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4614 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4615 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4616 SIVAL(pdata, 0x20, mode);
4617 SIVAL(pdata, 0x24, 0); /* padding. */
4618 SBVAL(pdata, 0x28, allocation_size);
4619 SBVAL(pdata, 0x30, file_size);
4620 SIVAL(pdata, 0x38, nlink);
4621 SCVAL(pdata, 0x3C, delete_pending);
4622 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4623 SSVAL(pdata, 0x3E, 0); /* padding */
4624 SBVAL(pdata, 0x40, file_index);
4625 SIVAL(pdata, 0x48, ea_size);
4626 SIVAL(pdata, 0x4C, access_mask);
4627 SBVAL(pdata, 0x50, pos);
4628 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4629 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4633 len = srvstr_push(dstart, flags2,
4635 PTR_DIFF(dend, pdata+4),
4639 data_size = PTR_DIFF(pdata,(*ppdata));
4642 case SMB_FILE_INTERNAL_INFORMATION:
4644 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4645 SBVAL(pdata, 0, file_index);
4649 case SMB_FILE_ACCESS_INFORMATION:
4650 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4651 SIVAL(pdata, 0, access_mask);
4655 case SMB_FILE_NAME_INFORMATION:
4656 /* Pathname with leading '\'. */
4659 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4660 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4661 SIVAL(pdata,0,byte_len);
4662 data_size = 4 + byte_len;
4666 case SMB_FILE_DISPOSITION_INFORMATION:
4667 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4669 SCVAL(pdata,0,delete_pending);
4672 case SMB_FILE_POSITION_INFORMATION:
4673 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4675 SOFF_T(pdata,0,pos);
4678 case SMB_FILE_MODE_INFORMATION:
4679 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4680 SIVAL(pdata,0,mode);
4684 case SMB_FILE_ALIGNMENT_INFORMATION:
4685 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4686 SIVAL(pdata,0,0); /* No alignment needed. */
4691 * NT4 server just returns "invalid query" to this - if we try
4692 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4695 /* The first statement above is false - verified using Thursby
4696 * client against NT4 -- gcolley.
4698 case SMB_QUERY_FILE_STREAM_INFO:
4699 case SMB_FILE_STREAM_INFORMATION: {
4700 unsigned int num_streams = 0;
4701 struct stream_struct *streams = NULL;
4703 DEBUG(10,("smbd_do_qfilepathinfo: "
4704 "SMB_FILE_STREAM_INFORMATION\n"));
4706 if (is_ntfs_stream_smb_fname(smb_fname)) {
4707 return NT_STATUS_INVALID_PARAMETER;
4710 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4711 talloc_tos(), &num_streams, &streams);
4713 if (!NT_STATUS_IS_OK(status)) {
4714 DEBUG(10, ("could not get stream info: %s\n",
4715 nt_errstr(status)));
4719 status = marshall_stream_info(num_streams, streams,
4720 pdata, max_data_bytes,
4723 if (!NT_STATUS_IS_OK(status)) {
4724 DEBUG(10, ("marshall_stream_info failed: %s\n",
4725 nt_errstr(status)));
4729 TALLOC_FREE(streams);
4733 case SMB_QUERY_COMPRESSION_INFO:
4734 case SMB_FILE_COMPRESSION_INFORMATION:
4735 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4736 SOFF_T(pdata,0,file_size);
4737 SIVAL(pdata,8,0); /* ??? */
4738 SIVAL(pdata,12,0); /* ??? */
4742 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4743 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4744 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4745 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4746 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4747 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4748 SOFF_T(pdata,32,allocation_size);
4749 SOFF_T(pdata,40,file_size);
4750 SIVAL(pdata,48,mode);
4751 SIVAL(pdata,52,0); /* ??? */
4755 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4756 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4757 SIVAL(pdata,0,mode);
4763 * CIFS UNIX Extensions.
4766 case SMB_QUERY_FILE_UNIX_BASIC:
4768 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4769 data_size = PTR_DIFF(pdata,(*ppdata));
4771 DEBUG(4,("smbd_do_qfilepathinfo: "
4772 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4773 dump_data(4, (uint8_t *)(*ppdata), data_size);
4777 case SMB_QUERY_FILE_UNIX_INFO2:
4779 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4780 data_size = PTR_DIFF(pdata,(*ppdata));
4784 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4786 for (i=0; i<100; i++)
4787 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4793 case SMB_QUERY_FILE_UNIX_LINK:
4796 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4799 return NT_STATUS_NO_MEMORY;
4802 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4804 if(!S_ISLNK(psbuf->st_ex_mode)) {
4805 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4808 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4810 len = SMB_VFS_READLINK(conn,
4811 smb_fname->base_name,
4814 return map_nt_error_from_unix(errno);
4817 len = srvstr_push(dstart, flags2,
4819 PTR_DIFF(dend, pdata),
4822 data_size = PTR_DIFF(pdata,(*ppdata));
4827 #if defined(HAVE_POSIX_ACLS)
4828 case SMB_QUERY_POSIX_ACL:
4830 SMB_ACL_T file_acl = NULL;
4831 SMB_ACL_T def_acl = NULL;
4832 uint16 num_file_acls = 0;
4833 uint16 num_def_acls = 0;
4835 if (fsp && fsp->fh->fd != -1) {
4836 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4839 SMB_VFS_SYS_ACL_GET_FILE(conn,
4840 smb_fname->base_name,
4841 SMB_ACL_TYPE_ACCESS);
4844 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4845 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4846 "not implemented on "
4847 "filesystem containing %s\n",
4848 smb_fname->base_name));
4849 return NT_STATUS_NOT_IMPLEMENTED;
4852 if (S_ISDIR(psbuf->st_ex_mode)) {
4853 if (fsp && fsp->is_directory) {
4855 SMB_VFS_SYS_ACL_GET_FILE(
4857 fsp->fsp_name->base_name,
4858 SMB_ACL_TYPE_DEFAULT);
4861 SMB_VFS_SYS_ACL_GET_FILE(
4863 smb_fname->base_name,
4864 SMB_ACL_TYPE_DEFAULT);
4866 def_acl = free_empty_sys_acl(conn, def_acl);
4869 num_file_acls = count_acl_entries(conn, file_acl);
4870 num_def_acls = count_acl_entries(conn, def_acl);
4872 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4873 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4875 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4876 SMB_POSIX_ACL_HEADER_SIZE) ));
4878 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4881 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4883 return NT_STATUS_BUFFER_TOO_SMALL;
4886 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4887 SSVAL(pdata,2,num_file_acls);
4888 SSVAL(pdata,4,num_def_acls);
4889 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4891 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4894 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4896 return NT_STATUS_INTERNAL_ERROR;
4898 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4900 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4903 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4905 return NT_STATUS_INTERNAL_ERROR;
4909 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4912 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4914 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4920 case SMB_QUERY_POSIX_LOCK:
4925 enum brl_type lock_type;
4927 /* We need an open file with a real fd for this. */
4928 if (!fsp || fsp->fh->fd == -1) {
4929 return NT_STATUS_INVALID_LEVEL;
4932 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4933 return NT_STATUS_INVALID_PARAMETER;
4936 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4937 case POSIX_LOCK_TYPE_READ:
4938 lock_type = READ_LOCK;
4940 case POSIX_LOCK_TYPE_WRITE:
4941 lock_type = WRITE_LOCK;
4943 case POSIX_LOCK_TYPE_UNLOCK:
4945 /* There's no point in asking for an unlock... */
4946 return NT_STATUS_INVALID_PARAMETER;
4949 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4950 #if defined(HAVE_LONGLONG)
4951 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4952 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4953 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4954 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4955 #else /* HAVE_LONGLONG */
4956 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4957 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4958 #endif /* HAVE_LONGLONG */
4960 status = query_lock(fsp,
4967 if (ERROR_WAS_LOCK_DENIED(status)) {
4968 /* Here we need to report who has it locked... */
4969 data_size = POSIX_LOCK_DATA_SIZE;
4971 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4972 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4973 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4974 #if defined(HAVE_LONGLONG)
4975 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4976 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4977 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4978 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4979 #else /* HAVE_LONGLONG */
4980 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4981 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4982 #endif /* HAVE_LONGLONG */
4984 } else if (NT_STATUS_IS_OK(status)) {
4985 /* For success we just return a copy of what we sent
4986 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4987 data_size = POSIX_LOCK_DATA_SIZE;
4988 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4989 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4997 return NT_STATUS_INVALID_LEVEL;
5000 *pdata_size = data_size;
5001 return NT_STATUS_OK;
5004 /****************************************************************************
5005 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5006 file name or file id).
5007 ****************************************************************************/
5009 static void call_trans2qfilepathinfo(connection_struct *conn,
5010 struct smb_request *req,
5011 unsigned int tran_call,
5012 char **pparams, int total_params,
5013 char **ppdata, int total_data,
5014 unsigned int max_data_bytes)
5016 char *params = *pparams;
5017 char *pdata = *ppdata;
5019 unsigned int data_size = 0;
5020 unsigned int param_size = 2;
5021 struct smb_filename *smb_fname = NULL;
5022 bool delete_pending = False;
5023 struct timespec write_time_ts;
5024 files_struct *fsp = NULL;
5025 struct file_id fileid;
5026 struct ea_list *ea_list = NULL;
5027 int lock_data_count = 0;
5028 char *lock_data = NULL;
5029 NTSTATUS status = NT_STATUS_OK;
5032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5036 ZERO_STRUCT(write_time_ts);
5038 if (tran_call == TRANSACT2_QFILEINFO) {
5039 if (total_params < 4) {
5040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5045 call_trans2qpipeinfo(conn, req, tran_call,
5046 pparams, total_params,
5052 fsp = file_fsp(req, SVAL(params,0));
5053 info_level = SVAL(params,2);
5055 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5057 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5058 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5062 /* Initial check for valid fsp ptr. */
5063 if (!check_fsp_open(conn, req, fsp)) {
5067 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5069 if (!NT_STATUS_IS_OK(status)) {
5070 reply_nterror(req, status);
5074 if(fsp->fake_file_handle) {
5076 * This is actually for the QUOTA_FAKE_FILE --metze
5079 /* We know this name is ok, it's already passed the checks. */
5081 } else if(fsp->fh->fd == -1) {
5083 * This is actually a QFILEINFO on a directory
5084 * handle (returned from an NT SMB). NT5.0 seems
5085 * to do this call. JRA.
5088 if (INFO_LEVEL_IS_UNIX(info_level)) {
5089 /* Always do lstat for UNIX calls. */
5090 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5091 DEBUG(3,("call_trans2qfilepathinfo: "
5092 "SMB_VFS_LSTAT of %s failed "
5094 smb_fname_str_dbg(smb_fname),
5097 map_nt_error_from_unix(errno));
5100 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5101 DEBUG(3,("call_trans2qfilepathinfo: "
5102 "SMB_VFS_STAT of %s failed (%s)\n",
5103 smb_fname_str_dbg(smb_fname),
5106 map_nt_error_from_unix(errno));
5110 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5111 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5114 * Original code - this is an open file.
5116 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5117 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5118 fsp->fnum, strerror(errno)));
5120 map_nt_error_from_unix(errno));
5123 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5124 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5130 uint32_t ucf_flags = 0;
5133 if (total_params < 7) {
5134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5138 info_level = SVAL(params,0);
5140 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5142 if (INFO_LEVEL_IS_UNIX(info_level)) {
5143 if (!lp_unix_extensions()) {
5144 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5147 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5148 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5149 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5150 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5154 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5156 STR_TERMINATE, &status);
5157 if (!NT_STATUS_IS_OK(status)) {
5158 reply_nterror(req, status);
5162 status = filename_convert(req,
5164 req->flags2 & FLAGS2_DFS_PATHNAMES,
5169 if (!NT_STATUS_IS_OK(status)) {
5170 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5171 reply_botherror(req,
5172 NT_STATUS_PATH_NOT_COVERED,
5173 ERRSRV, ERRbadpath);
5176 reply_nterror(req, status);
5180 /* If this is a stream, check if there is a delete_pending. */
5181 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5182 && is_ntfs_stream_smb_fname(smb_fname)) {
5183 struct smb_filename *smb_fname_base = NULL;
5185 /* Create an smb_filename with stream_name == NULL. */
5187 create_synthetic_smb_fname(talloc_tos(),
5188 smb_fname->base_name,
5191 if (!NT_STATUS_IS_OK(status)) {
5192 reply_nterror(req, status);
5196 if (INFO_LEVEL_IS_UNIX(info_level)) {
5197 /* Always do lstat for UNIX calls. */
5198 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5199 DEBUG(3,("call_trans2qfilepathinfo: "
5200 "SMB_VFS_LSTAT of %s failed "
5202 smb_fname_str_dbg(smb_fname_base),
5204 TALLOC_FREE(smb_fname_base);
5206 map_nt_error_from_unix(errno));
5210 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5211 DEBUG(3,("call_trans2qfilepathinfo: "
5212 "fileinfo of %s failed "
5214 smb_fname_str_dbg(smb_fname_base),
5216 TALLOC_FREE(smb_fname_base);
5218 map_nt_error_from_unix(errno));
5223 status = file_name_hash(conn,
5224 smb_fname_str_dbg(smb_fname_base),
5226 if (!NT_STATUS_IS_OK(status)) {
5227 TALLOC_FREE(smb_fname_base);
5228 reply_nterror(req, status);
5232 fileid = vfs_file_id_from_sbuf(conn,
5233 &smb_fname_base->st);
5234 TALLOC_FREE(smb_fname_base);
5235 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5236 if (delete_pending) {
5237 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5242 if (INFO_LEVEL_IS_UNIX(info_level)) {
5243 /* Always do lstat for UNIX calls. */
5244 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5245 DEBUG(3,("call_trans2qfilepathinfo: "
5246 "SMB_VFS_LSTAT of %s failed (%s)\n",
5247 smb_fname_str_dbg(smb_fname),
5250 map_nt_error_from_unix(errno));
5255 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5256 DEBUG(3,("call_trans2qfilepathinfo: "
5257 "SMB_VFS_STAT of %s failed (%s)\n",
5258 smb_fname_str_dbg(smb_fname),
5261 map_nt_error_from_unix(errno));
5266 status = file_name_hash(conn,
5267 smb_fname_str_dbg(smb_fname),
5269 if (!NT_STATUS_IS_OK(status)) {
5270 reply_nterror(req, status);
5274 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5275 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5276 if (delete_pending) {
5277 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5282 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5283 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5284 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5286 /* Pull out any data sent here before we realloc. */
5287 switch (info_level) {
5288 case SMB_INFO_QUERY_EAS_FROM_LIST:
5290 /* Pull any EA list from the data portion. */
5293 if (total_data < 4) {
5295 req, NT_STATUS_INVALID_PARAMETER);
5298 ea_size = IVAL(pdata,0);
5300 if (total_data > 0 && ea_size != total_data) {
5301 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5302 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5304 req, NT_STATUS_INVALID_PARAMETER);
5308 if (!lp_ea_support(SNUM(conn))) {
5309 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5313 /* Pull out the list of names. */
5314 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5317 req, NT_STATUS_INVALID_PARAMETER);
5323 case SMB_QUERY_POSIX_LOCK:
5325 if (fsp == NULL || fsp->fh->fd == -1) {
5326 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5330 if (total_data != POSIX_LOCK_DATA_SIZE) {
5332 req, NT_STATUS_INVALID_PARAMETER);
5336 /* Copy the lock range data. */
5337 lock_data = (char *)talloc_memdup(
5338 req, pdata, total_data);
5340 reply_nterror(req, NT_STATUS_NO_MEMORY);
5343 lock_data_count = total_data;
5349 *pparams = (char *)SMB_REALLOC(*pparams,2);
5350 if (*pparams == NULL) {
5351 reply_nterror(req, NT_STATUS_NO_MEMORY);
5358 * draft-leach-cifs-v1-spec-02.txt
5359 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5362 * The requested information is placed in the Data portion of the
5363 * transaction response. For the information levels greater than 0x100,
5364 * the transaction response has 1 parameter word which should be
5365 * ignored by the client.
5367 * However Windows only follows this rule for the IS_NAME_VALID call.
5369 switch (info_level) {
5370 case SMB_INFO_IS_NAME_VALID:
5375 if ((info_level & 0xFF00) == 0xFF00) {
5377 * We use levels that start with 0xFF00
5378 * internally to represent SMB2 specific levels
5380 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5384 status = smbd_do_qfilepathinfo(conn, req, info_level,
5386 delete_pending, write_time_ts,
5388 lock_data_count, lock_data,
5389 req->flags2, max_data_bytes,
5390 ppdata, &data_size);
5391 if (!NT_STATUS_IS_OK(status)) {
5392 reply_nterror(req, status);
5396 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5402 /****************************************************************************
5403 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5405 ****************************************************************************/
5407 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5408 connection_struct *conn,
5409 struct smb_request *req,
5410 bool overwrite_if_exists,
5411 const struct smb_filename *smb_fname_old,
5412 struct smb_filename *smb_fname_new)
5414 NTSTATUS status = NT_STATUS_OK;
5416 /* source must already exist. */
5417 if (!VALID_STAT(smb_fname_old->st)) {
5418 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5421 if (VALID_STAT(smb_fname_new->st)) {
5422 if (overwrite_if_exists) {
5423 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5424 return NT_STATUS_FILE_IS_A_DIRECTORY;
5426 status = unlink_internals(conn,
5428 FILE_ATTRIBUTE_NORMAL,
5431 if (!NT_STATUS_IS_OK(status)) {
5435 /* Disallow if newname already exists. */
5436 return NT_STATUS_OBJECT_NAME_COLLISION;
5440 /* No links from a directory. */
5441 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5442 return NT_STATUS_FILE_IS_A_DIRECTORY;
5445 /* Setting a hardlink to/from a stream isn't currently supported. */
5446 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5447 is_ntfs_stream_smb_fname(smb_fname_new)) {
5448 return NT_STATUS_INVALID_PARAMETER;
5451 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5452 smb_fname_old->base_name, smb_fname_new->base_name));
5454 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5455 smb_fname_new->base_name) != 0) {
5456 status = map_nt_error_from_unix(errno);
5457 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5458 nt_errstr(status), smb_fname_old->base_name,
5459 smb_fname_new->base_name));
5464 /****************************************************************************
5465 Deal with setting the time from any of the setfilepathinfo functions.
5466 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5467 calling this function.
5468 ****************************************************************************/
5470 NTSTATUS smb_set_file_time(connection_struct *conn,
5472 const struct smb_filename *smb_fname,
5473 struct smb_file_time *ft,
5474 bool setting_write_time)
5476 struct smb_filename smb_fname_base;
5478 FILE_NOTIFY_CHANGE_LAST_ACCESS
5479 |FILE_NOTIFY_CHANGE_LAST_WRITE
5480 |FILE_NOTIFY_CHANGE_CREATION;
5482 if (!VALID_STAT(smb_fname->st)) {
5483 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5486 /* get some defaults (no modifications) if any info is zero or -1. */
5487 if (null_timespec(ft->create_time)) {
5488 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5491 if (null_timespec(ft->atime)) {
5492 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5495 if (null_timespec(ft->mtime)) {
5496 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5499 if (!setting_write_time) {
5500 /* ft->mtime comes from change time, not write time. */
5501 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5504 /* Ensure the resolution is the correct for
5505 * what we can store on this filesystem. */
5507 round_timespec(conn->ts_res, &ft->create_time);
5508 round_timespec(conn->ts_res, &ft->ctime);
5509 round_timespec(conn->ts_res, &ft->atime);
5510 round_timespec(conn->ts_res, &ft->mtime);
5512 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5513 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5514 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5515 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5516 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5517 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5518 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5519 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5521 if (setting_write_time) {
5523 * This was a Windows setfileinfo on an open file.
5524 * NT does this a lot. We also need to
5525 * set the time here, as it can be read by
5526 * FindFirst/FindNext and with the patch for bug #2045
5527 * in smbd/fileio.c it ensures that this timestamp is
5528 * kept sticky even after a write. We save the request
5529 * away and will set it on file close and after a write. JRA.
5532 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5533 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5536 if (fsp->base_fsp) {
5537 set_sticky_write_time_fsp(fsp->base_fsp,
5540 set_sticky_write_time_fsp(fsp, ft->mtime);
5543 set_sticky_write_time_path(
5544 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5549 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5551 /* Always call ntimes on the base, even if a stream was passed in. */
5552 smb_fname_base = *smb_fname;
5553 smb_fname_base.stream_name = NULL;
5555 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5556 return map_nt_error_from_unix(errno);
5559 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5560 smb_fname->base_name);
5561 return NT_STATUS_OK;
5564 /****************************************************************************
5565 Deal with setting the dosmode from any of the setfilepathinfo functions.
5566 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5567 done before calling this function.
5568 ****************************************************************************/
5570 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5571 const struct smb_filename *smb_fname,
5574 struct smb_filename *smb_fname_base = NULL;
5577 if (!VALID_STAT(smb_fname->st)) {
5578 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5581 /* Always operate on the base_name, even if a stream was passed in. */
5582 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5583 NULL, &smb_fname->st,
5585 if (!NT_STATUS_IS_OK(status)) {
5590 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5591 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5593 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5597 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5599 /* check the mode isn't different, before changing it */
5600 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5601 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5602 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5603 (unsigned int)dosmode));
5605 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5607 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5609 smb_fname_str_dbg(smb_fname_base),
5611 status = map_nt_error_from_unix(errno);
5615 status = NT_STATUS_OK;
5617 TALLOC_FREE(smb_fname_base);
5621 /****************************************************************************
5622 Deal with setting the size from any of the setfilepathinfo functions.
5623 ****************************************************************************/
5625 static NTSTATUS smb_set_file_size(connection_struct *conn,
5626 struct smb_request *req,
5628 const struct smb_filename *smb_fname,
5629 const SMB_STRUCT_STAT *psbuf,
5631 bool fail_after_createfile)
5633 NTSTATUS status = NT_STATUS_OK;
5634 struct smb_filename *smb_fname_tmp = NULL;
5635 files_struct *new_fsp = NULL;
5637 if (!VALID_STAT(*psbuf)) {
5638 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5641 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5643 if (size == get_file_size_stat(psbuf)) {
5644 return NT_STATUS_OK;
5647 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5648 smb_fname_str_dbg(smb_fname), (double)size));
5650 if (fsp && fsp->fh->fd != -1) {
5651 /* Handle based call. */
5652 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5653 return NT_STATUS_ACCESS_DENIED;
5656 if (vfs_set_filelen(fsp, size) == -1) {
5657 return map_nt_error_from_unix(errno);
5659 trigger_write_time_update_immediate(fsp);
5660 return NT_STATUS_OK;
5663 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5664 if (!NT_STATUS_IS_OK(status)) {
5668 smb_fname_tmp->st = *psbuf;
5670 status = SMB_VFS_CREATE_FILE(
5673 0, /* root_dir_fid */
5674 smb_fname_tmp, /* fname */
5675 FILE_WRITE_DATA, /* access_mask */
5676 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5678 FILE_OPEN, /* create_disposition*/
5679 0, /* create_options */
5680 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5681 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5682 0, /* allocation_size */
5683 0, /* private_flags */
5686 &new_fsp, /* result */
5689 TALLOC_FREE(smb_fname_tmp);
5691 if (!NT_STATUS_IS_OK(status)) {
5692 /* NB. We check for open_was_deferred in the caller. */
5696 /* See RAW-SFILEINFO-END-OF-FILE */
5697 if (fail_after_createfile) {
5698 close_file(req, new_fsp,NORMAL_CLOSE);
5699 return NT_STATUS_INVALID_LEVEL;
5702 if (vfs_set_filelen(new_fsp, size) == -1) {
5703 status = map_nt_error_from_unix(errno);
5704 close_file(req, new_fsp,NORMAL_CLOSE);
5708 trigger_write_time_update_immediate(new_fsp);
5709 close_file(req, new_fsp,NORMAL_CLOSE);
5710 return NT_STATUS_OK;
5713 /****************************************************************************
5714 Deal with SMB_INFO_SET_EA.
5715 ****************************************************************************/
5717 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5721 const struct smb_filename *smb_fname)
5723 struct ea_list *ea_list = NULL;
5724 TALLOC_CTX *ctx = NULL;
5725 NTSTATUS status = NT_STATUS_OK;
5727 if (total_data < 10) {
5729 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5730 length. They seem to have no effect. Bug #3212. JRA */
5732 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5733 /* We're done. We only get EA info in this call. */
5734 return NT_STATUS_OK;
5737 return NT_STATUS_INVALID_PARAMETER;
5740 if (IVAL(pdata,0) > total_data) {
5741 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5742 IVAL(pdata,0), (unsigned int)total_data));
5743 return NT_STATUS_INVALID_PARAMETER;
5747 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5749 return NT_STATUS_INVALID_PARAMETER;
5752 status = set_ea(conn, fsp, smb_fname, ea_list);
5757 /****************************************************************************
5758 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5759 ****************************************************************************/
5761 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5766 struct ea_list *ea_list = NULL;
5770 return NT_STATUS_INVALID_HANDLE;
5773 if (!lp_ea_support(SNUM(conn))) {
5774 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5775 "EA's not supported.\n",
5776 (unsigned int)total_data));
5777 return NT_STATUS_EAS_NOT_SUPPORTED;
5780 if (total_data < 10) {
5781 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5783 (unsigned int)total_data));
5784 return NT_STATUS_INVALID_PARAMETER;
5787 ea_list = read_nttrans_ea_list(talloc_tos(),
5792 return NT_STATUS_INVALID_PARAMETER;
5795 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5797 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5798 smb_fname_str_dbg(fsp->fsp_name),
5799 nt_errstr(status) ));
5805 /****************************************************************************
5806 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5807 ****************************************************************************/
5809 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5813 struct smb_filename *smb_fname)
5815 NTSTATUS status = NT_STATUS_OK;
5816 bool delete_on_close;
5819 if (total_data < 1) {
5820 return NT_STATUS_INVALID_PARAMETER;
5824 return NT_STATUS_INVALID_HANDLE;
5827 delete_on_close = (CVAL(pdata,0) ? True : False);
5828 dosmode = dos_mode(conn, smb_fname);
5830 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5831 "delete_on_close = %u\n",
5832 smb_fname_str_dbg(smb_fname),
5833 (unsigned int)dosmode,
5834 (unsigned int)delete_on_close ));
5836 if (delete_on_close) {
5837 status = can_set_delete_on_close(fsp, dosmode);
5838 if (!NT_STATUS_IS_OK(status)) {
5843 /* The set is across all open files on this dev/inode pair. */
5844 if (!set_delete_on_close(fsp, delete_on_close,
5845 conn->session_info->unix_token)) {
5846 return NT_STATUS_ACCESS_DENIED;
5848 return NT_STATUS_OK;
5851 /****************************************************************************
5852 Deal with SMB_FILE_POSITION_INFORMATION.
5853 ****************************************************************************/
5855 static NTSTATUS smb_file_position_information(connection_struct *conn,
5860 uint64_t position_information;
5862 if (total_data < 8) {
5863 return NT_STATUS_INVALID_PARAMETER;
5867 /* Ignore on pathname based set. */
5868 return NT_STATUS_OK;
5871 position_information = (uint64_t)IVAL(pdata,0);
5872 #ifdef LARGE_SMB_OFF_T
5873 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5874 #else /* LARGE_SMB_OFF_T */
5875 if (IVAL(pdata,4) != 0) {
5876 /* more than 32 bits? */
5877 return NT_STATUS_INVALID_PARAMETER;
5879 #endif /* LARGE_SMB_OFF_T */
5881 DEBUG(10,("smb_file_position_information: Set file position "
5882 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5883 (double)position_information));
5884 fsp->fh->position_information = position_information;
5885 return NT_STATUS_OK;
5888 /****************************************************************************
5889 Deal with SMB_FILE_MODE_INFORMATION.
5890 ****************************************************************************/
5892 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5898 if (total_data < 4) {
5899 return NT_STATUS_INVALID_PARAMETER;
5901 mode = IVAL(pdata,0);
5902 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5903 return NT_STATUS_INVALID_PARAMETER;
5905 return NT_STATUS_OK;
5908 /****************************************************************************
5909 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5910 ****************************************************************************/
5912 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5913 struct smb_request *req,
5916 const struct smb_filename *smb_fname)
5918 char *link_target = NULL;
5919 const char *newname = smb_fname->base_name;
5920 TALLOC_CTX *ctx = talloc_tos();
5922 /* Set a symbolic link. */
5923 /* Don't allow this if follow links is false. */
5925 if (total_data == 0) {
5926 return NT_STATUS_INVALID_PARAMETER;
5929 if (!lp_symlinks(SNUM(conn))) {
5930 return NT_STATUS_ACCESS_DENIED;
5933 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5934 total_data, STR_TERMINATE);
5937 return NT_STATUS_INVALID_PARAMETER;
5940 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5941 newname, link_target ));
5943 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5944 return map_nt_error_from_unix(errno);
5947 return NT_STATUS_OK;
5950 /****************************************************************************
5951 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5952 ****************************************************************************/
5954 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5955 struct smb_request *req,
5956 const char *pdata, int total_data,
5957 struct smb_filename *smb_fname_new)
5959 char *oldname = NULL;
5960 struct smb_filename *smb_fname_old = NULL;
5961 TALLOC_CTX *ctx = talloc_tos();
5962 NTSTATUS status = NT_STATUS_OK;
5964 /* Set a hard link. */
5965 if (total_data == 0) {
5966 return NT_STATUS_INVALID_PARAMETER;
5969 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5970 total_data, STR_TERMINATE, &status);
5971 if (!NT_STATUS_IS_OK(status)) {
5975 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5976 smb_fname_str_dbg(smb_fname_new), oldname));
5978 status = filename_convert(ctx,
5980 req->flags2 & FLAGS2_DFS_PATHNAMES,
5985 if (!NT_STATUS_IS_OK(status)) {
5989 return hardlink_internals(ctx, conn, req, false,
5990 smb_fname_old, smb_fname_new);
5993 /****************************************************************************
5994 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5995 ****************************************************************************/
5997 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5998 struct smb_request *req,
6002 struct smb_filename *smb_fname_src)
6006 char *newname = NULL;
6007 struct smb_filename *smb_fname_dst = NULL;
6008 NTSTATUS status = NT_STATUS_OK;
6009 TALLOC_CTX *ctx = talloc_tos();
6012 return NT_STATUS_INVALID_HANDLE;
6015 if (total_data < 20) {
6016 return NT_STATUS_INVALID_PARAMETER;
6019 overwrite = (CVAL(pdata,0) ? True : False);
6020 len = IVAL(pdata,16);
6022 if (len > (total_data - 20) || (len == 0)) {
6023 return NT_STATUS_INVALID_PARAMETER;
6026 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6027 &pdata[20], len, STR_TERMINATE,
6029 if (!NT_STATUS_IS_OK(status)) {
6033 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6036 status = filename_convert(ctx,
6038 req->flags2 & FLAGS2_DFS_PATHNAMES,
6043 if (!NT_STATUS_IS_OK(status)) {
6047 if (fsp->base_fsp) {
6048 /* newname must be a stream name. */
6049 if (newname[0] != ':') {
6050 return NT_STATUS_NOT_SUPPORTED;
6053 /* Create an smb_fname to call rename_internals_fsp() with. */
6054 status = create_synthetic_smb_fname(talloc_tos(),
6055 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6057 if (!NT_STATUS_IS_OK(status)) {
6062 * Set the original last component, since
6063 * rename_internals_fsp() requires it.
6065 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6067 if (smb_fname_dst->original_lcomp == NULL) {
6068 status = NT_STATUS_NO_MEMORY;
6074 DEBUG(10,("smb2_file_rename_information: "
6075 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6076 fsp->fnum, fsp_str_dbg(fsp),
6077 smb_fname_str_dbg(smb_fname_dst)));
6078 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6079 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6083 TALLOC_FREE(smb_fname_dst);
6087 static NTSTATUS smb_file_link_information(connection_struct *conn,
6088 struct smb_request *req,
6092 struct smb_filename *smb_fname_src)
6096 char *newname = NULL;
6097 struct smb_filename *smb_fname_dst = NULL;
6098 NTSTATUS status = NT_STATUS_OK;
6099 TALLOC_CTX *ctx = talloc_tos();
6102 return NT_STATUS_INVALID_HANDLE;
6105 if (total_data < 20) {
6106 return NT_STATUS_INVALID_PARAMETER;
6109 overwrite = (CVAL(pdata,0) ? true : false);
6110 len = IVAL(pdata,16);
6112 if (len > (total_data - 20) || (len == 0)) {
6113 return NT_STATUS_INVALID_PARAMETER;
6116 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6117 &pdata[20], len, STR_TERMINATE,
6119 if (!NT_STATUS_IS_OK(status)) {
6123 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6126 status = filename_convert(ctx,
6128 req->flags2 & FLAGS2_DFS_PATHNAMES,
6133 if (!NT_STATUS_IS_OK(status)) {
6137 if (fsp->base_fsp) {
6138 /* No stream names. */
6139 return NT_STATUS_NOT_SUPPORTED;
6142 DEBUG(10,("smb_file_link_information: "
6143 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6144 fsp->fnum, fsp_str_dbg(fsp),
6145 smb_fname_str_dbg(smb_fname_dst)));
6146 status = hardlink_internals(ctx,
6153 TALLOC_FREE(smb_fname_dst);
6157 /****************************************************************************
6158 Deal with SMB_FILE_RENAME_INFORMATION.
6159 ****************************************************************************/
6161 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6162 struct smb_request *req,
6166 struct smb_filename *smb_fname_src)
6171 char *newname = NULL;
6172 struct smb_filename *smb_fname_dst = NULL;
6173 bool dest_has_wcard = False;
6174 NTSTATUS status = NT_STATUS_OK;
6176 TALLOC_CTX *ctx = talloc_tos();
6178 if (total_data < 13) {
6179 return NT_STATUS_INVALID_PARAMETER;
6182 overwrite = (CVAL(pdata,0) ? True : False);
6183 root_fid = IVAL(pdata,4);
6184 len = IVAL(pdata,8);
6186 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6187 return NT_STATUS_INVALID_PARAMETER;
6190 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6193 if (!NT_STATUS_IS_OK(status)) {
6197 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6200 status = resolve_dfspath_wcard(ctx, conn,
6201 req->flags2 & FLAGS2_DFS_PATHNAMES,
6206 if (!NT_STATUS_IS_OK(status)) {
6210 /* Check the new name has no '/' characters. */
6211 if (strchr_m(newname, '/')) {
6212 return NT_STATUS_NOT_SUPPORTED;
6215 if (fsp && fsp->base_fsp) {
6216 /* newname must be a stream name. */
6217 if (newname[0] != ':') {
6218 return NT_STATUS_NOT_SUPPORTED;
6221 /* Create an smb_fname to call rename_internals_fsp() with. */
6222 status = create_synthetic_smb_fname(talloc_tos(),
6223 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6225 if (!NT_STATUS_IS_OK(status)) {
6230 * Set the original last component, since
6231 * rename_internals_fsp() requires it.
6233 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6235 if (smb_fname_dst->original_lcomp == NULL) {
6236 status = NT_STATUS_NO_MEMORY;
6242 * Build up an smb_fname_dst based on the filename passed in.
6243 * We basically just strip off the last component, and put on
6244 * the newname instead.
6246 char *base_name = NULL;
6248 /* newname must *not* be a stream name. */
6249 if (newname[0] == ':') {
6250 return NT_STATUS_NOT_SUPPORTED;
6254 * Strip off the last component (filename) of the path passed
6257 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6259 return NT_STATUS_NO_MEMORY;
6261 p = strrchr_m(base_name, '/');
6265 base_name = talloc_strdup(ctx, "");
6267 return NT_STATUS_NO_MEMORY;
6270 /* Append the new name. */
6271 base_name = talloc_asprintf_append(base_name,
6275 return NT_STATUS_NO_MEMORY;
6278 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6281 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6284 /* If an error we expect this to be
6285 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6287 if (!NT_STATUS_IS_OK(status)) {
6288 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6292 /* Create an smb_fname to call rename_internals_fsp() */
6293 status = create_synthetic_smb_fname(ctx,
6297 if (!NT_STATUS_IS_OK(status)) {
6304 DEBUG(10,("smb_file_rename_information: "
6305 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6306 fsp->fnum, fsp_str_dbg(fsp),
6307 smb_fname_str_dbg(smb_fname_dst)));
6308 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6311 DEBUG(10,("smb_file_rename_information: "
6312 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6313 smb_fname_str_dbg(smb_fname_src),
6314 smb_fname_str_dbg(smb_fname_dst)));
6315 status = rename_internals(ctx, conn, req, smb_fname_src,
6316 smb_fname_dst, 0, overwrite, false,
6318 FILE_WRITE_ATTRIBUTES);
6321 TALLOC_FREE(smb_fname_dst);
6325 /****************************************************************************
6326 Deal with SMB_SET_POSIX_ACL.
6327 ****************************************************************************/
6329 #if defined(HAVE_POSIX_ACLS)
6330 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6334 const struct smb_filename *smb_fname)
6336 uint16 posix_acl_version;
6337 uint16 num_file_acls;
6338 uint16 num_def_acls;
6339 bool valid_file_acls = True;
6340 bool valid_def_acls = True;
6342 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6343 return NT_STATUS_INVALID_PARAMETER;
6345 posix_acl_version = SVAL(pdata,0);
6346 num_file_acls = SVAL(pdata,2);
6347 num_def_acls = SVAL(pdata,4);
6349 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6350 valid_file_acls = False;
6354 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6355 valid_def_acls = False;
6359 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6360 return NT_STATUS_INVALID_PARAMETER;
6363 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6364 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6365 return NT_STATUS_INVALID_PARAMETER;
6368 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6369 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6370 (unsigned int)num_file_acls,
6371 (unsigned int)num_def_acls));
6373 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6374 smb_fname->base_name, num_file_acls,
6375 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6376 return map_nt_error_from_unix(errno);
6379 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6380 smb_fname->base_name, &smb_fname->st, num_def_acls,
6381 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6382 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6383 return map_nt_error_from_unix(errno);
6385 return NT_STATUS_OK;
6389 /****************************************************************************
6390 Deal with SMB_SET_POSIX_LOCK.
6391 ****************************************************************************/
6393 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6394 struct smb_request *req,
6402 bool blocking_lock = False;
6403 enum brl_type lock_type;
6405 NTSTATUS status = NT_STATUS_OK;
6407 if (fsp == NULL || fsp->fh->fd == -1) {
6408 return NT_STATUS_INVALID_HANDLE;
6411 if (total_data != POSIX_LOCK_DATA_SIZE) {
6412 return NT_STATUS_INVALID_PARAMETER;
6415 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6416 case POSIX_LOCK_TYPE_READ:
6417 lock_type = READ_LOCK;
6419 case POSIX_LOCK_TYPE_WRITE:
6420 /* Return the right POSIX-mappable error code for files opened read-only. */
6421 if (!fsp->can_write) {
6422 return NT_STATUS_INVALID_HANDLE;
6424 lock_type = WRITE_LOCK;
6426 case POSIX_LOCK_TYPE_UNLOCK:
6427 lock_type = UNLOCK_LOCK;
6430 return NT_STATUS_INVALID_PARAMETER;
6433 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6434 blocking_lock = False;
6435 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6436 blocking_lock = True;
6438 return NT_STATUS_INVALID_PARAMETER;
6441 if (!lp_blocking_locks(SNUM(conn))) {
6442 blocking_lock = False;
6445 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6446 #if defined(HAVE_LONGLONG)
6447 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6448 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6449 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6450 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6451 #else /* HAVE_LONGLONG */
6452 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6453 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6454 #endif /* HAVE_LONGLONG */
6456 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6457 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6459 (unsigned int)lock_type,
6460 (unsigned long long)smblctx,
6464 if (lock_type == UNLOCK_LOCK) {
6465 status = do_unlock(req->sconn->msg_ctx,
6472 uint64_t block_smblctx;
6474 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6486 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6488 * A blocking lock was requested. Package up
6489 * this smb into a queued request and push it
6490 * onto the blocking lock queue.
6492 if(push_blocking_lock_request(br_lck,
6495 -1, /* infinite timeout. */
6503 TALLOC_FREE(br_lck);
6507 TALLOC_FREE(br_lck);
6513 /****************************************************************************
6514 Deal with SMB_SET_FILE_BASIC_INFO.
6515 ****************************************************************************/
6517 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6521 const struct smb_filename *smb_fname)
6523 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6524 struct smb_file_time ft;
6526 NTSTATUS status = NT_STATUS_OK;
6530 if (total_data < 36) {
6531 return NT_STATUS_INVALID_PARAMETER;
6534 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6535 if (!NT_STATUS_IS_OK(status)) {
6539 /* Set the attributes */
6540 dosmode = IVAL(pdata,32);
6541 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6542 if (!NT_STATUS_IS_OK(status)) {
6547 ft.create_time = interpret_long_date(pdata);
6550 ft.atime = interpret_long_date(pdata+8);
6553 ft.mtime = interpret_long_date(pdata+16);
6556 ft.ctime = interpret_long_date(pdata+24);
6558 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6559 smb_fname_str_dbg(smb_fname)));
6561 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6565 /****************************************************************************
6566 Deal with SMB_INFO_STANDARD.
6567 ****************************************************************************/
6569 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6573 const struct smb_filename *smb_fname)
6576 struct smb_file_time ft;
6580 if (total_data < 12) {
6581 return NT_STATUS_INVALID_PARAMETER;
6585 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6587 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6589 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6591 DEBUG(10,("smb_set_info_standard: file %s\n",
6592 smb_fname_str_dbg(smb_fname)));
6594 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6595 if (!NT_STATUS_IS_OK(status)) {
6599 return smb_set_file_time(conn,
6606 /****************************************************************************
6607 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6608 ****************************************************************************/
6610 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6611 struct smb_request *req,
6615 struct smb_filename *smb_fname)
6617 uint64_t allocation_size = 0;
6618 NTSTATUS status = NT_STATUS_OK;
6619 files_struct *new_fsp = NULL;
6621 if (!VALID_STAT(smb_fname->st)) {
6622 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6625 if (total_data < 8) {
6626 return NT_STATUS_INVALID_PARAMETER;
6629 allocation_size = (uint64_t)IVAL(pdata,0);
6630 #ifdef LARGE_SMB_OFF_T
6631 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6632 #else /* LARGE_SMB_OFF_T */
6633 if (IVAL(pdata,4) != 0) {
6634 /* more than 32 bits? */
6635 return NT_STATUS_INVALID_PARAMETER;
6637 #endif /* LARGE_SMB_OFF_T */
6639 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6640 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6641 (double)allocation_size));
6643 if (allocation_size) {
6644 allocation_size = smb_roundup(conn, allocation_size);
6647 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6648 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6649 (double)allocation_size));
6651 if (fsp && fsp->fh->fd != -1) {
6652 /* Open file handle. */
6653 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6654 return NT_STATUS_ACCESS_DENIED;
6657 /* Only change if needed. */
6658 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6659 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6660 return map_nt_error_from_unix(errno);
6663 /* But always update the time. */
6665 * This is equivalent to a write. Ensure it's seen immediately
6666 * if there are no pending writes.
6668 trigger_write_time_update_immediate(fsp);
6669 return NT_STATUS_OK;
6672 /* Pathname or stat or directory file. */
6673 status = SMB_VFS_CREATE_FILE(
6676 0, /* root_dir_fid */
6677 smb_fname, /* fname */
6678 FILE_WRITE_DATA, /* access_mask */
6679 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6681 FILE_OPEN, /* create_disposition*/
6682 0, /* create_options */
6683 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6684 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6685 0, /* allocation_size */
6686 0, /* private_flags */
6689 &new_fsp, /* result */
6692 if (!NT_STATUS_IS_OK(status)) {
6693 /* NB. We check for open_was_deferred in the caller. */
6697 /* Only change if needed. */
6698 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6699 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6700 status = map_nt_error_from_unix(errno);
6701 close_file(req, new_fsp, NORMAL_CLOSE);
6706 /* Changing the allocation size should set the last mod time. */
6708 * This is equivalent to a write. Ensure it's seen immediately
6709 * if there are no pending writes.
6711 trigger_write_time_update_immediate(new_fsp);
6713 close_file(req, new_fsp, NORMAL_CLOSE);
6714 return NT_STATUS_OK;
6717 /****************************************************************************
6718 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6719 ****************************************************************************/
6721 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6722 struct smb_request *req,
6726 const struct smb_filename *smb_fname,
6727 bool fail_after_createfile)
6731 if (total_data < 8) {
6732 return NT_STATUS_INVALID_PARAMETER;
6735 size = IVAL(pdata,0);
6736 #ifdef LARGE_SMB_OFF_T
6737 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6738 #else /* LARGE_SMB_OFF_T */
6739 if (IVAL(pdata,4) != 0) {
6740 /* more than 32 bits? */
6741 return NT_STATUS_INVALID_PARAMETER;
6743 #endif /* LARGE_SMB_OFF_T */
6744 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6745 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6748 return smb_set_file_size(conn, req,
6753 fail_after_createfile);
6756 /****************************************************************************
6757 Allow a UNIX info mknod.
6758 ****************************************************************************/
6760 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6763 const struct smb_filename *smb_fname)
6765 uint32 file_type = IVAL(pdata,56);
6766 #if defined(HAVE_MAKEDEV)
6767 uint32 dev_major = IVAL(pdata,60);
6768 uint32 dev_minor = IVAL(pdata,68);
6770 SMB_DEV_T dev = (SMB_DEV_T)0;
6771 uint32 raw_unixmode = IVAL(pdata,84);
6775 if (total_data < 100) {
6776 return NT_STATUS_INVALID_PARAMETER;
6779 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6780 PERM_NEW_FILE, &unixmode);
6781 if (!NT_STATUS_IS_OK(status)) {
6785 #if defined(HAVE_MAKEDEV)
6786 dev = makedev(dev_major, dev_minor);
6789 switch (file_type) {
6790 #if defined(S_IFIFO)
6791 case UNIX_TYPE_FIFO:
6792 unixmode |= S_IFIFO;
6795 #if defined(S_IFSOCK)
6796 case UNIX_TYPE_SOCKET:
6797 unixmode |= S_IFSOCK;
6800 #if defined(S_IFCHR)
6801 case UNIX_TYPE_CHARDEV:
6802 unixmode |= S_IFCHR;
6805 #if defined(S_IFBLK)
6806 case UNIX_TYPE_BLKDEV:
6807 unixmode |= S_IFBLK;
6811 return NT_STATUS_INVALID_PARAMETER;
6814 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6815 "%.0f mode 0%o for file %s\n", (double)dev,
6816 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6818 /* Ok - do the mknod. */
6819 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6820 return map_nt_error_from_unix(errno);
6823 /* If any of the other "set" calls fail we
6824 * don't want to end up with a half-constructed mknod.
6827 if (lp_inherit_perms(SNUM(conn))) {
6829 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6831 return NT_STATUS_NO_MEMORY;
6833 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6835 TALLOC_FREE(parent);
6838 return NT_STATUS_OK;
6841 /****************************************************************************
6842 Deal with SMB_SET_FILE_UNIX_BASIC.
6843 ****************************************************************************/
6845 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6846 struct smb_request *req,
6850 const struct smb_filename *smb_fname)
6852 struct smb_file_time ft;
6853 uint32 raw_unixmode;
6856 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6857 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6858 NTSTATUS status = NT_STATUS_OK;
6859 bool delete_on_fail = False;
6860 enum perm_type ptype;
6861 files_struct *all_fsps = NULL;
6862 bool modify_mtime = true;
6864 struct smb_filename *smb_fname_tmp = NULL;
6865 SMB_STRUCT_STAT sbuf;
6869 if (total_data < 100) {
6870 return NT_STATUS_INVALID_PARAMETER;
6873 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6874 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6875 size=IVAL(pdata,0); /* first 8 Bytes are size */
6876 #ifdef LARGE_SMB_OFF_T
6877 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6878 #else /* LARGE_SMB_OFF_T */
6879 if (IVAL(pdata,4) != 0) {
6880 /* more than 32 bits? */
6881 return NT_STATUS_INVALID_PARAMETER;
6883 #endif /* LARGE_SMB_OFF_T */
6886 ft.atime = interpret_long_date(pdata+24); /* access_time */
6887 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6888 set_owner = (uid_t)IVAL(pdata,40);
6889 set_grp = (gid_t)IVAL(pdata,48);
6890 raw_unixmode = IVAL(pdata,84);
6892 if (VALID_STAT(smb_fname->st)) {
6893 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6894 ptype = PERM_EXISTING_DIR;
6896 ptype = PERM_EXISTING_FILE;
6899 ptype = PERM_NEW_FILE;
6902 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6904 if (!NT_STATUS_IS_OK(status)) {
6908 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6909 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6910 smb_fname_str_dbg(smb_fname), (double)size,
6911 (unsigned int)set_owner, (unsigned int)set_grp,
6912 (int)raw_unixmode));
6914 sbuf = smb_fname->st;
6916 if (!VALID_STAT(sbuf)) {
6918 * The only valid use of this is to create character and block
6919 * devices, and named pipes. This is deprecated (IMHO) and
6920 * a new info level should be used for mknod. JRA.
6923 status = smb_unix_mknod(conn,
6927 if (!NT_STATUS_IS_OK(status)) {
6931 status = copy_smb_filename(talloc_tos(), smb_fname,
6933 if (!NT_STATUS_IS_OK(status)) {
6937 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6938 status = map_nt_error_from_unix(errno);
6939 TALLOC_FREE(smb_fname_tmp);
6940 SMB_VFS_UNLINK(conn, smb_fname);
6944 sbuf = smb_fname_tmp->st;
6945 smb_fname = smb_fname_tmp;
6947 /* Ensure we don't try and change anything else. */
6948 raw_unixmode = SMB_MODE_NO_CHANGE;
6949 size = get_file_size_stat(&sbuf);
6950 ft.atime = sbuf.st_ex_atime;
6951 ft.mtime = sbuf.st_ex_mtime;
6953 * We continue here as we might want to change the
6956 delete_on_fail = True;
6960 /* Horrible backwards compatibility hack as an old server bug
6961 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6965 size = get_file_size_stat(&sbuf);
6970 * Deal with the UNIX specific mode set.
6973 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6974 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6975 "setting mode 0%o for file %s\n",
6976 (unsigned int)unixmode,
6977 smb_fname_str_dbg(smb_fname)));
6978 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6979 return map_nt_error_from_unix(errno);
6984 * Deal with the UNIX specific uid set.
6987 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6988 (sbuf.st_ex_uid != set_owner)) {
6991 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6992 "changing owner %u for path %s\n",
6993 (unsigned int)set_owner,
6994 smb_fname_str_dbg(smb_fname)));
6996 if (S_ISLNK(sbuf.st_ex_mode)) {
6997 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6998 set_owner, (gid_t)-1);
7000 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7001 set_owner, (gid_t)-1);
7005 status = map_nt_error_from_unix(errno);
7006 if (delete_on_fail) {
7007 SMB_VFS_UNLINK(conn, smb_fname);
7014 * Deal with the UNIX specific gid set.
7017 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7018 (sbuf.st_ex_gid != set_grp)) {
7019 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7020 "changing group %u for file %s\n",
7021 (unsigned int)set_owner,
7022 smb_fname_str_dbg(smb_fname)));
7023 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7025 status = map_nt_error_from_unix(errno);
7026 if (delete_on_fail) {
7027 SMB_VFS_UNLINK(conn, smb_fname);
7033 /* Deal with any size changes. */
7035 status = smb_set_file_size(conn, req,
7041 if (!NT_STATUS_IS_OK(status)) {
7045 /* Deal with any time changes. */
7046 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7047 /* No change, don't cancel anything. */
7051 id = vfs_file_id_from_sbuf(conn, &sbuf);
7052 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7053 all_fsps = file_find_di_next(all_fsps)) {
7055 * We're setting the time explicitly for UNIX.
7056 * Cancel any pending changes over all handles.
7058 all_fsps->update_write_time_on_close = false;
7059 TALLOC_FREE(all_fsps->update_write_time_event);
7063 * Override the "setting_write_time"
7064 * parameter here as it almost does what
7065 * we need. Just remember if we modified
7066 * mtime and send the notify ourselves.
7068 if (null_timespec(ft.mtime)) {
7069 modify_mtime = false;
7072 status = smb_set_file_time(conn,
7078 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7079 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7084 /****************************************************************************
7085 Deal with SMB_SET_FILE_UNIX_INFO2.
7086 ****************************************************************************/
7088 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7089 struct smb_request *req,
7093 const struct smb_filename *smb_fname)
7099 if (total_data < 116) {
7100 return NT_STATUS_INVALID_PARAMETER;
7103 /* Start by setting all the fields that are common between UNIX_BASIC
7106 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7108 if (!NT_STATUS_IS_OK(status)) {
7112 smb_fflags = IVAL(pdata, 108);
7113 smb_fmask = IVAL(pdata, 112);
7115 /* NB: We should only attempt to alter the file flags if the client
7116 * sends a non-zero mask.
7118 if (smb_fmask != 0) {
7119 int stat_fflags = 0;
7121 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7122 smb_fmask, &stat_fflags)) {
7123 /* Client asked to alter a flag we don't understand. */
7124 return NT_STATUS_INVALID_PARAMETER;
7127 if (fsp && fsp->fh->fd != -1) {
7128 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7129 return NT_STATUS_NOT_SUPPORTED;
7131 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7132 stat_fflags) != 0) {
7133 return map_nt_error_from_unix(errno);
7138 /* XXX: need to add support for changing the create_time here. You
7139 * can do this for paths on Darwin with setattrlist(2). The right way
7140 * to hook this up is probably by extending the VFS utimes interface.
7143 return NT_STATUS_OK;
7146 /****************************************************************************
7147 Create a directory with POSIX semantics.
7148 ****************************************************************************/
7150 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7151 struct smb_request *req,
7154 struct smb_filename *smb_fname,
7155 int *pdata_return_size)
7157 NTSTATUS status = NT_STATUS_OK;
7158 uint32 raw_unixmode = 0;
7159 uint32 mod_unixmode = 0;
7160 mode_t unixmode = (mode_t)0;
7161 files_struct *fsp = NULL;
7162 uint16 info_level_return = 0;
7164 char *pdata = *ppdata;
7166 if (total_data < 18) {
7167 return NT_STATUS_INVALID_PARAMETER;
7170 raw_unixmode = IVAL(pdata,8);
7171 /* Next 4 bytes are not yet defined. */
7173 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7174 PERM_NEW_DIR, &unixmode);
7175 if (!NT_STATUS_IS_OK(status)) {
7179 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7181 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7182 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7184 status = SMB_VFS_CREATE_FILE(
7187 0, /* root_dir_fid */
7188 smb_fname, /* fname */
7189 FILE_READ_ATTRIBUTES, /* access_mask */
7190 FILE_SHARE_NONE, /* share_access */
7191 FILE_CREATE, /* create_disposition*/
7192 FILE_DIRECTORY_FILE, /* create_options */
7193 mod_unixmode, /* file_attributes */
7194 0, /* oplock_request */
7195 0, /* allocation_size */
7196 0, /* private_flags */
7202 if (NT_STATUS_IS_OK(status)) {
7203 close_file(req, fsp, NORMAL_CLOSE);
7206 info_level_return = SVAL(pdata,16);
7208 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7209 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7210 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7211 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7213 *pdata_return_size = 12;
7216 /* Realloc the data size */
7217 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7218 if (*ppdata == NULL) {
7219 *pdata_return_size = 0;
7220 return NT_STATUS_NO_MEMORY;
7224 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7225 SSVAL(pdata,2,0); /* No fnum. */
7226 SIVAL(pdata,4,info); /* Was directory created. */
7228 switch (info_level_return) {
7229 case SMB_QUERY_FILE_UNIX_BASIC:
7230 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7231 SSVAL(pdata,10,0); /* Padding. */
7232 store_file_unix_basic(conn, pdata + 12, fsp,
7235 case SMB_QUERY_FILE_UNIX_INFO2:
7236 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7237 SSVAL(pdata,10,0); /* Padding. */
7238 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7242 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7243 SSVAL(pdata,10,0); /* Padding. */
7250 /****************************************************************************
7251 Open/Create a file with POSIX semantics.
7252 ****************************************************************************/
7254 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7255 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7257 static NTSTATUS smb_posix_open(connection_struct *conn,
7258 struct smb_request *req,
7261 struct smb_filename *smb_fname,
7262 int *pdata_return_size)
7264 bool extended_oplock_granted = False;
7265 char *pdata = *ppdata;
7267 uint32 wire_open_mode = 0;
7268 uint32 raw_unixmode = 0;
7269 uint32 mod_unixmode = 0;
7270 uint32 create_disp = 0;
7271 uint32 access_mask = 0;
7272 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7273 NTSTATUS status = NT_STATUS_OK;
7274 mode_t unixmode = (mode_t)0;
7275 files_struct *fsp = NULL;
7276 int oplock_request = 0;
7278 uint16 info_level_return = 0;
7280 if (total_data < 18) {
7281 return NT_STATUS_INVALID_PARAMETER;
7284 flags = IVAL(pdata,0);
7285 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7286 if (oplock_request) {
7287 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7290 wire_open_mode = IVAL(pdata,4);
7292 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7293 return smb_posix_mkdir(conn, req,
7300 switch (wire_open_mode & SMB_ACCMODE) {
7302 access_mask = SMB_O_RDONLY_MAPPING;
7305 access_mask = SMB_O_WRONLY_MAPPING;
7308 access_mask = (SMB_O_RDONLY_MAPPING|
7309 SMB_O_WRONLY_MAPPING);
7312 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7313 (unsigned int)wire_open_mode ));
7314 return NT_STATUS_INVALID_PARAMETER;
7317 wire_open_mode &= ~SMB_ACCMODE;
7319 /* First take care of O_CREAT|O_EXCL interactions. */
7320 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7321 case (SMB_O_CREAT | SMB_O_EXCL):
7322 /* File exists fail. File not exist create. */
7323 create_disp = FILE_CREATE;
7326 /* File exists open. File not exist create. */
7327 create_disp = FILE_OPEN_IF;
7330 /* File exists open. File not exist fail. */
7331 create_disp = FILE_OPEN;
7334 /* O_EXCL on its own without O_CREAT is undefined. */
7336 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7337 (unsigned int)wire_open_mode ));
7338 return NT_STATUS_INVALID_PARAMETER;
7341 /* Next factor in the effects of O_TRUNC. */
7342 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7344 if (wire_open_mode & SMB_O_TRUNC) {
7345 switch (create_disp) {
7347 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7348 /* Leave create_disp alone as
7349 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7351 /* File exists fail. File not exist create. */
7354 /* SMB_O_CREAT | SMB_O_TRUNC */
7355 /* File exists overwrite. File not exist create. */
7356 create_disp = FILE_OVERWRITE_IF;
7360 /* File exists overwrite. File not exist fail. */
7361 create_disp = FILE_OVERWRITE;
7364 /* Cannot get here. */
7365 smb_panic("smb_posix_open: logic error");
7366 return NT_STATUS_INVALID_PARAMETER;
7370 raw_unixmode = IVAL(pdata,8);
7371 /* Next 4 bytes are not yet defined. */
7373 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7374 (VALID_STAT(smb_fname->st) ?
7375 PERM_EXISTING_FILE : PERM_NEW_FILE),
7378 if (!NT_STATUS_IS_OK(status)) {
7382 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7384 if (wire_open_mode & SMB_O_SYNC) {
7385 create_options |= FILE_WRITE_THROUGH;
7387 if (wire_open_mode & SMB_O_APPEND) {
7388 access_mask |= FILE_APPEND_DATA;
7390 if (wire_open_mode & SMB_O_DIRECT) {
7391 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7394 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7395 VALID_STAT_OF_DIR(smb_fname->st)) {
7396 if (access_mask != SMB_O_RDONLY_MAPPING) {
7397 return NT_STATUS_FILE_IS_A_DIRECTORY;
7399 create_options &= ~FILE_NON_DIRECTORY_FILE;
7400 create_options |= FILE_DIRECTORY_FILE;
7403 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7404 smb_fname_str_dbg(smb_fname),
7405 (unsigned int)wire_open_mode,
7406 (unsigned int)unixmode ));
7408 status = SMB_VFS_CREATE_FILE(
7411 0, /* root_dir_fid */
7412 smb_fname, /* fname */
7413 access_mask, /* access_mask */
7414 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7416 create_disp, /* create_disposition*/
7417 create_options, /* create_options */
7418 mod_unixmode, /* file_attributes */
7419 oplock_request, /* oplock_request */
7420 0, /* allocation_size */
7421 0, /* private_flags */
7427 if (!NT_STATUS_IS_OK(status)) {
7431 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7432 extended_oplock_granted = True;
7435 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7436 extended_oplock_granted = True;
7439 info_level_return = SVAL(pdata,16);
7441 /* Allocate the correct return size. */
7443 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7444 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7445 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7446 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7448 *pdata_return_size = 12;
7451 /* Realloc the data size */
7452 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7453 if (*ppdata == NULL) {
7454 close_file(req, fsp, ERROR_CLOSE);
7455 *pdata_return_size = 0;
7456 return NT_STATUS_NO_MEMORY;
7460 if (extended_oplock_granted) {
7461 if (flags & REQUEST_BATCH_OPLOCK) {
7462 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7464 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7466 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7467 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7469 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7472 SSVAL(pdata,2,fsp->fnum);
7473 SIVAL(pdata,4,info); /* Was file created etc. */
7475 switch (info_level_return) {
7476 case SMB_QUERY_FILE_UNIX_BASIC:
7477 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7478 SSVAL(pdata,10,0); /* padding. */
7479 store_file_unix_basic(conn, pdata + 12, fsp,
7482 case SMB_QUERY_FILE_UNIX_INFO2:
7483 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7484 SSVAL(pdata,10,0); /* padding. */
7485 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7489 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7490 SSVAL(pdata,10,0); /* padding. */
7493 return NT_STATUS_OK;
7496 /****************************************************************************
7497 Delete a file with POSIX semantics.
7498 ****************************************************************************/
7500 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7501 struct smb_request *req,
7504 struct smb_filename *smb_fname)
7506 NTSTATUS status = NT_STATUS_OK;
7507 files_struct *fsp = NULL;
7511 int create_options = 0;
7513 struct share_mode_lock *lck = NULL;
7515 if (total_data < 2) {
7516 return NT_STATUS_INVALID_PARAMETER;
7519 flags = SVAL(pdata,0);
7521 if (!VALID_STAT(smb_fname->st)) {
7522 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7525 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7526 !VALID_STAT_OF_DIR(smb_fname->st)) {
7527 return NT_STATUS_NOT_A_DIRECTORY;
7530 DEBUG(10,("smb_posix_unlink: %s %s\n",
7531 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7532 smb_fname_str_dbg(smb_fname)));
7534 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7535 create_options |= FILE_DIRECTORY_FILE;
7538 status = SMB_VFS_CREATE_FILE(
7541 0, /* root_dir_fid */
7542 smb_fname, /* fname */
7543 DELETE_ACCESS, /* access_mask */
7544 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7546 FILE_OPEN, /* create_disposition*/
7547 create_options, /* create_options */
7548 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7549 0, /* oplock_request */
7550 0, /* allocation_size */
7551 0, /* private_flags */
7557 if (!NT_STATUS_IS_OK(status)) {
7562 * Don't lie to client. If we can't really delete due to
7563 * non-POSIX opens return SHARING_VIOLATION.
7566 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7568 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7569 "lock for file %s\n", fsp_str_dbg(fsp)));
7570 close_file(req, fsp, NORMAL_CLOSE);
7571 return NT_STATUS_INVALID_PARAMETER;
7575 * See if others still have the file open. If this is the case, then
7576 * don't delete. If all opens are POSIX delete we can set the delete
7577 * on close disposition.
7579 for (i=0; i<lck->data->num_share_modes; i++) {
7580 struct share_mode_entry *e = &lck->data->share_modes[i];
7581 if (is_valid_share_mode_entry(e)) {
7582 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7585 /* Fail with sharing violation. */
7586 close_file(req, fsp, NORMAL_CLOSE);
7588 return NT_STATUS_SHARING_VIOLATION;
7593 * Set the delete on close.
7595 status = smb_set_file_disposition_info(conn,
7601 if (!NT_STATUS_IS_OK(status)) {
7602 close_file(req, fsp, NORMAL_CLOSE);
7607 return close_file(req, fsp, NORMAL_CLOSE);
7610 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7611 struct smb_request *req,
7612 TALLOC_CTX *mem_ctx,
7613 uint16_t info_level,
7615 struct smb_filename *smb_fname,
7616 char **ppdata, int total_data,
7619 char *pdata = *ppdata;
7620 NTSTATUS status = NT_STATUS_OK;
7621 int data_return_size = 0;
7625 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7626 return NT_STATUS_INVALID_LEVEL;
7629 if (!CAN_WRITE(conn)) {
7630 /* Allow POSIX opens. The open path will deny
7631 * any non-readonly opens. */
7632 if (info_level != SMB_POSIX_PATH_OPEN) {
7633 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7637 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7638 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7639 fsp ? fsp->fnum : -1, info_level, total_data));
7641 switch (info_level) {
7643 case SMB_INFO_STANDARD:
7645 status = smb_set_info_standard(conn,
7653 case SMB_INFO_SET_EA:
7655 status = smb_info_set_ea(conn,
7663 case SMB_SET_FILE_BASIC_INFO:
7664 case SMB_FILE_BASIC_INFORMATION:
7666 status = smb_set_file_basic_info(conn,
7674 case SMB_FILE_ALLOCATION_INFORMATION:
7675 case SMB_SET_FILE_ALLOCATION_INFO:
7677 status = smb_set_file_allocation_info(conn, req,
7685 case SMB_FILE_END_OF_FILE_INFORMATION:
7686 case SMB_SET_FILE_END_OF_FILE_INFO:
7689 * XP/Win7 both fail after the createfile with
7690 * SMB_SET_FILE_END_OF_FILE_INFO but not
7691 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7692 * The level is known here, so pass it down
7696 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7698 status = smb_set_file_end_of_file_info(conn, req,
7707 case SMB_FILE_DISPOSITION_INFORMATION:
7708 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7711 /* JRA - We used to just ignore this on a path ?
7712 * Shouldn't this be invalid level on a pathname
7715 if (tran_call != TRANSACT2_SETFILEINFO) {
7716 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7719 status = smb_set_file_disposition_info(conn,
7727 case SMB_FILE_POSITION_INFORMATION:
7729 status = smb_file_position_information(conn,
7736 case SMB_FILE_FULL_EA_INFORMATION:
7738 status = smb_set_file_full_ea_info(conn,
7745 /* From tridge Samba4 :
7746 * MODE_INFORMATION in setfileinfo (I have no
7747 * idea what "mode information" on a file is - it takes a value of 0,
7748 * 2, 4 or 6. What could it be?).
7751 case SMB_FILE_MODE_INFORMATION:
7753 status = smb_file_mode_information(conn,
7760 * CIFS UNIX extensions.
7763 case SMB_SET_FILE_UNIX_BASIC:
7765 status = smb_set_file_unix_basic(conn, req,
7773 case SMB_SET_FILE_UNIX_INFO2:
7775 status = smb_set_file_unix_info2(conn, req,
7783 case SMB_SET_FILE_UNIX_LINK:
7786 /* We must have a pathname for this. */
7787 return NT_STATUS_INVALID_LEVEL;
7789 status = smb_set_file_unix_link(conn, req, pdata,
7790 total_data, smb_fname);
7794 case SMB_SET_FILE_UNIX_HLINK:
7797 /* We must have a pathname for this. */
7798 return NT_STATUS_INVALID_LEVEL;
7800 status = smb_set_file_unix_hlink(conn, req,
7806 case SMB_FILE_RENAME_INFORMATION:
7808 status = smb_file_rename_information(conn, req,
7814 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7816 /* SMB2 rename information. */
7817 status = smb2_file_rename_information(conn, req,
7823 case SMB_FILE_LINK_INFORMATION:
7825 status = smb_file_link_information(conn, req,
7831 #if defined(HAVE_POSIX_ACLS)
7832 case SMB_SET_POSIX_ACL:
7834 status = smb_set_posix_acl(conn,
7843 case SMB_SET_POSIX_LOCK:
7846 return NT_STATUS_INVALID_LEVEL;
7848 status = smb_set_posix_lock(conn, req,
7849 pdata, total_data, fsp);
7853 case SMB_POSIX_PATH_OPEN:
7856 /* We must have a pathname for this. */
7857 return NT_STATUS_INVALID_LEVEL;
7860 status = smb_posix_open(conn, req,
7868 case SMB_POSIX_PATH_UNLINK:
7871 /* We must have a pathname for this. */
7872 return NT_STATUS_INVALID_LEVEL;
7875 status = smb_posix_unlink(conn, req,
7883 return NT_STATUS_INVALID_LEVEL;
7886 if (!NT_STATUS_IS_OK(status)) {
7890 *ret_data_size = data_return_size;
7891 return NT_STATUS_OK;
7894 /****************************************************************************
7895 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7896 ****************************************************************************/
7898 static void call_trans2setfilepathinfo(connection_struct *conn,
7899 struct smb_request *req,
7900 unsigned int tran_call,
7901 char **pparams, int total_params,
7902 char **ppdata, int total_data,
7903 unsigned int max_data_bytes)
7905 char *params = *pparams;
7906 char *pdata = *ppdata;
7908 struct smb_filename *smb_fname = NULL;
7909 files_struct *fsp = NULL;
7910 NTSTATUS status = NT_STATUS_OK;
7911 int data_return_size = 0;
7914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7918 if (tran_call == TRANSACT2_SETFILEINFO) {
7919 if (total_params < 4) {
7920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7924 fsp = file_fsp(req, SVAL(params,0));
7925 /* Basic check for non-null fsp. */
7926 if (!check_fsp_open(conn, req, fsp)) {
7929 info_level = SVAL(params,2);
7931 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7933 if (!NT_STATUS_IS_OK(status)) {
7934 reply_nterror(req, status);
7938 if(fsp->fh->fd == -1) {
7940 * This is actually a SETFILEINFO on a directory
7941 * handle (returned from an NT SMB). NT5.0 seems
7942 * to do this call. JRA.
7944 if (INFO_LEVEL_IS_UNIX(info_level)) {
7945 /* Always do lstat for UNIX calls. */
7946 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7947 DEBUG(3,("call_trans2setfilepathinfo: "
7948 "SMB_VFS_LSTAT of %s failed "
7950 smb_fname_str_dbg(smb_fname),
7952 reply_nterror(req, map_nt_error_from_unix(errno));
7956 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7957 DEBUG(3,("call_trans2setfilepathinfo: "
7958 "fileinfo of %s failed (%s)\n",
7959 smb_fname_str_dbg(smb_fname),
7961 reply_nterror(req, map_nt_error_from_unix(errno));
7965 } else if (fsp->print_file) {
7967 * Doing a DELETE_ON_CLOSE should cancel a print job.
7969 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7970 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7972 DEBUG(3,("call_trans2setfilepathinfo: "
7973 "Cancelling print job (%s)\n",
7977 send_trans2_replies(conn, req, params, 2,
7983 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7988 * Original code - this is an open file.
7990 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7991 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7992 "of fnum %d failed (%s)\n", fsp->fnum,
7994 reply_nterror(req, map_nt_error_from_unix(errno));
8000 uint32_t ucf_flags = 0;
8003 if (total_params < 7) {
8004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8008 info_level = SVAL(params,0);
8009 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8010 total_params - 6, STR_TERMINATE,
8012 if (!NT_STATUS_IS_OK(status)) {
8013 reply_nterror(req, status);
8017 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8018 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8019 info_level == SMB_FILE_RENAME_INFORMATION ||
8020 info_level == SMB_POSIX_PATH_UNLINK) {
8021 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8024 status = filename_convert(req, conn,
8025 req->flags2 & FLAGS2_DFS_PATHNAMES,
8030 if (!NT_STATUS_IS_OK(status)) {
8031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8032 reply_botherror(req,
8033 NT_STATUS_PATH_NOT_COVERED,
8034 ERRSRV, ERRbadpath);
8037 reply_nterror(req, status);
8041 if (INFO_LEVEL_IS_UNIX(info_level)) {
8043 * For CIFS UNIX extensions the target name may not exist.
8046 /* Always do lstat for UNIX calls. */
8047 SMB_VFS_LSTAT(conn, smb_fname);
8049 } else if (!VALID_STAT(smb_fname->st) &&
8050 SMB_VFS_STAT(conn, smb_fname)) {
8051 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8053 smb_fname_str_dbg(smb_fname),
8055 reply_nterror(req, map_nt_error_from_unix(errno));
8060 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8061 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8062 fsp ? fsp->fnum : -1, info_level,total_data));
8064 /* Realloc the parameter size */
8065 *pparams = (char *)SMB_REALLOC(*pparams,2);
8066 if (*pparams == NULL) {
8067 reply_nterror(req, NT_STATUS_NO_MEMORY);
8074 status = smbd_do_setfilepathinfo(conn, req, req,
8080 if (!NT_STATUS_IS_OK(status)) {
8081 if (open_was_deferred(req->sconn, req->mid)) {
8082 /* We have re-scheduled this call. */
8085 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8086 /* We have re-scheduled this call. */
8089 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8090 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8091 ERRSRV, ERRbadpath);
8094 if (info_level == SMB_POSIX_PATH_OPEN) {
8095 reply_openerror(req, status);
8099 reply_nterror(req, status);
8103 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8109 /****************************************************************************
8110 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8111 ****************************************************************************/
8113 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8114 char **pparams, int total_params,
8115 char **ppdata, int total_data,
8116 unsigned int max_data_bytes)
8118 struct smb_filename *smb_dname = NULL;
8119 char *params = *pparams;
8120 char *pdata = *ppdata;
8121 char *directory = NULL;
8122 NTSTATUS status = NT_STATUS_OK;
8123 struct ea_list *ea_list = NULL;
8124 TALLOC_CTX *ctx = talloc_tos();
8126 if (!CAN_WRITE(conn)) {
8127 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8131 if (total_params < 5) {
8132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8136 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8137 total_params - 4, STR_TERMINATE,
8139 if (!NT_STATUS_IS_OK(status)) {
8140 reply_nterror(req, status);
8144 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8146 status = filename_convert(ctx,
8148 req->flags2 & FLAGS2_DFS_PATHNAMES,
8154 if (!NT_STATUS_IS_OK(status)) {
8155 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8156 reply_botherror(req,
8157 NT_STATUS_PATH_NOT_COVERED,
8158 ERRSRV, ERRbadpath);
8161 reply_nterror(req, status);
8166 * OS/2 workplace shell seems to send SET_EA requests of "null"
8167 * length (4 bytes containing IVAL 4).
8168 * They seem to have no effect. Bug #3212. JRA.
8171 if (total_data && (total_data != 4)) {
8172 /* Any data in this call is an EA list. */
8173 if (total_data < 10) {
8174 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8178 if (IVAL(pdata,0) > total_data) {
8179 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8180 IVAL(pdata,0), (unsigned int)total_data));
8181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8185 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8188 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8192 if (!lp_ea_support(SNUM(conn))) {
8193 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8197 /* If total_data == 4 Windows doesn't care what values
8198 * are placed in that field, it just ignores them.
8199 * The System i QNTC IBM SMB client puts bad values here,
8200 * so ignore them. */
8202 status = create_directory(conn, req, smb_dname);
8204 if (!NT_STATUS_IS_OK(status)) {
8205 reply_nterror(req, status);
8209 /* Try and set any given EA. */
8211 status = set_ea(conn, NULL, smb_dname, ea_list);
8212 if (!NT_STATUS_IS_OK(status)) {
8213 reply_nterror(req, status);
8218 /* Realloc the parameter and data sizes */
8219 *pparams = (char *)SMB_REALLOC(*pparams,2);
8220 if(*pparams == NULL) {
8221 reply_nterror(req, NT_STATUS_NO_MEMORY);
8228 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8231 TALLOC_FREE(smb_dname);
8235 /****************************************************************************
8236 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8237 We don't actually do this - we just send a null response.
8238 ****************************************************************************/
8240 static void call_trans2findnotifyfirst(connection_struct *conn,
8241 struct smb_request *req,
8242 char **pparams, int total_params,
8243 char **ppdata, int total_data,
8244 unsigned int max_data_bytes)
8246 char *params = *pparams;
8249 if (total_params < 6) {
8250 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8254 info_level = SVAL(params,4);
8255 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8257 switch (info_level) {
8262 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8266 /* Realloc the parameter and data sizes */
8267 *pparams = (char *)SMB_REALLOC(*pparams,6);
8268 if (*pparams == NULL) {
8269 reply_nterror(req, NT_STATUS_NO_MEMORY);
8274 SSVAL(params,0,fnf_handle);
8275 SSVAL(params,2,0); /* No changes */
8276 SSVAL(params,4,0); /* No EA errors */
8283 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8288 /****************************************************************************
8289 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8290 changes). Currently this does nothing.
8291 ****************************************************************************/
8293 static void call_trans2findnotifynext(connection_struct *conn,
8294 struct smb_request *req,
8295 char **pparams, int total_params,
8296 char **ppdata, int total_data,
8297 unsigned int max_data_bytes)
8299 char *params = *pparams;
8301 DEBUG(3,("call_trans2findnotifynext\n"));
8303 /* Realloc the parameter and data sizes */
8304 *pparams = (char *)SMB_REALLOC(*pparams,4);
8305 if (*pparams == NULL) {
8306 reply_nterror(req, NT_STATUS_NO_MEMORY);
8311 SSVAL(params,0,0); /* No changes */
8312 SSVAL(params,2,0); /* No EA errors */
8314 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8319 /****************************************************************************
8320 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8321 ****************************************************************************/
8323 static void call_trans2getdfsreferral(connection_struct *conn,
8324 struct smb_request *req,
8325 char **pparams, int total_params,
8326 char **ppdata, int total_data,
8327 unsigned int max_data_bytes)
8329 char *params = *pparams;
8330 char *pathname = NULL;
8332 int max_referral_level;
8333 NTSTATUS status = NT_STATUS_OK;
8334 TALLOC_CTX *ctx = talloc_tos();
8336 DEBUG(10,("call_trans2getdfsreferral\n"));
8338 if (total_params < 3) {
8339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8343 max_referral_level = SVAL(params,0);
8345 if(!lp_host_msdfs()) {
8346 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8350 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8351 total_params - 2, STR_TERMINATE);
8353 reply_nterror(req, NT_STATUS_NOT_FOUND);
8356 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8357 ppdata,&status)) < 0) {
8358 reply_nterror(req, status);
8362 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8363 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8364 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8369 #define LMCAT_SPL 0x53
8370 #define LMFUNC_GETJOBID 0x60
8372 /****************************************************************************
8373 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8374 ****************************************************************************/
8376 static void call_trans2ioctl(connection_struct *conn,
8377 struct smb_request *req,
8378 char **pparams, int total_params,
8379 char **ppdata, int total_data,
8380 unsigned int max_data_bytes)
8382 char *pdata = *ppdata;
8383 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8385 /* check for an invalid fid before proceeding */
8388 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8392 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8393 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8394 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8395 if (*ppdata == NULL) {
8396 reply_nterror(req, NT_STATUS_NO_MEMORY);
8401 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8402 CAN ACCEPT THIS IN UNICODE. JRA. */
8405 if (fsp->print_file) {
8406 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8410 srvstr_push(pdata, req->flags2, pdata + 2,
8411 lp_netbios_name(), 15,
8412 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8413 srvstr_push(pdata, req->flags2, pdata+18,
8414 lp_servicename(SNUM(conn)), 13,
8415 STR_ASCII|STR_TERMINATE); /* Service name */
8416 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8421 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8422 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8425 /****************************************************************************
8426 Reply to a SMBfindclose (stop trans2 directory search).
8427 ****************************************************************************/
8429 void reply_findclose(struct smb_request *req)
8432 struct smbd_server_connection *sconn = req->sconn;
8434 START_PROFILE(SMBfindclose);
8437 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8438 END_PROFILE(SMBfindclose);
8442 dptr_num = SVALS(req->vwv+0, 0);
8444 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8446 dptr_close(sconn, &dptr_num);
8448 reply_outbuf(req, 0, 0);
8450 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8452 END_PROFILE(SMBfindclose);
8456 /****************************************************************************
8457 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8458 ****************************************************************************/
8460 void reply_findnclose(struct smb_request *req)
8464 START_PROFILE(SMBfindnclose);
8467 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8468 END_PROFILE(SMBfindnclose);
8472 dptr_num = SVAL(req->vwv+0, 0);
8474 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8476 /* We never give out valid handles for a
8477 findnotifyfirst - so any dptr_num is ok here.
8480 reply_outbuf(req, 0, 0);
8482 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8484 END_PROFILE(SMBfindnclose);
8488 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8489 struct trans_state *state)
8491 if (get_Protocol() >= PROTOCOL_NT1) {
8492 req->flags2 |= 0x40; /* IS_LONG_NAME */
8493 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8496 if (conn->encrypt_level == Required && !req->encrypted) {
8497 if (state->call != TRANSACT2_QFSINFO &&
8498 state->call != TRANSACT2_SETFSINFO) {
8499 DEBUG(0,("handle_trans2: encryption required "
8501 (unsigned int)state->call));
8502 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8507 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8509 /* Now we must call the relevant TRANS2 function */
8510 switch(state->call) {
8511 case TRANSACT2_OPEN:
8513 START_PROFILE(Trans2_open);
8514 call_trans2open(conn, req,
8515 &state->param, state->total_param,
8516 &state->data, state->total_data,
8517 state->max_data_return);
8518 END_PROFILE(Trans2_open);
8522 case TRANSACT2_FINDFIRST:
8524 START_PROFILE(Trans2_findfirst);
8525 call_trans2findfirst(conn, req,
8526 &state->param, state->total_param,
8527 &state->data, state->total_data,
8528 state->max_data_return);
8529 END_PROFILE(Trans2_findfirst);
8533 case TRANSACT2_FINDNEXT:
8535 START_PROFILE(Trans2_findnext);
8536 call_trans2findnext(conn, req,
8537 &state->param, state->total_param,
8538 &state->data, state->total_data,
8539 state->max_data_return);
8540 END_PROFILE(Trans2_findnext);
8544 case TRANSACT2_QFSINFO:
8546 START_PROFILE(Trans2_qfsinfo);
8547 call_trans2qfsinfo(conn, req,
8548 &state->param, state->total_param,
8549 &state->data, state->total_data,
8550 state->max_data_return);
8551 END_PROFILE(Trans2_qfsinfo);
8555 case TRANSACT2_SETFSINFO:
8557 START_PROFILE(Trans2_setfsinfo);
8558 call_trans2setfsinfo(conn, req,
8559 &state->param, state->total_param,
8560 &state->data, state->total_data,
8561 state->max_data_return);
8562 END_PROFILE(Trans2_setfsinfo);
8566 case TRANSACT2_QPATHINFO:
8567 case TRANSACT2_QFILEINFO:
8569 START_PROFILE(Trans2_qpathinfo);
8570 call_trans2qfilepathinfo(conn, req, state->call,
8571 &state->param, state->total_param,
8572 &state->data, state->total_data,
8573 state->max_data_return);
8574 END_PROFILE(Trans2_qpathinfo);
8578 case TRANSACT2_SETPATHINFO:
8579 case TRANSACT2_SETFILEINFO:
8581 START_PROFILE(Trans2_setpathinfo);
8582 call_trans2setfilepathinfo(conn, req, state->call,
8583 &state->param, state->total_param,
8584 &state->data, state->total_data,
8585 state->max_data_return);
8586 END_PROFILE(Trans2_setpathinfo);
8590 case TRANSACT2_FINDNOTIFYFIRST:
8592 START_PROFILE(Trans2_findnotifyfirst);
8593 call_trans2findnotifyfirst(conn, req,
8594 &state->param, state->total_param,
8595 &state->data, state->total_data,
8596 state->max_data_return);
8597 END_PROFILE(Trans2_findnotifyfirst);
8601 case TRANSACT2_FINDNOTIFYNEXT:
8603 START_PROFILE(Trans2_findnotifynext);
8604 call_trans2findnotifynext(conn, req,
8605 &state->param, state->total_param,
8606 &state->data, state->total_data,
8607 state->max_data_return);
8608 END_PROFILE(Trans2_findnotifynext);
8612 case TRANSACT2_MKDIR:
8614 START_PROFILE(Trans2_mkdir);
8615 call_trans2mkdir(conn, req,
8616 &state->param, state->total_param,
8617 &state->data, state->total_data,
8618 state->max_data_return);
8619 END_PROFILE(Trans2_mkdir);
8623 case TRANSACT2_GET_DFS_REFERRAL:
8625 START_PROFILE(Trans2_get_dfs_referral);
8626 call_trans2getdfsreferral(conn, req,
8627 &state->param, state->total_param,
8628 &state->data, state->total_data,
8629 state->max_data_return);
8630 END_PROFILE(Trans2_get_dfs_referral);
8634 case TRANSACT2_IOCTL:
8636 START_PROFILE(Trans2_ioctl);
8637 call_trans2ioctl(conn, req,
8638 &state->param, state->total_param,
8639 &state->data, state->total_data,
8640 state->max_data_return);
8641 END_PROFILE(Trans2_ioctl);
8646 /* Error in request */
8647 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8648 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8652 /****************************************************************************
8653 Reply to a SMBtrans2.
8654 ****************************************************************************/
8656 void reply_trans2(struct smb_request *req)
8658 connection_struct *conn = req->conn;
8663 unsigned int tran_call;
8664 struct trans_state *state;
8667 START_PROFILE(SMBtrans2);
8669 if (req->wct < 14) {
8670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8671 END_PROFILE(SMBtrans2);
8675 dsoff = SVAL(req->vwv+12, 0);
8676 dscnt = SVAL(req->vwv+11, 0);
8677 psoff = SVAL(req->vwv+10, 0);
8678 pscnt = SVAL(req->vwv+9, 0);
8679 tran_call = SVAL(req->vwv+14, 0);
8681 result = allow_new_trans(conn->pending_trans, req->mid);
8682 if (!NT_STATUS_IS_OK(result)) {
8683 DEBUG(2, ("Got invalid trans2 request: %s\n",
8684 nt_errstr(result)));
8685 reply_nterror(req, result);
8686 END_PROFILE(SMBtrans2);
8691 switch (tran_call) {
8692 /* List the allowed trans2 calls on IPC$ */
8693 case TRANSACT2_OPEN:
8694 case TRANSACT2_GET_DFS_REFERRAL:
8695 case TRANSACT2_QFILEINFO:
8696 case TRANSACT2_QFSINFO:
8697 case TRANSACT2_SETFSINFO:
8700 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8701 END_PROFILE(SMBtrans2);
8706 if ((state = talloc(conn, struct trans_state)) == NULL) {
8707 DEBUG(0, ("talloc failed\n"));
8708 reply_nterror(req, NT_STATUS_NO_MEMORY);
8709 END_PROFILE(SMBtrans2);
8713 state->cmd = SMBtrans2;
8715 state->mid = req->mid;
8716 state->vuid = req->vuid;
8717 state->setup_count = SVAL(req->vwv+13, 0);
8718 state->setup = NULL;
8719 state->total_param = SVAL(req->vwv+0, 0);
8720 state->param = NULL;
8721 state->total_data = SVAL(req->vwv+1, 0);
8723 state->max_param_return = SVAL(req->vwv+2, 0);
8724 state->max_data_return = SVAL(req->vwv+3, 0);
8725 state->max_setup_return = SVAL(req->vwv+4, 0);
8726 state->close_on_completion = BITSETW(req->vwv+5, 0);
8727 state->one_way = BITSETW(req->vwv+5, 1);
8729 state->call = tran_call;
8731 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8732 is so as a sanity check */
8733 if (state->setup_count != 1) {
8735 * Need to have rc=0 for ioctl to get job id for OS/2.
8736 * Network printing will fail if function is not successful.
8737 * Similar function in reply.c will be used if protocol
8738 * is LANMAN1.0 instead of LM1.2X002.
8739 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8740 * outbuf doesn't have to be set(only job id is used).
8742 if ( (state->setup_count == 4)
8743 && (tran_call == TRANSACT2_IOCTL)
8744 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8745 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8746 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8748 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8749 DEBUG(2,("Transaction is %d\n",tran_call));
8751 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8752 END_PROFILE(SMBtrans2);
8757 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8760 if (state->total_data) {
8762 if (trans_oob(state->total_data, 0, dscnt)
8763 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8767 /* Can't use talloc here, the core routines do realloc on the
8768 * params and data. */
8769 state->data = (char *)SMB_MALLOC(state->total_data);
8770 if (state->data == NULL) {
8771 DEBUG(0,("reply_trans2: data malloc fail for %u "
8772 "bytes !\n", (unsigned int)state->total_data));
8774 reply_nterror(req, NT_STATUS_NO_MEMORY);
8775 END_PROFILE(SMBtrans2);
8779 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8782 if (state->total_param) {
8784 if (trans_oob(state->total_param, 0, pscnt)
8785 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8789 /* Can't use talloc here, the core routines do realloc on the
8790 * params and data. */
8791 state->param = (char *)SMB_MALLOC(state->total_param);
8792 if (state->param == NULL) {
8793 DEBUG(0,("reply_trans: param malloc fail for %u "
8794 "bytes !\n", (unsigned int)state->total_param));
8795 SAFE_FREE(state->data);
8797 reply_nterror(req, NT_STATUS_NO_MEMORY);
8798 END_PROFILE(SMBtrans2);
8802 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8805 state->received_data = dscnt;
8806 state->received_param = pscnt;
8808 if ((state->received_param == state->total_param) &&
8809 (state->received_data == state->total_data)) {
8811 handle_trans2(conn, req, state);
8813 SAFE_FREE(state->data);
8814 SAFE_FREE(state->param);
8816 END_PROFILE(SMBtrans2);
8820 DLIST_ADD(conn->pending_trans, state);
8822 /* We need to send an interim response then receive the rest
8823 of the parameter/data bytes */
8824 reply_outbuf(req, 0, 0);
8825 show_msg((char *)req->outbuf);
8826 END_PROFILE(SMBtrans2);
8831 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8832 SAFE_FREE(state->data);
8833 SAFE_FREE(state->param);
8835 END_PROFILE(SMBtrans2);
8836 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8840 /****************************************************************************
8841 Reply to a SMBtranss2
8842 ****************************************************************************/
8844 void reply_transs2(struct smb_request *req)
8846 connection_struct *conn = req->conn;
8847 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8848 struct trans_state *state;
8850 START_PROFILE(SMBtranss2);
8852 show_msg((const char *)req->inbuf);
8855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8856 END_PROFILE(SMBtranss2);
8860 for (state = conn->pending_trans; state != NULL;
8861 state = state->next) {
8862 if (state->mid == req->mid) {
8867 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8869 END_PROFILE(SMBtranss2);
8873 /* Revise state->total_param and state->total_data in case they have
8874 changed downwards */
8876 if (SVAL(req->vwv+0, 0) < state->total_param)
8877 state->total_param = SVAL(req->vwv+0, 0);
8878 if (SVAL(req->vwv+1, 0) < state->total_data)
8879 state->total_data = SVAL(req->vwv+1, 0);
8881 pcnt = SVAL(req->vwv+2, 0);
8882 poff = SVAL(req->vwv+3, 0);
8883 pdisp = SVAL(req->vwv+4, 0);
8885 dcnt = SVAL(req->vwv+5, 0);
8886 doff = SVAL(req->vwv+6, 0);
8887 ddisp = SVAL(req->vwv+7, 0);
8889 state->received_param += pcnt;
8890 state->received_data += dcnt;
8892 if ((state->received_data > state->total_data) ||
8893 (state->received_param > state->total_param))
8897 if (trans_oob(state->total_param, pdisp, pcnt)
8898 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8901 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8905 if (trans_oob(state->total_data, ddisp, dcnt)
8906 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8909 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8912 if ((state->received_param < state->total_param) ||
8913 (state->received_data < state->total_data)) {
8914 END_PROFILE(SMBtranss2);
8918 handle_trans2(conn, req, state);
8920 DLIST_REMOVE(conn->pending_trans, state);
8921 SAFE_FREE(state->data);
8922 SAFE_FREE(state->param);
8925 END_PROFILE(SMBtranss2);
8930 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8931 DLIST_REMOVE(conn->pending_trans, state);
8932 SAFE_FREE(state->data);
8933 SAFE_FREE(state->param);
8935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8936 END_PROFILE(SMBtranss2);