2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "libcli/security/security.h"
37 #include "smbprofile.h"
38 #include "rpc_server/srv_pipe_hnd.h"
40 #define DIR_ENTRY_SAFETY_MARGIN 4096
42 static char *store_file_unix_basic(connection_struct *conn,
45 const SMB_STRUCT_STAT *psbuf);
47 static char *store_file_unix_basic_info2(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 /********************************************************************
53 Roundup a value to the nearest allocation roundup size boundary.
54 Only do this for Windows clients.
55 ********************************************************************/
57 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
59 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
61 /* Only roundup for Windows clients. */
62 enum remote_arch_types ra_type = get_remote_arch();
63 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
64 val = SMB_ROUNDUP(val,rval);
69 /********************************************************************
70 Create a 64 bit FileIndex. If the file is on the same device as
71 the root of the share, just return the 64-bit inode. If it isn't,
72 mangle as we used to do.
73 ********************************************************************/
75 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
78 if (conn->base_share_dev == psbuf->st_ex_dev) {
79 return (uint64_t)psbuf->st_ex_ino;
81 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
82 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
86 /****************************************************************************
87 Utility functions for dealing with extended attributes.
88 ****************************************************************************/
90 /****************************************************************************
91 Refuse to allow clients to overwrite our private xattrs.
92 ****************************************************************************/
94 static bool samba_private_attr_name(const char *unix_ea_name)
96 static const char * const prohibited_ea_names[] = {
97 SAMBA_POSIX_INHERITANCE_EA_NAME,
98 SAMBA_XATTR_DOS_ATTRIB,
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
110 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
111 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
117 /****************************************************************************
118 Get one EA value. Fill in a struct ea_struct.
119 ****************************************************************************/
121 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
122 files_struct *fsp, const char *fname,
123 const char *ea_name, struct ea_struct *pea)
125 /* Get the value of this xattr. Max size is 64k. */
126 size_t attr_size = 256;
132 val = talloc_realloc(mem_ctx, val, char, attr_size);
134 return NT_STATUS_NO_MEMORY;
137 if (fsp && fsp->fh->fd != -1) {
138 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
140 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
143 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
149 return map_nt_error_from_unix(errno);
152 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
153 dump_data(10, (uint8 *)val, sizeret);
156 if (strnequal(ea_name, "user.", 5)) {
157 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
159 pea->name = talloc_strdup(mem_ctx, ea_name);
161 if (pea->name == NULL) {
163 return NT_STATUS_NO_MEMORY;
165 pea->value.data = (unsigned char *)val;
166 pea->value.length = (size_t)sizeret;
170 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
171 files_struct *fsp, const char *fname,
172 char ***pnames, size_t *pnum_names)
174 /* Get a list of all xattrs. Max namesize is 64k. */
175 size_t ea_namelist_size = 1024;
176 char *ea_namelist = NULL;
181 ssize_t sizeret = -1;
183 if (!lp_ea_support(SNUM(conn))) {
192 * TALLOC the result early to get the talloc hierarchy right.
195 names = talloc_array(mem_ctx, char *, 1);
197 DEBUG(0, ("talloc failed\n"));
198 return NT_STATUS_NO_MEMORY;
201 while (ea_namelist_size <= 65536) {
203 ea_namelist = talloc_realloc(
204 names, ea_namelist, char, ea_namelist_size);
205 if (ea_namelist == NULL) {
206 DEBUG(0, ("talloc failed\n"));
208 return NT_STATUS_NO_MEMORY;
211 if (fsp && fsp->fh->fd != -1) {
212 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
215 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
219 if ((sizeret == -1) && (errno == ERANGE)) {
220 ea_namelist_size *= 2;
229 return map_nt_error_from_unix(errno);
232 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
233 (unsigned int)sizeret));
245 * Ensure the result is 0-terminated
248 if (ea_namelist[sizeret-1] != '\0') {
250 return NT_STATUS_INTERNAL_ERROR;
258 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
262 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
264 DEBUG(0, ("talloc failed\n"));
266 return NT_STATUS_NO_MEMORY;
272 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
273 names[num_names++] = p;
281 *pnum_names = num_names;
285 /****************************************************************************
286 Return a linked list of the total EA's. Plus the total size
287 ****************************************************************************/
289 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
290 const char *fname, size_t *pea_total_len)
292 /* Get a list of all xattrs. Max namesize is 64k. */
295 struct ea_list *ea_list_head = NULL;
300 if (!lp_ea_support(SNUM(conn))) {
304 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
307 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
311 for (i=0; i<num_names; i++) {
312 struct ea_list *listp;
315 if (strnequal(names[i], "system.", 7)
316 || samba_private_attr_name(names[i]))
319 listp = talloc(mem_ctx, struct ea_list);
324 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
330 push_ascii_fstring(dos_ea_name, listp->ea.name);
333 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
335 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
336 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
337 (unsigned int)listp->ea.value.length));
339 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
343 /* Add on 4 for total length. */
344 if (*pea_total_len) {
348 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
349 (unsigned int)*pea_total_len));
354 /****************************************************************************
355 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
357 ****************************************************************************/
359 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
360 connection_struct *conn, struct ea_list *ea_list)
362 unsigned int ret_data_size = 4;
365 SMB_ASSERT(total_data_size >= 4);
367 if (!lp_ea_support(SNUM(conn))) {
372 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
375 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
376 dos_namelen = strlen(dos_ea_name);
377 if (dos_namelen > 255 || dos_namelen == 0) {
380 if (ea_list->ea.value.length > 65535) {
383 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
387 /* We know we have room. */
388 SCVAL(p,0,ea_list->ea.flags);
389 SCVAL(p,1,dos_namelen);
390 SSVAL(p,2,ea_list->ea.value.length);
391 strlcpy(p+4, dos_ea_name, dos_namelen+1);
392 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
394 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
395 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
398 ret_data_size = PTR_DIFF(p, pdata);
399 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
400 SIVAL(pdata,0,ret_data_size);
401 return ret_data_size;
404 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
406 unsigned int total_data_size,
407 unsigned int *ret_data_size,
408 connection_struct *conn,
409 struct ea_list *ea_list)
411 uint8_t *p = (uint8_t *)pdata;
412 uint8_t *last_start = NULL;
416 if (!lp_ea_support(SNUM(conn))) {
417 return NT_STATUS_NO_EAS_ON_FILE;
420 for (; ea_list; ea_list = ea_list->next) {
426 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
430 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
431 dos_namelen = strlen(dos_ea_name);
432 if (dos_namelen > 255 || dos_namelen == 0) {
433 return NT_STATUS_INTERNAL_ERROR;
435 if (ea_list->ea.value.length > 65535) {
436 return NT_STATUS_INTERNAL_ERROR;
439 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
442 size_t pad = 4 - (this_size % 4);
446 if (this_size > total_data_size) {
447 return NT_STATUS_INFO_LENGTH_MISMATCH;
450 /* We know we have room. */
451 SIVAL(p, 0x00, 0); /* next offset */
452 SCVAL(p, 0x04, ea_list->ea.flags);
453 SCVAL(p, 0x05, dos_namelen);
454 SSVAL(p, 0x06, ea_list->ea.value.length);
455 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
456 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
458 total_data_size -= this_size;
462 *ret_data_size = PTR_DIFF(p, pdata);
463 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
467 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
469 size_t total_ea_len = 0;
470 TALLOC_CTX *mem_ctx = NULL;
472 if (!lp_ea_support(SNUM(conn))) {
475 mem_ctx = talloc_tos();
476 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
480 /****************************************************************************
481 Ensure the EA name is case insensitive by matching any existing EA name.
482 ****************************************************************************/
484 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
487 TALLOC_CTX *mem_ctx = talloc_tos();
488 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
490 for (; ea_list; ea_list = ea_list->next) {
491 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
492 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
493 &unix_ea_name[5], ea_list->ea.name));
494 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
500 /****************************************************************************
501 Set or delete an extended attribute.
502 ****************************************************************************/
504 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
505 const struct smb_filename *smb_fname, struct ea_list *ea_list)
509 if (!lp_ea_support(SNUM(conn))) {
510 return NT_STATUS_EAS_NOT_SUPPORTED;
513 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
514 return NT_STATUS_ACCESS_DENIED;
517 /* For now setting EAs on streams isn't supported. */
518 fname = smb_fname->base_name;
520 for (;ea_list; ea_list = ea_list->next) {
522 fstring unix_ea_name;
524 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
525 fstrcat(unix_ea_name, ea_list->ea.name);
527 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
529 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
531 if (samba_private_attr_name(unix_ea_name)) {
532 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
533 return NT_STATUS_ACCESS_DENIED;
536 if (ea_list->ea.value.length == 0) {
537 /* Remove the attribute. */
538 if (fsp && (fsp->fh->fd != -1)) {
539 DEBUG(10,("set_ea: deleting ea name %s on "
540 "file %s by file descriptor.\n",
541 unix_ea_name, fsp_str_dbg(fsp)));
542 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
544 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
545 unix_ea_name, fname));
546 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
549 /* Removing a non existent attribute always succeeds. */
550 if (ret == -1 && errno == ENOATTR) {
551 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
557 if (fsp && (fsp->fh->fd != -1)) {
558 DEBUG(10,("set_ea: setting ea name %s on file "
559 "%s by file descriptor.\n",
560 unix_ea_name, fsp_str_dbg(fsp)));
561 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
562 ea_list->ea.value.data, ea_list->ea.value.length, 0);
564 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
565 unix_ea_name, fname));
566 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
567 ea_list->ea.value.data, ea_list->ea.value.length, 0);
573 if (errno == ENOTSUP) {
574 return NT_STATUS_EAS_NOT_SUPPORTED;
577 return map_nt_error_from_unix(errno);
583 /****************************************************************************
584 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
585 ****************************************************************************/
587 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
589 struct ea_list *ea_list_head = NULL;
590 size_t converted_size, offset = 0;
592 while (offset + 2 < data_size) {
593 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
594 unsigned int namelen = CVAL(pdata,offset);
596 offset++; /* Go past the namelen byte. */
598 /* integer wrap paranioa. */
599 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
600 (offset > data_size) || (namelen > data_size) ||
601 (offset + namelen >= data_size)) {
604 /* Ensure the name is null terminated. */
605 if (pdata[offset + namelen] != '\0') {
608 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
610 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
611 "failed: %s", strerror(errno)));
617 offset += (namelen + 1); /* Go past the name + terminating zero. */
618 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
619 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
625 /****************************************************************************
626 Read one EA list entry from the buffer.
627 ****************************************************************************/
629 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
631 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
633 unsigned int namelen;
634 size_t converted_size;
644 eal->ea.flags = CVAL(pdata,0);
645 namelen = CVAL(pdata,1);
646 val_len = SVAL(pdata,2);
648 if (4 + namelen + 1 + val_len > data_size) {
652 /* Ensure the name is null terminated. */
653 if (pdata[namelen + 4] != '\0') {
656 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
657 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
664 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
665 if (!eal->ea.value.data) {
669 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
671 /* Ensure we're null terminated just in case we print the value. */
672 eal->ea.value.data[val_len] = '\0';
673 /* But don't count the null. */
674 eal->ea.value.length--;
677 *pbytes_used = 4 + namelen + 1 + val_len;
680 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
681 dump_data(10, eal->ea.value.data, eal->ea.value.length);
686 /****************************************************************************
687 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
688 ****************************************************************************/
690 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
692 struct ea_list *ea_list_head = NULL;
694 size_t bytes_used = 0;
696 while (offset < data_size) {
697 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
703 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
704 offset += bytes_used;
710 /****************************************************************************
711 Count the total EA size needed.
712 ****************************************************************************/
714 static size_t ea_list_size(struct ea_list *ealist)
717 struct ea_list *listp;
720 for (listp = ealist; listp; listp = listp->next) {
721 push_ascii_fstring(dos_ea_name, listp->ea.name);
722 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
724 /* Add on 4 for total length. */
732 /****************************************************************************
733 Return a union of EA's from a file list and a list of names.
734 The TALLOC context for the two lists *MUST* be identical as we steal
735 memory from one list to add to another. JRA.
736 ****************************************************************************/
738 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
740 struct ea_list *nlistp, *flistp;
742 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
743 for (flistp = file_list; flistp; flistp = flistp->next) {
744 if (strequal(nlistp->ea.name, flistp->ea.name)) {
750 /* Copy the data from this entry. */
751 nlistp->ea.flags = flistp->ea.flags;
752 nlistp->ea.value = flistp->ea.value;
755 nlistp->ea.flags = 0;
756 ZERO_STRUCT(nlistp->ea.value);
760 *total_ea_len = ea_list_size(name_list);
764 /****************************************************************************
765 Send the required number of replies back.
766 We assume all fields other than the data fields are
767 set correctly for the type of call.
768 HACK ! Always assumes smb_setup field is zero.
769 ****************************************************************************/
771 void send_trans2_replies(connection_struct *conn,
772 struct smb_request *req,
779 /* As we are using a protocol > LANMAN1 then the max_send
780 variable must have been set in the sessetupX call.
781 This takes precedence over the max_xmit field in the
782 global struct. These different max_xmit variables should
783 be merged as this is now too confusing */
785 int data_to_send = datasize;
786 int params_to_send = paramsize;
788 const char *pp = params;
789 const char *pd = pdata;
790 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
791 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
792 int data_alignment_offset = 0;
793 bool overflow = False;
794 struct smbd_server_connection *sconn = req->sconn;
795 int max_send = sconn->smb1.sessions.max_send;
797 /* Modify the data_to_send and datasize and set the error if
798 we're trying to send more than max_data_bytes. We still send
799 the part of the packet(s) that fit. Strange, but needed
802 if (max_data_bytes > 0 && datasize > max_data_bytes) {
803 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
804 max_data_bytes, datasize ));
805 datasize = data_to_send = max_data_bytes;
809 /* If there genuinely are no parameters or data to send just send the empty packet */
811 if(params_to_send == 0 && data_to_send == 0) {
812 reply_outbuf(req, 10, 0);
813 show_msg((char *)req->outbuf);
814 if (!srv_send_smb(sconn,
817 IS_CONN_ENCRYPTED(conn),
819 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
821 TALLOC_FREE(req->outbuf);
825 /* When sending params and data ensure that both are nicely aligned */
826 /* Only do this alignment when there is also data to send - else
827 can cause NT redirector problems. */
829 if (((params_to_send % 4) != 0) && (data_to_send != 0))
830 data_alignment_offset = 4 - (params_to_send % 4);
832 /* Space is bufsize minus Netbios over TCP header minus SMB header */
833 /* The alignment_offset is to align the param bytes on an even byte
834 boundary. NT 4.0 Beta needs this to work correctly. */
836 useable_space = max_send - (smb_size
839 + data_alignment_offset);
841 if (useable_space < 0) {
842 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
843 "= %d!!!", useable_space));
844 exit_server_cleanly("send_trans2_replies: Not enough space");
847 while (params_to_send || data_to_send) {
848 /* Calculate whether we will totally or partially fill this packet */
850 total_sent_thistime = params_to_send + data_to_send;
852 /* We can never send more than useable_space */
854 * Note that 'useable_space' does not include the alignment offsets,
855 * but we must include the alignment offsets in the calculation of
856 * the length of the data we send over the wire, as the alignment offsets
857 * are sent here. Fix from Marc_Jacobsen@hp.com.
860 total_sent_thistime = MIN(total_sent_thistime, useable_space);
862 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
863 + data_alignment_offset);
866 * We might have SMBtrans2s in req which was transferred to
867 * the outbuf, fix that.
869 SCVAL(req->outbuf, smb_com, SMBtrans2);
871 /* Set total params and data to be sent */
872 SSVAL(req->outbuf,smb_tprcnt,paramsize);
873 SSVAL(req->outbuf,smb_tdrcnt,datasize);
875 /* Calculate how many parameters and data we can fit into
876 * this packet. Parameters get precedence
879 params_sent_thistime = MIN(params_to_send,useable_space);
880 data_sent_thistime = useable_space - params_sent_thistime;
881 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
883 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
885 /* smb_proff is the offset from the start of the SMB header to the
886 parameter bytes, however the first 4 bytes of outbuf are
887 the Netbios over TCP header. Thus use smb_base() to subtract
888 them from the calculation */
890 SSVAL(req->outbuf,smb_proff,
891 ((smb_buf(req->outbuf)+alignment_offset)
892 - smb_base(req->outbuf)));
894 if(params_sent_thistime == 0)
895 SSVAL(req->outbuf,smb_prdisp,0);
897 /* Absolute displacement of param bytes sent in this packet */
898 SSVAL(req->outbuf,smb_prdisp,pp - params);
900 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
901 if(data_sent_thistime == 0) {
902 SSVAL(req->outbuf,smb_droff,0);
903 SSVAL(req->outbuf,smb_drdisp, 0);
905 /* The offset of the data bytes is the offset of the
906 parameter bytes plus the number of parameters being sent this time */
907 SSVAL(req->outbuf, smb_droff,
908 ((smb_buf(req->outbuf)+alignment_offset)
909 - smb_base(req->outbuf))
910 + params_sent_thistime + data_alignment_offset);
911 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
914 /* Initialize the padding for alignment */
916 if (alignment_offset != 0) {
917 memset(smb_buf(req->outbuf), 0, alignment_offset);
920 /* Copy the param bytes into the packet */
922 if(params_sent_thistime) {
923 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
924 params_sent_thistime);
927 /* Copy in the data bytes */
928 if(data_sent_thistime) {
929 if (data_alignment_offset != 0) {
930 memset((smb_buf(req->outbuf)+alignment_offset+
931 params_sent_thistime), 0,
932 data_alignment_offset);
934 memcpy(smb_buf(req->outbuf)+alignment_offset
935 +params_sent_thistime+data_alignment_offset,
936 pd,data_sent_thistime);
939 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
940 params_sent_thistime, data_sent_thistime, useable_space));
941 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
942 params_to_send, data_to_send, paramsize, datasize));
945 error_packet_set((char *)req->outbuf,
946 ERRDOS,ERRbufferoverflow,
947 STATUS_BUFFER_OVERFLOW,
951 /* Send the packet */
952 show_msg((char *)req->outbuf);
953 if (!srv_send_smb(sconn,
956 IS_CONN_ENCRYPTED(conn),
958 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
960 TALLOC_FREE(req->outbuf);
962 pp += params_sent_thistime;
963 pd += data_sent_thistime;
965 params_to_send -= params_sent_thistime;
966 data_to_send -= data_sent_thistime;
969 if(params_to_send < 0 || data_to_send < 0) {
970 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
971 params_to_send, data_to_send));
979 /****************************************************************************
980 Reply to a TRANSACT2_OPEN.
981 ****************************************************************************/
983 static void call_trans2open(connection_struct *conn,
984 struct smb_request *req,
985 char **pparams, int total_params,
986 char **ppdata, int total_data,
987 unsigned int max_data_bytes)
989 struct smb_filename *smb_fname = NULL;
990 char *params = *pparams;
991 char *pdata = *ppdata;
996 bool return_additional_info;
1005 int fattr=0,mtime=0;
1006 SMB_INO_T inode = 0;
1009 struct ea_list *ea_list = NULL;
1014 uint32 create_disposition;
1015 uint32 create_options = 0;
1016 uint32_t private_flags = 0;
1017 TALLOC_CTX *ctx = talloc_tos();
1020 * Ensure we have enough parameters to perform the operation.
1023 if (total_params < 29) {
1024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1028 flags = SVAL(params, 0);
1029 deny_mode = SVAL(params, 2);
1030 open_attr = SVAL(params,6);
1031 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1032 if (oplock_request) {
1033 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1037 return_additional_info = BITSETW(params,0);
1038 open_sattr = SVAL(params, 4);
1039 open_time = make_unix_date3(params+8);
1041 open_ofun = SVAL(params,12);
1042 open_size = IVAL(params,14);
1043 pname = ¶ms[28];
1046 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1050 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1051 total_params - 28, STR_TERMINATE,
1053 if (!NT_STATUS_IS_OK(status)) {
1054 reply_nterror(req, status);
1058 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1059 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1060 (unsigned int)open_ofun, open_size));
1062 status = filename_convert(ctx,
1064 req->flags2 & FLAGS2_DFS_PATHNAMES,
1069 if (!NT_STATUS_IS_OK(status)) {
1070 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1071 reply_botherror(req,
1072 NT_STATUS_PATH_NOT_COVERED,
1073 ERRSRV, ERRbadpath);
1076 reply_nterror(req, status);
1080 if (open_ofun == 0) {
1081 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1085 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1087 &access_mask, &share_mode,
1088 &create_disposition,
1091 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1095 /* Any data in this call is an EA list. */
1096 if (total_data && (total_data != 4)) {
1097 if (total_data < 10) {
1098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1102 if (IVAL(pdata,0) > total_data) {
1103 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1104 IVAL(pdata,0), (unsigned int)total_data));
1105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1109 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1116 if (!lp_ea_support(SNUM(conn))) {
1117 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1122 status = SMB_VFS_CREATE_FILE(
1125 0, /* root_dir_fid */
1126 smb_fname, /* fname */
1127 access_mask, /* access_mask */
1128 share_mode, /* share_access */
1129 create_disposition, /* create_disposition*/
1130 create_options, /* create_options */
1131 open_attr, /* file_attributes */
1132 oplock_request, /* oplock_request */
1133 open_size, /* allocation_size */
1136 ea_list, /* ea_list */
1138 &smb_action); /* psbuf */
1140 if (!NT_STATUS_IS_OK(status)) {
1141 if (open_was_deferred(req->sconn, req->mid)) {
1142 /* We have re-scheduled this call. */
1145 reply_openerror(req, status);
1149 size = get_file_size_stat(&smb_fname->st);
1150 fattr = dos_mode(conn, smb_fname);
1151 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1152 inode = smb_fname->st.st_ex_ino;
1153 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1154 close_file(req, fsp, ERROR_CLOSE);
1155 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1159 /* Realloc the size of parameters and data we will return */
1160 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1161 if(*pparams == NULL ) {
1162 reply_nterror(req, NT_STATUS_NO_MEMORY);
1167 SSVAL(params,0,fsp->fnum);
1168 SSVAL(params,2,fattr);
1169 srv_put_dos_date2(params,4, mtime);
1170 SIVAL(params,8, (uint32)size);
1171 SSVAL(params,12,deny_mode);
1172 SSVAL(params,14,0); /* open_type - file or directory. */
1173 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1175 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1176 smb_action |= EXTENDED_OPLOCK_GRANTED;
1179 SSVAL(params,18,smb_action);
1182 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1184 SIVAL(params,20,inode);
1185 SSVAL(params,24,0); /* Padding. */
1187 uint32 ea_size = estimate_ea_size(conn, fsp,
1188 fsp->fsp_name->base_name);
1189 SIVAL(params, 26, ea_size);
1191 SIVAL(params, 26, 0);
1194 /* Send the required number of replies */
1195 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1197 TALLOC_FREE(smb_fname);
1200 /*********************************************************
1201 Routine to check if a given string matches exactly.
1202 as a special case a mask of "." does NOT match. That
1203 is required for correct wildcard semantics
1204 Case can be significant or not.
1205 **********************************************************/
1207 static bool exact_match(bool has_wild,
1208 bool case_sensitive,
1212 if (mask[0] == '.' && mask[1] == 0) {
1220 if (case_sensitive) {
1221 return strcmp(str,mask)==0;
1223 return strcasecmp_m(str,mask) == 0;
1227 /****************************************************************************
1228 Return the filetype for UNIX extensions.
1229 ****************************************************************************/
1231 static uint32 unix_filetype(mode_t mode)
1234 return UNIX_TYPE_FILE;
1235 else if(S_ISDIR(mode))
1236 return UNIX_TYPE_DIR;
1238 else if(S_ISLNK(mode))
1239 return UNIX_TYPE_SYMLINK;
1242 else if(S_ISCHR(mode))
1243 return UNIX_TYPE_CHARDEV;
1246 else if(S_ISBLK(mode))
1247 return UNIX_TYPE_BLKDEV;
1250 else if(S_ISFIFO(mode))
1251 return UNIX_TYPE_FIFO;
1254 else if(S_ISSOCK(mode))
1255 return UNIX_TYPE_SOCKET;
1258 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1259 return UNIX_TYPE_UNKNOWN;
1262 /****************************************************************************
1263 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1264 ****************************************************************************/
1266 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1268 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1269 const SMB_STRUCT_STAT *psbuf,
1271 enum perm_type ptype,
1276 if (perms == SMB_MODE_NO_CHANGE) {
1277 if (!VALID_STAT(*psbuf)) {
1278 return NT_STATUS_INVALID_PARAMETER;
1280 *ret_perms = psbuf->st_ex_mode;
1281 return NT_STATUS_OK;
1285 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1286 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1287 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1288 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1289 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1290 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1291 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1292 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1293 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1295 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1298 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1301 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1306 /* Apply mode mask */
1307 ret &= lp_create_mask(SNUM(conn));
1308 /* Add in force bits */
1309 ret |= lp_force_create_mode(SNUM(conn));
1312 ret &= lp_dir_mask(SNUM(conn));
1313 /* Add in force bits */
1314 ret |= lp_force_dir_mode(SNUM(conn));
1316 case PERM_EXISTING_FILE:
1317 /* Apply mode mask */
1318 ret &= lp_security_mask(SNUM(conn));
1319 /* Add in force bits */
1320 ret |= lp_force_security_mode(SNUM(conn));
1322 case PERM_EXISTING_DIR:
1323 /* Apply mode mask */
1324 ret &= lp_dir_security_mask(SNUM(conn));
1325 /* Add in force bits */
1326 ret |= lp_force_dir_security_mode(SNUM(conn));
1331 return NT_STATUS_OK;
1334 /****************************************************************************
1335 Needed to show the msdfs symlinks as directories. Modifies psbuf
1336 to be a directory if it's a msdfs link.
1337 ****************************************************************************/
1339 static bool check_msdfs_link(connection_struct *conn,
1340 const char *pathname,
1341 SMB_STRUCT_STAT *psbuf)
1343 int saved_errno = errno;
1344 if(lp_host_msdfs() &&
1345 lp_msdfs_root(SNUM(conn)) &&
1346 is_msdfs_link(conn, pathname, psbuf)) {
1348 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1351 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1352 errno = saved_errno;
1355 errno = saved_errno;
1360 /****************************************************************************
1361 Get a level dependent lanman2 dir entry.
1362 ****************************************************************************/
1364 struct smbd_dirptr_lanman2_state {
1365 connection_struct *conn;
1366 uint32_t info_level;
1367 bool check_mangled_names;
1369 bool got_exact_match;
1372 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1378 struct smbd_dirptr_lanman2_state *state =
1379 (struct smbd_dirptr_lanman2_state *)private_data;
1381 char mangled_name[13]; /* mangled 8.3 name. */
1385 /* Mangle fname if it's an illegal name. */
1386 if (mangle_must_mangle(dname, state->conn->params)) {
1387 ok = name_to_8_3(dname, mangled_name,
1388 true, state->conn->params);
1392 fname = mangled_name;
1397 got_match = exact_match(state->has_wild,
1398 state->conn->case_sensitive,
1400 state->got_exact_match = got_match;
1402 got_match = mask_match(fname, mask,
1403 state->conn->case_sensitive);
1406 if(!got_match && state->check_mangled_names &&
1407 !mangle_is_8_3(fname, false, state->conn->params)) {
1409 * It turns out that NT matches wildcards against
1410 * both long *and* short names. This may explain some
1411 * of the wildcard wierdness from old DOS clients
1412 * that some people have been seeing.... JRA.
1414 /* Force the mangling into 8.3. */
1415 ok = name_to_8_3(fname, mangled_name,
1416 false, state->conn->params);
1421 got_match = exact_match(state->has_wild,
1422 state->conn->case_sensitive,
1423 mangled_name, mask);
1424 state->got_exact_match = got_match;
1426 got_match = mask_match(mangled_name, mask,
1427 state->conn->case_sensitive);
1435 *_fname = talloc_strdup(ctx, fname);
1436 if (*_fname == NULL) {
1443 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1445 struct smb_filename *smb_fname,
1448 struct smbd_dirptr_lanman2_state *state =
1449 (struct smbd_dirptr_lanman2_state *)private_data;
1450 bool ms_dfs_link = false;
1453 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1454 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1455 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1456 "Couldn't lstat [%s] (%s)\n",
1457 smb_fname_str_dbg(smb_fname),
1461 } else if (!VALID_STAT(smb_fname->st) &&
1462 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1463 /* Needed to show the msdfs symlinks as
1466 ms_dfs_link = check_msdfs_link(state->conn,
1467 smb_fname->base_name,
1470 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1471 "Couldn't stat [%s] (%s)\n",
1472 smb_fname_str_dbg(smb_fname),
1479 mode = dos_mode_msdfs(state->conn, smb_fname);
1481 mode = dos_mode(state->conn, smb_fname);
1488 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1489 connection_struct *conn,
1491 uint32_t info_level,
1492 struct ea_list *name_list,
1493 bool check_mangled_names,
1494 bool requires_resume_key,
1497 const struct smb_filename *smb_fname,
1498 int space_remaining,
1505 uint64_t *last_entry_off)
1507 char *p, *q, *pdata = *ppdata;
1509 uint64_t file_size = 0;
1510 uint64_t allocation_size = 0;
1511 uint64_t file_index = 0;
1513 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1514 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1515 time_t c_date = (time_t)0;
1517 char *last_entry_ptr;
1522 *out_of_space = false;
1524 ZERO_STRUCT(mdate_ts);
1525 ZERO_STRUCT(adate_ts);
1526 ZERO_STRUCT(create_date_ts);
1527 ZERO_STRUCT(cdate_ts);
1529 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1530 file_size = get_file_size_stat(&smb_fname->st);
1532 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1534 file_index = get_FileIndex(conn, &smb_fname->st);
1536 mdate_ts = smb_fname->st.st_ex_mtime;
1537 adate_ts = smb_fname->st.st_ex_atime;
1538 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1539 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1541 if (lp_dos_filetime_resolution(SNUM(conn))) {
1542 dos_filetime_timespec(&create_date_ts);
1543 dos_filetime_timespec(&mdate_ts);
1544 dos_filetime_timespec(&adate_ts);
1545 dos_filetime_timespec(&cdate_ts);
1548 create_date = convert_timespec_to_time_t(create_date_ts);
1549 mdate = convert_timespec_to_time_t(mdate_ts);
1550 adate = convert_timespec_to_time_t(adate_ts);
1551 c_date = convert_timespec_to_time_t(cdate_ts);
1553 /* align the record */
1554 SMB_ASSERT(align >= 1);
1556 off = (int)PTR_DIFF(pdata, base_data);
1557 pad = (off + (align-1)) & ~(align-1);
1560 if (pad && pad > space_remaining) {
1561 *out_of_space = true;
1562 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1563 "for padding (wanted %u, had %d)\n",
1566 return false; /* Not finished - just out of space */
1570 /* initialize padding to 0 */
1572 memset(pdata, 0, pad);
1574 space_remaining -= pad;
1576 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1586 switch (info_level) {
1587 case SMB_FIND_INFO_STANDARD:
1588 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1589 if(requires_resume_key) {
1593 srv_put_dos_date2(p,0,create_date);
1594 srv_put_dos_date2(p,4,adate);
1595 srv_put_dos_date2(p,8,mdate);
1596 SIVAL(p,12,(uint32)file_size);
1597 SIVAL(p,16,(uint32)allocation_size);
1601 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1602 p += ucs2_align(base_data, p, 0);
1604 len = srvstr_push(base_data, flags2, p,
1605 fname, PTR_DIFF(end_data, p),
1607 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1609 SCVAL(nameptr, -1, len - 2);
1611 SCVAL(nameptr, -1, 0);
1615 SCVAL(nameptr, -1, len - 1);
1617 SCVAL(nameptr, -1, 0);
1623 case SMB_FIND_EA_SIZE:
1624 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1625 if (requires_resume_key) {
1629 srv_put_dos_date2(p,0,create_date);
1630 srv_put_dos_date2(p,4,adate);
1631 srv_put_dos_date2(p,8,mdate);
1632 SIVAL(p,12,(uint32)file_size);
1633 SIVAL(p,16,(uint32)allocation_size);
1636 unsigned int ea_size = estimate_ea_size(conn, NULL,
1637 smb_fname->base_name);
1638 SIVAL(p,22,ea_size); /* Extended attributes */
1642 len = srvstr_push(base_data, flags2,
1643 p, fname, PTR_DIFF(end_data, p),
1644 STR_TERMINATE | STR_NOALIGN);
1645 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1658 SCVAL(nameptr,0,len);
1660 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1663 case SMB_FIND_EA_LIST:
1665 struct ea_list *file_list = NULL;
1668 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1672 if (requires_resume_key) {
1676 srv_put_dos_date2(p,0,create_date);
1677 srv_put_dos_date2(p,4,adate);
1678 srv_put_dos_date2(p,8,mdate);
1679 SIVAL(p,12,(uint32)file_size);
1680 SIVAL(p,16,(uint32)allocation_size);
1682 p += 22; /* p now points to the EA area. */
1684 file_list = get_ea_list_from_file(ctx, conn, NULL,
1685 smb_fname->base_name,
1687 name_list = ea_list_union(name_list, file_list, &ea_len);
1689 /* We need to determine if this entry will fit in the space available. */
1690 /* Max string size is 255 bytes. */
1691 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1692 *out_of_space = true;
1693 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1694 "(wanted %u, had %d)\n",
1695 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1697 return False; /* Not finished - just out of space */
1700 /* Push the ea_data followed by the name. */
1701 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1703 len = srvstr_push(base_data, flags2,
1704 p + 1, fname, PTR_DIFF(end_data, p+1),
1705 STR_TERMINATE | STR_NOALIGN);
1706 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1719 SCVAL(nameptr,0,len);
1721 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1725 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1726 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1727 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1729 SIVAL(p,0,reskey); p += 4;
1730 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1731 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1732 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1733 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1734 SOFF_T(p,0,file_size); p += 8;
1735 SOFF_T(p,0,allocation_size); p += 8;
1736 SIVAL(p,0,mode); p += 4;
1737 q = p; p += 4; /* q is placeholder for name length. */
1739 unsigned int ea_size = estimate_ea_size(conn, NULL,
1740 smb_fname->base_name);
1741 SIVAL(p,0,ea_size); /* Extended attributes */
1744 /* Clear the short name buffer. This is
1745 * IMPORTANT as not doing so will trigger
1746 * a Win2k client bug. JRA.
1748 if (!was_8_3 && check_mangled_names) {
1749 char mangled_name[13]; /* mangled 8.3 name. */
1750 if (!name_to_8_3(fname,mangled_name,True,
1752 /* Error - mangle failed ! */
1753 memset(mangled_name,'\0',12);
1755 mangled_name[12] = 0;
1756 len = srvstr_push(base_data, flags2,
1757 p+2, mangled_name, 24,
1758 STR_UPPER|STR_UNICODE);
1760 memset(p + 2 + len,'\0',24 - len);
1767 len = srvstr_push(base_data, flags2, p,
1768 fname, PTR_DIFF(end_data, p),
1769 STR_TERMINATE_ASCII);
1773 len = PTR_DIFF(p, pdata);
1774 pad = (len + (align-1)) & ~(align-1);
1776 * offset to the next entry, the caller
1777 * will overwrite it for the last entry
1778 * that's why we always include the padding
1782 * set padding to zero
1785 memset(p, 0, pad - len);
1792 case SMB_FIND_FILE_DIRECTORY_INFO:
1793 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1795 SIVAL(p,0,reskey); p += 4;
1796 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1797 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1798 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1799 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1800 SOFF_T(p,0,file_size); p += 8;
1801 SOFF_T(p,0,allocation_size); p += 8;
1802 SIVAL(p,0,mode); p += 4;
1803 len = srvstr_push(base_data, flags2,
1804 p + 4, fname, PTR_DIFF(end_data, p+4),
1805 STR_TERMINATE_ASCII);
1809 len = PTR_DIFF(p, pdata);
1810 pad = (len + (align-1)) & ~(align-1);
1812 * offset to the next entry, the caller
1813 * will overwrite it for the last entry
1814 * that's why we always include the padding
1818 * set padding to zero
1821 memset(p, 0, pad - len);
1828 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1829 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1831 SIVAL(p,0,reskey); p += 4;
1832 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1833 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1834 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1835 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1836 SOFF_T(p,0,file_size); p += 8;
1837 SOFF_T(p,0,allocation_size); p += 8;
1838 SIVAL(p,0,mode); p += 4;
1839 q = p; p += 4; /* q is placeholder for name length. */
1841 unsigned int ea_size = estimate_ea_size(conn, NULL,
1842 smb_fname->base_name);
1843 SIVAL(p,0,ea_size); /* Extended attributes */
1846 len = srvstr_push(base_data, flags2, p,
1847 fname, PTR_DIFF(end_data, p),
1848 STR_TERMINATE_ASCII);
1852 len = PTR_DIFF(p, pdata);
1853 pad = (len + (align-1)) & ~(align-1);
1855 * offset to the next entry, the caller
1856 * will overwrite it for the last entry
1857 * that's why we always include the padding
1861 * set padding to zero
1864 memset(p, 0, pad - len);
1871 case SMB_FIND_FILE_NAMES_INFO:
1872 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1874 SIVAL(p,0,reskey); p += 4;
1876 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1877 acl on a dir (tridge) */
1878 len = srvstr_push(base_data, flags2, p,
1879 fname, PTR_DIFF(end_data, p),
1880 STR_TERMINATE_ASCII);
1884 len = PTR_DIFF(p, pdata);
1885 pad = (len + (align-1)) & ~(align-1);
1887 * offset to the next entry, the caller
1888 * will overwrite it for the last entry
1889 * that's why we always include the padding
1893 * set padding to zero
1896 memset(p, 0, pad - len);
1903 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1906 SIVAL(p,0,reskey); p += 4;
1907 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1910 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1911 SOFF_T(p,0,file_size); p += 8;
1912 SOFF_T(p,0,allocation_size); p += 8;
1913 SIVAL(p,0,mode); p += 4;
1914 q = p; p += 4; /* q is placeholder for name length. */
1916 unsigned int ea_size = estimate_ea_size(conn, NULL,
1917 smb_fname->base_name);
1918 SIVAL(p,0,ea_size); /* Extended attributes */
1921 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1922 SBVAL(p,0,file_index); p += 8;
1923 len = srvstr_push(base_data, flags2, p,
1924 fname, PTR_DIFF(end_data, p),
1925 STR_TERMINATE_ASCII);
1929 len = PTR_DIFF(p, pdata);
1930 pad = (len + (align-1)) & ~(align-1);
1932 * offset to the next entry, the caller
1933 * will overwrite it for the last entry
1934 * that's why we always include the padding
1938 * set padding to zero
1941 memset(p, 0, pad - len);
1948 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1949 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1950 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1952 SIVAL(p,0,reskey); p += 4;
1953 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1954 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1955 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1956 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1957 SOFF_T(p,0,file_size); p += 8;
1958 SOFF_T(p,0,allocation_size); p += 8;
1959 SIVAL(p,0,mode); p += 4;
1960 q = p; p += 4; /* q is placeholder for name length */
1962 unsigned int ea_size = estimate_ea_size(conn, NULL,
1963 smb_fname->base_name);
1964 SIVAL(p,0,ea_size); /* Extended attributes */
1967 /* Clear the short name buffer. This is
1968 * IMPORTANT as not doing so will trigger
1969 * a Win2k client bug. JRA.
1971 if (!was_8_3 && check_mangled_names) {
1972 char mangled_name[13]; /* mangled 8.3 name. */
1973 if (!name_to_8_3(fname,mangled_name,True,
1975 /* Error - mangle failed ! */
1976 memset(mangled_name,'\0',12);
1978 mangled_name[12] = 0;
1979 len = srvstr_push(base_data, flags2,
1980 p+2, mangled_name, 24,
1981 STR_UPPER|STR_UNICODE);
1984 memset(p + 2 + len,'\0',24 - len);
1991 SSVAL(p,0,0); p += 2; /* Reserved ? */
1992 SBVAL(p,0,file_index); p += 8;
1993 len = srvstr_push(base_data, flags2, p,
1994 fname, PTR_DIFF(end_data, p),
1995 STR_TERMINATE_ASCII);
1999 len = PTR_DIFF(p, pdata);
2000 pad = (len + (align-1)) & ~(align-1);
2002 * offset to the next entry, the caller
2003 * will overwrite it for the last entry
2004 * that's why we always include the padding
2008 * set padding to zero
2011 memset(p, 0, pad - len);
2018 /* CIFS UNIX Extension. */
2020 case SMB_FIND_FILE_UNIX:
2021 case SMB_FIND_FILE_UNIX_INFO2:
2023 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2025 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2027 if (info_level == SMB_FIND_FILE_UNIX) {
2028 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2029 p = store_file_unix_basic(conn, p,
2030 NULL, &smb_fname->st);
2031 len = srvstr_push(base_data, flags2, p,
2032 fname, PTR_DIFF(end_data, p),
2035 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2036 p = store_file_unix_basic_info2(conn, p,
2037 NULL, &smb_fname->st);
2040 len = srvstr_push(base_data, flags2, p, fname,
2041 PTR_DIFF(end_data, p), 0);
2042 SIVAL(nameptr, 0, len);
2047 len = PTR_DIFF(p, pdata);
2048 pad = (len + (align-1)) & ~(align-1);
2050 * offset to the next entry, the caller
2051 * will overwrite it for the last entry
2052 * that's why we always include the padding
2056 * set padding to zero
2059 memset(p, 0, pad - len);
2064 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2072 if (PTR_DIFF(p,pdata) > space_remaining) {
2073 *out_of_space = true;
2074 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2075 "(wanted %u, had %d)\n",
2076 (unsigned int)PTR_DIFF(p,pdata),
2078 return false; /* Not finished - just out of space */
2081 /* Setup the last entry pointer, as an offset from base_data */
2082 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2083 /* Advance the data pointer to the next slot */
2089 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2090 connection_struct *conn,
2091 struct dptr_struct *dirptr,
2093 const char *path_mask,
2096 int requires_resume_key,
2104 int space_remaining,
2106 bool *got_exact_match,
2107 int *_last_entry_off,
2108 struct ea_list *name_list)
2111 const char *mask = NULL;
2112 long prev_dirpos = 0;
2115 struct smb_filename *smb_fname = NULL;
2116 struct smbd_dirptr_lanman2_state state;
2118 uint64_t last_entry_off = 0;
2122 state.info_level = info_level;
2123 state.check_mangled_names = lp_manglednames(conn->params);
2124 state.has_wild = dptr_has_wild(dirptr);
2125 state.got_exact_match = false;
2127 *out_of_space = false;
2128 *got_exact_match = false;
2130 p = strrchr_m(path_mask,'/');
2141 ok = smbd_dirptr_get_entry(ctx,
2147 smbd_dirptr_lanman2_match_fn,
2148 smbd_dirptr_lanman2_mode_fn,
2158 *got_exact_match = state.got_exact_match;
2160 ok = smbd_marshall_dir_entry(ctx,
2165 state.check_mangled_names,
2166 requires_resume_key,
2179 TALLOC_FREE(smb_fname);
2180 if (*out_of_space) {
2181 dptr_SeekDir(dirptr, prev_dirpos);
2188 *_last_entry_off = last_entry_off;
2192 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2193 connection_struct *conn,
2194 struct dptr_struct *dirptr,
2196 const char *path_mask,
2199 bool requires_resume_key,
2205 int space_remaining,
2207 bool *got_exact_match,
2208 int *last_entry_off,
2209 struct ea_list *name_list)
2212 const bool do_pad = true;
2214 if (info_level >= 1 && info_level <= 3) {
2215 /* No alignment on earlier info levels. */
2219 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2220 path_mask, dirtype, info_level,
2221 requires_resume_key, dont_descend, ask_sharemode,
2223 ppdata, base_data, end_data,
2225 out_of_space, got_exact_match,
2226 last_entry_off, name_list);
2229 /****************************************************************************
2230 Reply to a TRANS2_FINDFIRST.
2231 ****************************************************************************/
2233 static void call_trans2findfirst(connection_struct *conn,
2234 struct smb_request *req,
2235 char **pparams, int total_params,
2236 char **ppdata, int total_data,
2237 unsigned int max_data_bytes)
2239 /* We must be careful here that we don't return more than the
2240 allowed number of data bytes. If this means returning fewer than
2241 maxentries then so be it. We assume that the redirector has
2242 enough room for the fixed number of parameter bytes it has
2244 struct smb_filename *smb_dname = NULL;
2245 char *params = *pparams;
2246 char *pdata = *ppdata;
2250 uint16 findfirst_flags;
2251 bool close_after_first;
2253 bool requires_resume_key;
2255 char *directory = NULL;
2258 int last_entry_off=0;
2262 bool finished = False;
2263 bool dont_descend = False;
2264 bool out_of_space = False;
2265 int space_remaining;
2266 bool mask_contains_wcard = False;
2267 struct ea_list *ea_list = NULL;
2268 NTSTATUS ntstatus = NT_STATUS_OK;
2269 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2270 TALLOC_CTX *ctx = talloc_tos();
2271 struct dptr_struct *dirptr = NULL;
2272 struct smbd_server_connection *sconn = req->sconn;
2273 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2275 if (total_params < 13) {
2276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2280 dirtype = SVAL(params,0);
2281 maxentries = SVAL(params,2);
2282 findfirst_flags = SVAL(params,4);
2283 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2284 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2285 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2286 info_level = SVAL(params,6);
2288 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2289 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2290 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2291 info_level, max_data_bytes));
2294 /* W2K3 seems to treat zero as 1. */
2298 switch (info_level) {
2299 case SMB_FIND_INFO_STANDARD:
2300 case SMB_FIND_EA_SIZE:
2301 case SMB_FIND_EA_LIST:
2302 case SMB_FIND_FILE_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2304 case SMB_FIND_FILE_NAMES_INFO:
2305 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2306 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2307 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2309 case SMB_FIND_FILE_UNIX:
2310 case SMB_FIND_FILE_UNIX_INFO2:
2311 /* Always use filesystem for UNIX mtime query. */
2312 ask_sharemode = false;
2313 if (!lp_unix_extensions()) {
2314 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2317 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2320 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2324 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2325 params+12, total_params - 12,
2326 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2327 if (!NT_STATUS_IS_OK(ntstatus)) {
2328 reply_nterror(req, ntstatus);
2332 ntstatus = filename_convert(ctx, conn,
2333 req->flags2 & FLAGS2_DFS_PATHNAMES,
2336 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2337 &mask_contains_wcard,
2339 if (!NT_STATUS_IS_OK(ntstatus)) {
2340 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2341 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2342 ERRSRV, ERRbadpath);
2345 reply_nterror(req, ntstatus);
2349 mask = smb_dname->original_lcomp;
2351 directory = smb_dname->base_name;
2353 p = strrchr_m(directory,'/');
2355 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2356 if((directory[0] == '.') && (directory[1] == '\0')) {
2357 mask = talloc_strdup(ctx,"*");
2359 reply_nterror(req, NT_STATUS_NO_MEMORY);
2362 mask_contains_wcard = True;
2368 if (p == NULL || p == directory) {
2369 /* Ensure we don't have a directory name of "". */
2370 directory = talloc_strdup(talloc_tos(), ".");
2372 reply_nterror(req, NT_STATUS_NO_MEMORY);
2377 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2379 if (info_level == SMB_FIND_EA_LIST) {
2382 if (total_data < 4) {
2383 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2387 ea_size = IVAL(pdata,0);
2388 if (ea_size != total_data) {
2389 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2390 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2395 if (!lp_ea_support(SNUM(conn))) {
2396 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2400 /* Pull out the list of names. */
2401 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2408 *ppdata = (char *)SMB_REALLOC(
2409 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2410 if(*ppdata == NULL ) {
2411 reply_nterror(req, NT_STATUS_NO_MEMORY);
2415 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2417 /* Realloc the params space */
2418 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2419 if (*pparams == NULL) {
2420 reply_nterror(req, NT_STATUS_NO_MEMORY);
2425 /* Save the wildcard match and attribs we are using on this directory -
2426 needed as lanman2 assumes these are being saved between calls */
2428 ntstatus = dptr_create(conn,
2435 mask_contains_wcard,
2439 if (!NT_STATUS_IS_OK(ntstatus)) {
2440 reply_nterror(req, ntstatus);
2444 dptr_num = dptr_dnum(dirptr);
2445 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2447 /* Initialize per TRANS2_FIND_FIRST operation data */
2448 dptr_init_search_op(dirptr);
2450 /* We don't need to check for VOL here as this is returned by
2451 a different TRANS2 call. */
2453 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2454 directory,lp_dontdescend(SNUM(conn))));
2455 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2456 dont_descend = True;
2459 space_remaining = max_data_bytes;
2460 out_of_space = False;
2462 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2463 bool got_exact_match = False;
2465 /* this is a heuristic to avoid seeking the dirptr except when
2466 absolutely necessary. It allows for a filename of about 40 chars */
2467 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2468 out_of_space = True;
2471 finished = !get_lanman2_dir_entry(ctx,
2475 mask,dirtype,info_level,
2476 requires_resume_key,dont_descend,
2479 space_remaining, &out_of_space,
2481 &last_entry_off, ea_list);
2484 if (finished && out_of_space)
2487 if (!finished && !out_of_space)
2491 * As an optimisation if we know we aren't looking
2492 * for a wildcard name (ie. the name matches the wildcard exactly)
2493 * then we can finish on any (first) match.
2494 * This speeds up large directory searches. JRA.
2500 /* Ensure space_remaining never goes -ve. */
2501 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2502 space_remaining = 0;
2503 out_of_space = true;
2505 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2509 /* Check if we can close the dirptr */
2510 if(close_after_first || (finished && close_if_end)) {
2511 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2512 dptr_close(sconn, &dptr_num);
2516 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2517 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2518 * the protocol level is less than NT1. Tested with smbclient. JRA.
2519 * This should fix the OS/2 client bug #2335.
2522 if(numentries == 0) {
2523 dptr_close(sconn, &dptr_num);
2524 if (get_Protocol() < PROTOCOL_NT1) {
2525 reply_force_doserror(req, ERRDOS, ERRnofiles);
2528 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2529 ERRDOS, ERRbadfile);
2534 /* At this point pdata points to numentries directory entries. */
2536 /* Set up the return parameter block */
2537 SSVAL(params,0,dptr_num);
2538 SSVAL(params,2,numentries);
2539 SSVAL(params,4,finished);
2540 SSVAL(params,6,0); /* Never an EA error */
2541 SSVAL(params,8,last_entry_off);
2543 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2546 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2547 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2549 reply_nterror(req, NT_STATUS_NO_MEMORY);
2553 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2554 smb_fn_name(req->cmd),
2555 mask, directory, dirtype, numentries ) );
2558 * Force a name mangle here to ensure that the
2559 * mask as an 8.3 name is top of the mangled cache.
2560 * The reasons for this are subtle. Don't remove
2561 * this code unless you know what you are doing
2562 * (see PR#13758). JRA.
2565 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2566 char mangled_name[13];
2567 name_to_8_3(mask, mangled_name, True, conn->params);
2570 TALLOC_FREE(smb_dname);
2574 /****************************************************************************
2575 Reply to a TRANS2_FINDNEXT.
2576 ****************************************************************************/
2578 static void call_trans2findnext(connection_struct *conn,
2579 struct smb_request *req,
2580 char **pparams, int total_params,
2581 char **ppdata, int total_data,
2582 unsigned int max_data_bytes)
2584 /* We must be careful here that we don't return more than the
2585 allowed number of data bytes. If this means returning fewer than
2586 maxentries then so be it. We assume that the redirector has
2587 enough room for the fixed number of parameter bytes it has
2589 char *params = *pparams;
2590 char *pdata = *ppdata;
2596 uint16 findnext_flags;
2597 bool close_after_request;
2599 bool requires_resume_key;
2601 bool mask_contains_wcard = False;
2602 char *resume_name = NULL;
2603 const char *mask = NULL;
2604 const char *directory = NULL;
2608 int i, last_entry_off=0;
2609 bool finished = False;
2610 bool dont_descend = False;
2611 bool out_of_space = False;
2612 int space_remaining;
2613 struct ea_list *ea_list = NULL;
2614 NTSTATUS ntstatus = NT_STATUS_OK;
2615 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2616 TALLOC_CTX *ctx = talloc_tos();
2617 struct dptr_struct *dirptr;
2618 struct smbd_server_connection *sconn = req->sconn;
2620 if (total_params < 13) {
2621 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2625 dptr_num = SVAL(params,0);
2626 maxentries = SVAL(params,2);
2627 info_level = SVAL(params,4);
2628 resume_key = IVAL(params,6);
2629 findnext_flags = SVAL(params,10);
2630 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2631 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2632 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2633 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2635 if (!continue_bit) {
2636 /* We only need resume_name if continue_bit is zero. */
2637 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2639 total_params - 12, STR_TERMINATE, &ntstatus,
2640 &mask_contains_wcard);
2641 if (!NT_STATUS_IS_OK(ntstatus)) {
2642 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2643 complain (it thinks we're asking for the directory above the shared
2644 path or an invalid name). Catch this as the resume name is only compared, never used in
2645 a file access. JRA. */
2646 srvstr_pull_talloc(ctx, params, req->flags2,
2647 &resume_name, params+12,
2651 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2652 reply_nterror(req, ntstatus);
2658 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2659 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2660 resume_key = %d resume name = %s continue=%d level = %d\n",
2661 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2662 requires_resume_key, resume_key,
2663 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2666 /* W2K3 seems to treat zero as 1. */
2670 switch (info_level) {
2671 case SMB_FIND_INFO_STANDARD:
2672 case SMB_FIND_EA_SIZE:
2673 case SMB_FIND_EA_LIST:
2674 case SMB_FIND_FILE_DIRECTORY_INFO:
2675 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2676 case SMB_FIND_FILE_NAMES_INFO:
2677 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2678 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2679 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2681 case SMB_FIND_FILE_UNIX:
2682 case SMB_FIND_FILE_UNIX_INFO2:
2683 /* Always use filesystem for UNIX mtime query. */
2684 ask_sharemode = false;
2685 if (!lp_unix_extensions()) {
2686 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2691 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2695 if (info_level == SMB_FIND_EA_LIST) {
2698 if (total_data < 4) {
2699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2703 ea_size = IVAL(pdata,0);
2704 if (ea_size != total_data) {
2705 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2706 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2711 if (!lp_ea_support(SNUM(conn))) {
2712 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2716 /* Pull out the list of names. */
2717 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2724 *ppdata = (char *)SMB_REALLOC(
2725 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2726 if(*ppdata == NULL) {
2727 reply_nterror(req, NT_STATUS_NO_MEMORY);
2732 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2734 /* Realloc the params space */
2735 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2736 if(*pparams == NULL ) {
2737 reply_nterror(req, NT_STATUS_NO_MEMORY);
2743 /* Check that the dptr is valid */
2744 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2745 reply_nterror(req, STATUS_NO_MORE_FILES);
2749 directory = dptr_path(sconn, dptr_num);
2751 /* Get the wildcard mask from the dptr */
2752 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2753 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2754 reply_nterror(req, STATUS_NO_MORE_FILES);
2760 /* Get the attr mask from the dptr */
2761 dirtype = dptr_attr(sconn, dptr_num);
2763 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2764 dptr_num, mask, dirtype,
2766 dptr_TellDir(dirptr)));
2768 /* Initialize per TRANS2_FIND_NEXT operation data */
2769 dptr_init_search_op(dirptr);
2771 /* We don't need to check for VOL here as this is returned by
2772 a different TRANS2 call. */
2774 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2775 directory,lp_dontdescend(SNUM(conn))));
2776 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2777 dont_descend = True;
2780 space_remaining = max_data_bytes;
2781 out_of_space = False;
2784 * Seek to the correct position. We no longer use the resume key but
2785 * depend on the last file name instead.
2788 if(!continue_bit && resume_name && *resume_name) {
2791 long current_pos = 0;
2793 * Remember, name_to_8_3 is called by
2794 * get_lanman2_dir_entry(), so the resume name
2795 * could be mangled. Ensure we check the unmangled name.
2798 if (mangle_is_mangled(resume_name, conn->params)) {
2799 char *new_resume_name = NULL;
2800 mangle_lookup_name_from_8_3(ctx,
2804 if (new_resume_name) {
2805 resume_name = new_resume_name;
2810 * Fix for NT redirector problem triggered by resume key indexes
2811 * changing between directory scans. We now return a resume key of 0
2812 * and instead look for the filename to continue from (also given
2813 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2814 * findfirst/findnext (as is usual) then the directory pointer
2815 * should already be at the correct place.
2818 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2819 } /* end if resume_name && !continue_bit */
2821 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2822 bool got_exact_match = False;
2824 /* this is a heuristic to avoid seeking the dirptr except when
2825 absolutely necessary. It allows for a filename of about 40 chars */
2826 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2827 out_of_space = True;
2830 finished = !get_lanman2_dir_entry(ctx,
2834 mask,dirtype,info_level,
2835 requires_resume_key,dont_descend,
2838 space_remaining, &out_of_space,
2840 &last_entry_off, ea_list);
2843 if (finished && out_of_space)
2846 if (!finished && !out_of_space)
2850 * As an optimisation if we know we aren't looking
2851 * for a wildcard name (ie. the name matches the wildcard exactly)
2852 * then we can finish on any (first) match.
2853 * This speeds up large directory searches. JRA.
2859 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2862 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2863 smb_fn_name(req->cmd),
2864 mask, directory, dirtype, numentries ) );
2866 /* Check if we can close the dirptr */
2867 if(close_after_request || (finished && close_if_end)) {
2868 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2869 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2872 /* Set up the return parameter block */
2873 SSVAL(params,0,numentries);
2874 SSVAL(params,2,finished);
2875 SSVAL(params,4,0); /* Never an EA error */
2876 SSVAL(params,6,last_entry_off);
2878 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2884 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2886 E_md4hash(lp_servicename(SNUM(conn)),objid);
2890 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2892 SMB_ASSERT(extended_info != NULL);
2894 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2895 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2896 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2897 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2898 #ifdef SAMBA_VERSION_REVISION
2899 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2901 extended_info->samba_subversion = 0;
2902 #ifdef SAMBA_VERSION_RC_RELEASE
2903 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2905 #ifdef SAMBA_VERSION_PRE_RELEASE
2906 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2909 #ifdef SAMBA_VERSION_VENDOR_PATCH
2910 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2912 extended_info->samba_gitcommitdate = 0;
2913 #ifdef SAMBA_VERSION_COMMIT_TIME
2914 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2917 memset(extended_info->samba_version_string, 0,
2918 sizeof(extended_info->samba_version_string));
2920 snprintf (extended_info->samba_version_string,
2921 sizeof(extended_info->samba_version_string),
2922 "%s", samba_version_string());
2925 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2926 TALLOC_CTX *mem_ctx,
2927 uint16_t info_level,
2929 unsigned int max_data_bytes,
2933 char *pdata, *end_data;
2934 int data_len = 0, len;
2935 const char *vname = volume_label(SNUM(conn));
2936 int snum = SNUM(conn);
2937 char *fstype = lp_fstype(SNUM(conn));
2938 uint32 additional_flags = 0;
2939 struct smb_filename smb_fname_dot;
2943 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2944 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2945 "info level (0x%x) on IPC$.\n",
2946 (unsigned int)info_level));
2947 return NT_STATUS_ACCESS_DENIED;
2951 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2953 ZERO_STRUCT(smb_fname_dot);
2954 smb_fname_dot.base_name = discard_const_p(char, ".");
2956 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2957 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2958 return map_nt_error_from_unix(errno);
2961 st = smb_fname_dot.st;
2963 *ppdata = (char *)SMB_REALLOC(
2964 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2965 if (*ppdata == NULL) {
2966 return NT_STATUS_NO_MEMORY;
2970 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2971 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2973 switch (info_level) {
2974 case SMB_INFO_ALLOCATION:
2976 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2978 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2979 return map_nt_error_from_unix(errno);
2982 block_size = lp_block_size(snum);
2983 if (bsize < block_size) {
2984 uint64_t factor = block_size/bsize;
2989 if (bsize > block_size) {
2990 uint64_t factor = bsize/block_size;
2995 bytes_per_sector = 512;
2996 sectors_per_unit = bsize/bytes_per_sector;
2998 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2999 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3000 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3002 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3003 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3004 SIVAL(pdata,l1_cUnit,dsize);
3005 SIVAL(pdata,l1_cUnitAvail,dfree);
3006 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3010 case SMB_INFO_VOLUME:
3011 /* Return volume name */
3013 * Add volume serial number - hash of a combination of
3014 * the called hostname and the service name.
3016 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3018 * Win2k3 and previous mess this up by sending a name length
3019 * one byte short. I believe only older clients (OS/2 Win9x) use
3020 * this call so try fixing this by adding a terminating null to
3021 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3025 pdata+l2_vol_szVolLabel, vname,
3026 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3027 STR_NOALIGN|STR_TERMINATE);
3028 SCVAL(pdata,l2_vol_cch,len);
3029 data_len = l2_vol_szVolLabel + len;
3030 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3031 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3035 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3036 case SMB_FS_ATTRIBUTE_INFORMATION:
3038 additional_flags = 0;
3039 #if defined(HAVE_SYS_QUOTAS)
3040 additional_flags |= FILE_VOLUME_QUOTAS;
3043 if(lp_nt_acl_support(SNUM(conn))) {
3044 additional_flags |= FILE_PERSISTENT_ACLS;
3047 /* Capabilities are filled in at connection time through STATVFS call */
3048 additional_flags |= conn->fs_capabilities;
3049 additional_flags |= lp_parm_int(conn->params->service,
3050 "share", "fake_fscaps",
3053 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3054 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3055 additional_flags); /* FS ATTRIBUTES */
3057 SIVAL(pdata,4,255); /* Max filename component length */
3058 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3059 and will think we can't do long filenames */
3060 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3061 PTR_DIFF(end_data, pdata+12),
3064 data_len = 12 + len;
3067 case SMB_QUERY_FS_LABEL_INFO:
3068 case SMB_FS_LABEL_INFORMATION:
3069 len = srvstr_push(pdata, flags2, pdata+4, vname,
3070 PTR_DIFF(end_data, pdata+4), 0);
3075 case SMB_QUERY_FS_VOLUME_INFO:
3076 case SMB_FS_VOLUME_INFORMATION:
3079 * Add volume serial number - hash of a combination of
3080 * the called hostname and the service name.
3082 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3083 (str_checksum(get_local_machine_name())<<16));
3085 /* Max label len is 32 characters. */
3086 len = srvstr_push(pdata, flags2, pdata+18, vname,
3087 PTR_DIFF(end_data, pdata+18),
3089 SIVAL(pdata,12,len);
3092 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3093 (int)strlen(vname),vname, lp_servicename(snum)));
3096 case SMB_QUERY_FS_SIZE_INFO:
3097 case SMB_FS_SIZE_INFORMATION:
3099 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3101 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3102 return map_nt_error_from_unix(errno);
3104 block_size = lp_block_size(snum);
3105 if (bsize < block_size) {
3106 uint64_t factor = block_size/bsize;
3111 if (bsize > block_size) {
3112 uint64_t factor = bsize/block_size;
3117 bytes_per_sector = 512;
3118 sectors_per_unit = bsize/bytes_per_sector;
3119 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3120 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3121 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3122 SBIG_UINT(pdata,0,dsize);
3123 SBIG_UINT(pdata,8,dfree);
3124 SIVAL(pdata,16,sectors_per_unit);
3125 SIVAL(pdata,20,bytes_per_sector);
3129 case SMB_FS_FULL_SIZE_INFORMATION:
3131 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3133 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3134 return map_nt_error_from_unix(errno);
3136 block_size = lp_block_size(snum);
3137 if (bsize < block_size) {
3138 uint64_t factor = block_size/bsize;
3143 if (bsize > block_size) {
3144 uint64_t factor = bsize/block_size;
3149 bytes_per_sector = 512;
3150 sectors_per_unit = bsize/bytes_per_sector;
3151 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3152 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3153 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3154 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3155 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3156 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3157 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3158 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3162 case SMB_QUERY_FS_DEVICE_INFO:
3163 case SMB_FS_DEVICE_INFORMATION:
3165 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3167 if (!CAN_WRITE(conn)) {
3168 characteristics |= FILE_READ_ONLY_DEVICE;
3171 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3172 SIVAL(pdata,4,characteristics);
3176 #ifdef HAVE_SYS_QUOTAS
3177 case SMB_FS_QUOTA_INFORMATION:
3179 * what we have to send --metze:
3181 * Unknown1: 24 NULL bytes
3182 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3183 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3184 * Quota Flags: 2 byte :
3185 * Unknown3: 6 NULL bytes
3189 * details for Quota Flags:
3191 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3192 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3193 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3194 * 0x0001 Enable Quotas: enable quota for this fs
3198 /* we need to fake up a fsp here,
3199 * because its not send in this call
3202 SMB_NTQUOTA_STRUCT quotas;
3205 ZERO_STRUCT(quotas);
3211 if (get_current_uid(conn) != 0) {
3212 DEBUG(0,("set_user_quota: access_denied "
3213 "service [%s] user [%s]\n",
3214 lp_servicename(SNUM(conn)),
3215 conn->session_info->unix_info->unix_name));
3216 return NT_STATUS_ACCESS_DENIED;
3219 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3220 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3221 return map_nt_error_from_unix(errno);
3226 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3227 lp_servicename(SNUM(conn))));
3229 /* Unknown1 24 NULL bytes*/
3230 SBIG_UINT(pdata,0,(uint64_t)0);
3231 SBIG_UINT(pdata,8,(uint64_t)0);
3232 SBIG_UINT(pdata,16,(uint64_t)0);
3234 /* Default Soft Quota 8 bytes */
3235 SBIG_UINT(pdata,24,quotas.softlim);
3237 /* Default Hard Quota 8 bytes */
3238 SBIG_UINT(pdata,32,quotas.hardlim);
3240 /* Quota flag 2 bytes */
3241 SSVAL(pdata,40,quotas.qflags);
3243 /* Unknown3 6 NULL bytes */
3249 #endif /* HAVE_SYS_QUOTAS */
3250 case SMB_FS_OBJECTID_INFORMATION:
3252 unsigned char objid[16];
3253 struct smb_extended_info extended_info;
3254 memcpy(pdata,create_volume_objectid(conn, objid),16);
3255 samba_extended_info_version (&extended_info);
3256 SIVAL(pdata,16,extended_info.samba_magic);
3257 SIVAL(pdata,20,extended_info.samba_version);
3258 SIVAL(pdata,24,extended_info.samba_subversion);
3259 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3260 memcpy(pdata+36,extended_info.samba_version_string,28);
3266 * Query the version and capabilities of the CIFS UNIX extensions
3270 case SMB_QUERY_CIFS_UNIX_INFO:
3272 bool large_write = lp_min_receive_file_size() &&
3273 !srv_is_signing_active(conn->sconn);
3274 bool large_read = !srv_is_signing_active(conn->sconn);
3275 int encrypt_caps = 0;
3277 if (!lp_unix_extensions()) {
3278 return NT_STATUS_INVALID_LEVEL;
3281 switch (conn->encrypt_level) {
3287 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3290 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3291 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3292 large_write = false;
3298 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3299 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3301 /* We have POSIX ACLs, pathname, encryption,
3302 * large read/write, and locking capability. */
3304 SBIG_UINT(pdata,4,((uint64_t)(
3305 CIFS_UNIX_POSIX_ACLS_CAP|
3306 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3307 CIFS_UNIX_FCNTL_LOCKS_CAP|
3308 CIFS_UNIX_EXTATTR_CAP|
3309 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3311 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3313 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3317 case SMB_QUERY_POSIX_FS_INFO:
3320 vfs_statvfs_struct svfs;
3322 if (!lp_unix_extensions()) {
3323 return NT_STATUS_INVALID_LEVEL;
3326 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3330 SIVAL(pdata,0,svfs.OptimalTransferSize);
3331 SIVAL(pdata,4,svfs.BlockSize);
3332 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3333 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3334 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3335 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3336 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3337 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3338 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3340 } else if (rc == EOPNOTSUPP) {
3341 return NT_STATUS_INVALID_LEVEL;
3342 #endif /* EOPNOTSUPP */
3344 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3345 return NT_STATUS_DOS(ERRSRV, ERRerror);
3350 case SMB_QUERY_POSIX_WHOAMI:
3356 if (!lp_unix_extensions()) {
3357 return NT_STATUS_INVALID_LEVEL;
3360 if (max_data_bytes < 40) {
3361 return NT_STATUS_BUFFER_TOO_SMALL;
3364 /* We ARE guest if global_sid_Builtin_Guests is
3365 * in our list of SIDs.
3367 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3368 conn->session_info->security_token)) {
3369 flags |= SMB_WHOAMI_GUEST;
3372 /* We are NOT guest if global_sid_Authenticated_Users
3373 * is in our list of SIDs.
3375 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3376 conn->session_info->security_token)) {
3377 flags &= ~SMB_WHOAMI_GUEST;
3380 /* NOTE: 8 bytes for UID/GID, irrespective of native
3381 * platform size. This matches
3382 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3384 data_len = 4 /* flags */
3391 + 4 /* pad/reserved */
3392 + (conn->session_info->unix_token->ngroups * 8)
3394 + (conn->session_info->security_token->num_sids *
3398 SIVAL(pdata, 0, flags);
3399 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3401 (uint64_t)conn->session_info->unix_token->uid);
3402 SBIG_UINT(pdata, 16,
3403 (uint64_t)conn->session_info->unix_token->gid);
3406 if (data_len >= max_data_bytes) {
3407 /* Potential overflow, skip the GIDs and SIDs. */
3409 SIVAL(pdata, 24, 0); /* num_groups */
3410 SIVAL(pdata, 28, 0); /* num_sids */
3411 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3412 SIVAL(pdata, 36, 0); /* reserved */
3418 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3419 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3421 /* We walk the SID list twice, but this call is fairly
3422 * infrequent, and I don't expect that it's performance
3423 * sensitive -- jpeach
3425 for (i = 0, sid_bytes = 0;
3426 i < conn->session_info->security_token->num_sids; ++i) {
3427 sid_bytes += ndr_size_dom_sid(
3428 &conn->session_info->security_token->sids[i],
3432 /* SID list byte count */
3433 SIVAL(pdata, 32, sid_bytes);
3435 /* 4 bytes pad/reserved - must be zero */
3436 SIVAL(pdata, 36, 0);
3440 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3441 SBIG_UINT(pdata, data_len,
3442 (uint64_t)conn->session_info->unix_token->groups[i]);
3448 i < conn->session_info->security_token->num_sids; ++i) {
3449 int sid_len = ndr_size_dom_sid(
3450 &conn->session_info->security_token->sids[i],
3453 sid_linearize(pdata + data_len, sid_len,
3454 &conn->session_info->security_token->sids[i]);
3455 data_len += sid_len;
3461 case SMB_MAC_QUERY_FS_INFO:
3463 * Thursby MAC extension... ONLY on NTFS filesystems
3464 * once we do streams then we don't need this
3466 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3468 SIVAL(pdata,84,0x100); /* Don't support mac... */
3473 return NT_STATUS_INVALID_LEVEL;
3476 *ret_data_len = data_len;
3477 return NT_STATUS_OK;
3480 /****************************************************************************
3481 Reply to a TRANS2_QFSINFO (query filesystem info).
3482 ****************************************************************************/
3484 static void call_trans2qfsinfo(connection_struct *conn,
3485 struct smb_request *req,
3486 char **pparams, int total_params,
3487 char **ppdata, int total_data,
3488 unsigned int max_data_bytes)
3490 char *params = *pparams;
3491 uint16_t info_level;
3495 if (total_params < 2) {
3496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3500 info_level = SVAL(params,0);
3502 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3503 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3504 DEBUG(0,("call_trans2qfsinfo: encryption required "
3505 "and info level 0x%x sent.\n",
3506 (unsigned int)info_level));
3507 exit_server_cleanly("encryption required "
3513 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3515 status = smbd_do_qfsinfo(conn, req,
3520 if (!NT_STATUS_IS_OK(status)) {
3521 reply_nterror(req, status);
3525 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3528 DEBUG( 4, ( "%s info_level = %d\n",
3529 smb_fn_name(req->cmd), info_level) );
3534 /****************************************************************************
3535 Reply to a TRANS2_SETFSINFO (set filesystem info).
3536 ****************************************************************************/
3538 static void call_trans2setfsinfo(connection_struct *conn,
3539 struct smb_request *req,
3540 char **pparams, int total_params,
3541 char **ppdata, int total_data,
3542 unsigned int max_data_bytes)
3544 struct smbd_server_connection *sconn = req->sconn;
3545 char *pdata = *ppdata;
3546 char *params = *pparams;
3549 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3552 if (total_params < 4) {
3553 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3559 info_level = SVAL(params,2);
3562 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3563 info_level != SMB_SET_CIFS_UNIX_INFO) {
3564 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3565 "info level (0x%x) on IPC$.\n",
3566 (unsigned int)info_level));
3567 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3572 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3573 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3574 DEBUG(0,("call_trans2setfsinfo: encryption required "
3575 "and info level 0x%x sent.\n",
3576 (unsigned int)info_level));
3577 exit_server_cleanly("encryption required "
3583 switch(info_level) {
3584 case SMB_SET_CIFS_UNIX_INFO:
3585 if (!lp_unix_extensions()) {
3587 NT_STATUS_INVALID_LEVEL);
3591 /* There should be 12 bytes of capabilities set. */
3592 if (total_data < 8) {
3595 NT_STATUS_INVALID_PARAMETER);
3598 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3599 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3600 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3601 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3602 /* Just print these values for now. */
3603 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3604 "major = %u, minor = %u cap_low = 0x%x, "
3606 (unsigned int)sconn->
3607 smb1.unix_info.client_major,
3608 (unsigned int)sconn->
3609 smb1.unix_info.client_minor,
3610 (unsigned int)sconn->
3611 smb1.unix_info.client_cap_low,
3612 (unsigned int)sconn->
3613 smb1.unix_info.client_cap_high));
3615 /* Here is where we must switch to posix pathname processing... */
3616 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3617 lp_set_posix_pathnames();
3618 mangle_change_to_posix();
3621 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3622 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3623 /* Client that knows how to do posix locks,
3624 * but not posix open/mkdir operations. Set a
3625 * default type for read/write checks. */
3627 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3632 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3635 size_t param_len = 0;
3636 size_t data_len = total_data;
3638 if (!lp_unix_extensions()) {
3641 NT_STATUS_INVALID_LEVEL);
3645 if (lp_smb_encrypt(SNUM(conn)) == false) {
3648 NT_STATUS_NOT_SUPPORTED);
3652 if (req->sconn->smb1.echo_handler.trusted_fde) {
3653 DEBUG( 2,("call_trans2setfsinfo: "
3654 "request transport encryption disabled"
3655 "with 'fork echo handler = yes'\n"));
3658 NT_STATUS_NOT_SUPPORTED);
3662 DEBUG( 4,("call_trans2setfsinfo: "
3663 "request transport encryption.\n"));
3665 status = srv_request_encryption_setup(conn,
3666 (unsigned char **)ppdata,
3668 (unsigned char **)pparams,
3671 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3672 !NT_STATUS_IS_OK(status)) {
3673 reply_nterror(req, status);
3677 send_trans2_replies(conn, req,
3684 if (NT_STATUS_IS_OK(status)) {
3685 /* Server-side transport
3686 * encryption is now *on*. */
3687 status = srv_encryption_start(conn);
3688 if (!NT_STATUS_IS_OK(status)) {
3689 char *reason = talloc_asprintf(talloc_tos(),
3690 "Failure in setting "
3691 "up encrypted transport: %s",
3693 exit_server_cleanly(reason);
3699 case SMB_FS_QUOTA_INFORMATION:
3701 files_struct *fsp = NULL;
3702 SMB_NTQUOTA_STRUCT quotas;
3704 ZERO_STRUCT(quotas);
3707 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3708 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3709 lp_servicename(SNUM(conn)),
3710 conn->session_info->unix_info->unix_name));
3711 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3715 /* note: normaly there're 48 bytes,
3716 * but we didn't use the last 6 bytes for now
3719 fsp = file_fsp(req, SVAL(params,0));
3721 if (!check_fsp_ntquota_handle(conn, req,
3723 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3725 req, NT_STATUS_INVALID_HANDLE);
3729 if (total_data < 42) {
3730 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3734 NT_STATUS_INVALID_PARAMETER);
3738 /* unknown_1 24 NULL bytes in pdata*/
3740 /* the soft quotas 8 bytes (uint64_t)*/
3741 quotas.softlim = BVAL(pdata,24);
3743 /* the hard quotas 8 bytes (uint64_t)*/
3744 quotas.hardlim = BVAL(pdata,32);
3746 /* quota_flags 2 bytes **/
3747 quotas.qflags = SVAL(pdata,40);
3749 /* unknown_2 6 NULL bytes follow*/
3751 /* now set the quotas */
3752 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3753 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3754 reply_nterror(req, map_nt_error_from_unix(errno));
3761 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3763 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3769 * sending this reply works fine,
3770 * but I'm not sure it's the same
3771 * like windows do...
3774 reply_outbuf(req, 10, 0);
3777 #if defined(HAVE_POSIX_ACLS)
3778 /****************************************************************************
3779 Utility function to count the number of entries in a POSIX acl.
3780 ****************************************************************************/
3782 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3784 unsigned int ace_count = 0;
3785 int entry_id = SMB_ACL_FIRST_ENTRY;
3786 SMB_ACL_ENTRY_T entry;
3788 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3790 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3791 entry_id = SMB_ACL_NEXT_ENTRY;
3798 /****************************************************************************
3799 Utility function to marshall a POSIX acl into wire format.
3800 ****************************************************************************/
3802 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3804 int entry_id = SMB_ACL_FIRST_ENTRY;
3805 SMB_ACL_ENTRY_T entry;
3807 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3808 SMB_ACL_TAG_T tagtype;
3809 SMB_ACL_PERMSET_T permset;
3810 unsigned char perms = 0;
3811 unsigned int own_grp;
3814 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3815 entry_id = SMB_ACL_NEXT_ENTRY;
3818 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3819 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3823 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3824 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3828 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3829 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3830 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3832 SCVAL(pdata,1,perms);
3835 case SMB_ACL_USER_OBJ:
3836 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3837 own_grp = (unsigned int)pst->st_ex_uid;
3838 SIVAL(pdata,2,own_grp);
3843 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3845 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3848 own_grp = (unsigned int)*puid;
3849 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3850 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3851 SIVAL(pdata,2,own_grp);
3855 case SMB_ACL_GROUP_OBJ:
3856 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3857 own_grp = (unsigned int)pst->st_ex_gid;
3858 SIVAL(pdata,2,own_grp);
3863 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3865 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3868 own_grp = (unsigned int)*pgid;
3869 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3870 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3871 SIVAL(pdata,2,own_grp);
3876 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3877 SIVAL(pdata,2,0xFFFFFFFF);
3878 SIVAL(pdata,6,0xFFFFFFFF);
3881 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3882 SIVAL(pdata,2,0xFFFFFFFF);
3883 SIVAL(pdata,6,0xFFFFFFFF);
3886 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3889 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3896 /****************************************************************************
3897 Store the FILE_UNIX_BASIC info.
3898 ****************************************************************************/
3900 static char *store_file_unix_basic(connection_struct *conn,
3903 const SMB_STRUCT_STAT *psbuf)
3905 uint64_t file_index = get_FileIndex(conn, psbuf);
3907 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3908 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3910 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3913 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3916 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3917 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3918 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3921 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3925 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3929 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3932 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3936 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3940 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3943 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3947 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3954 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3955 * the chflags(2) (or equivalent) flags.
3957 * XXX: this really should be behind the VFS interface. To do this, we would
3958 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3959 * Each VFS module could then implement its own mapping as appropriate for the
3960 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3962 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3966 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3970 { UF_IMMUTABLE, EXT_IMMUTABLE },
3974 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3978 { UF_HIDDEN, EXT_HIDDEN },
3981 /* Do not remove. We need to guarantee that this array has at least one
3982 * entry to build on HP-UX.
3988 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3989 uint32 *smb_fflags, uint32 *smb_fmask)
3993 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3994 *smb_fmask |= info2_flags_map[i].smb_fflag;
3995 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3996 *smb_fflags |= info2_flags_map[i].smb_fflag;
4001 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4002 const uint32 smb_fflags,
4003 const uint32 smb_fmask,
4006 uint32 max_fmask = 0;
4009 *stat_fflags = psbuf->st_ex_flags;
4011 /* For each flags requested in smb_fmask, check the state of the
4012 * corresponding flag in smb_fflags and set or clear the matching
4016 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4017 max_fmask |= info2_flags_map[i].smb_fflag;
4018 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4019 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4020 *stat_fflags |= info2_flags_map[i].stat_fflag;
4022 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4027 /* If smb_fmask is asking to set any bits that are not supported by
4028 * our flag mappings, we should fail.
4030 if ((smb_fmask & max_fmask) != smb_fmask) {
4038 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4039 * of file flags and birth (create) time.
4041 static char *store_file_unix_basic_info2(connection_struct *conn,
4044 const SMB_STRUCT_STAT *psbuf)
4046 uint32 file_flags = 0;
4047 uint32 flags_mask = 0;
4049 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4051 /* Create (birth) time 64 bit */
4052 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4055 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4056 SIVAL(pdata, 0, file_flags); /* flags */
4057 SIVAL(pdata, 4, flags_mask); /* mask */
4063 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4064 const struct stream_struct *streams,
4066 unsigned int max_data_bytes,
4067 unsigned int *data_size)
4070 unsigned int ofs = 0;
4072 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4073 unsigned int next_offset;
4075 smb_ucs2_t *namebuf;
4077 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4078 streams[i].name, &namelen) ||
4081 return NT_STATUS_INVALID_PARAMETER;
4085 * name_buf is now null-terminated, we need to marshall as not
4091 SIVAL(data, ofs+4, namelen);
4092 SOFF_T(data, ofs+8, streams[i].size);
4093 SOFF_T(data, ofs+16, streams[i].alloc_size);
4094 memcpy(data+ofs+24, namebuf, namelen);
4095 TALLOC_FREE(namebuf);
4097 next_offset = ofs + 24 + namelen;
4099 if (i == num_streams-1) {
4100 SIVAL(data, ofs, 0);
4103 unsigned int align = ndr_align_size(next_offset, 8);
4105 memset(data+next_offset, 0, align);
4106 next_offset += align;
4108 SIVAL(data, ofs, next_offset - ofs);
4117 return NT_STATUS_OK;
4120 /****************************************************************************
4121 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4122 ****************************************************************************/
4124 static void call_trans2qpipeinfo(connection_struct *conn,
4125 struct smb_request *req,
4126 unsigned int tran_call,
4127 char **pparams, int total_params,
4128 char **ppdata, int total_data,
4129 unsigned int max_data_bytes)
4131 char *params = *pparams;
4132 char *pdata = *ppdata;
4133 unsigned int data_size = 0;
4134 unsigned int param_size = 2;
4139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4143 if (total_params < 4) {
4144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4148 fsp = file_fsp(req, SVAL(params,0));
4149 if (!fsp_is_np(fsp)) {
4150 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4154 info_level = SVAL(params,2);
4156 *pparams = (char *)SMB_REALLOC(*pparams,2);
4157 if (*pparams == NULL) {
4158 reply_nterror(req, NT_STATUS_NO_MEMORY);
4163 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4164 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4165 if (*ppdata == NULL ) {
4166 reply_nterror(req, NT_STATUS_NO_MEMORY);
4171 switch (info_level) {
4172 case SMB_FILE_STANDARD_INFORMATION:
4174 SOFF_T(pdata,0,4096LL);
4181 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4185 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4191 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4192 TALLOC_CTX *mem_ctx,
4193 uint16_t info_level,
4195 struct smb_filename *smb_fname,
4196 bool delete_pending,
4197 struct timespec write_time_ts,
4198 struct ea_list *ea_list,
4199 int lock_data_count,
4202 unsigned int max_data_bytes,
4204 unsigned int *pdata_size)
4206 char *pdata = *ppdata;
4207 char *dstart, *dend;
4208 unsigned int data_size;
4209 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4210 time_t create_time, mtime, atime, c_time;
4211 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4218 uint64_t file_size = 0;
4220 uint64_t allocation_size = 0;
4221 uint64_t file_index = 0;
4222 uint32_t access_mask = 0;
4224 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4225 return NT_STATUS_INVALID_LEVEL;
4228 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4229 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4230 info_level, max_data_bytes));
4232 mode = dos_mode(conn, smb_fname);
4233 nlink = psbuf->st_ex_nlink;
4235 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4239 if ((nlink > 0) && delete_pending) {
4243 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4244 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4245 if (*ppdata == NULL) {
4246 return NT_STATUS_NO_MEMORY;
4250 dend = dstart + data_size - 1;
4252 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4253 update_stat_ex_mtime(psbuf, write_time_ts);
4256 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4257 mtime_ts = psbuf->st_ex_mtime;
4258 atime_ts = psbuf->st_ex_atime;
4259 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4261 if (lp_dos_filetime_resolution(SNUM(conn))) {
4262 dos_filetime_timespec(&create_time_ts);
4263 dos_filetime_timespec(&mtime_ts);
4264 dos_filetime_timespec(&atime_ts);
4265 dos_filetime_timespec(&ctime_ts);
4268 create_time = convert_timespec_to_time_t(create_time_ts);
4269 mtime = convert_timespec_to_time_t(mtime_ts);
4270 atime = convert_timespec_to_time_t(atime_ts);
4271 c_time = convert_timespec_to_time_t(ctime_ts);
4273 p = strrchr_m(smb_fname->base_name,'/');
4275 base_name = smb_fname->base_name;
4279 /* NT expects the name to be in an exact form of the *full*
4280 filename. See the trans2 torture test */
4281 if (ISDOT(base_name)) {
4282 dos_fname = talloc_strdup(mem_ctx, "\\");
4284 return NT_STATUS_NO_MEMORY;
4287 dos_fname = talloc_asprintf(mem_ctx,
4289 smb_fname->base_name);
4291 return NT_STATUS_NO_MEMORY;
4293 if (is_ntfs_stream_smb_fname(smb_fname)) {
4294 dos_fname = talloc_asprintf(dos_fname, "%s",
4295 smb_fname->stream_name);
4297 return NT_STATUS_NO_MEMORY;
4301 string_replace(dos_fname, '/', '\\');
4304 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4307 /* Do we have this path open ? */
4309 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4310 fsp1 = file_find_di_first(conn->sconn, fileid);
4311 if (fsp1 && fsp1->initial_allocation_size) {
4312 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4316 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4317 file_size = get_file_size_stat(psbuf);
4321 pos = fsp->fh->position_information;
4325 access_mask = fsp->access_mask;
4327 /* GENERIC_EXECUTE mapping from Windows */
4328 access_mask = 0x12019F;
4331 /* This should be an index number - looks like
4334 I think this causes us to fail the IFSKIT
4335 BasicFileInformationTest. -tpot */
4336 file_index = get_FileIndex(conn, psbuf);
4338 switch (info_level) {
4339 case SMB_INFO_STANDARD:
4340 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4342 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4343 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4344 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4345 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4346 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4347 SSVAL(pdata,l1_attrFile,mode);
4350 case SMB_INFO_QUERY_EA_SIZE:
4352 unsigned int ea_size =
4353 estimate_ea_size(conn, fsp,
4354 smb_fname->base_name);
4355 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4357 srv_put_dos_date2(pdata,0,create_time);
4358 srv_put_dos_date2(pdata,4,atime);
4359 srv_put_dos_date2(pdata,8,mtime); /* write time */
4360 SIVAL(pdata,12,(uint32)file_size);
4361 SIVAL(pdata,16,(uint32)allocation_size);
4362 SSVAL(pdata,20,mode);
4363 SIVAL(pdata,22,ea_size);
4367 case SMB_INFO_IS_NAME_VALID:
4368 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4370 /* os/2 needs this ? really ?*/
4371 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4373 /* This is only reached for qpathinfo */
4377 case SMB_INFO_QUERY_EAS_FROM_LIST:
4379 size_t total_ea_len = 0;
4380 struct ea_list *ea_file_list = NULL;
4382 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4385 get_ea_list_from_file(mem_ctx, conn, fsp,
4386 smb_fname->base_name,
4388 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4390 if (!ea_list || (total_ea_len > data_size)) {
4392 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4396 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4400 case SMB_INFO_QUERY_ALL_EAS:
4402 /* We have data_size bytes to put EA's into. */
4403 size_t total_ea_len = 0;
4405 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4407 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4408 smb_fname->base_name,
4410 if (!ea_list || (total_ea_len > data_size)) {
4412 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4416 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4420 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4422 /* This is FileFullEaInformation - 0xF which maps to
4423 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4425 /* We have data_size bytes to put EA's into. */
4426 size_t total_ea_len = 0;
4427 struct ea_list *ea_file_list = NULL;
4429 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4431 /*TODO: add filtering and index handling */
4434 get_ea_list_from_file(mem_ctx, conn, fsp,
4435 smb_fname->base_name,
4437 if (!ea_file_list) {
4438 return NT_STATUS_NO_EAS_ON_FILE;
4441 status = fill_ea_chained_buffer(mem_ctx,
4445 conn, ea_file_list);
4446 if (!NT_STATUS_IS_OK(status)) {
4452 case SMB_FILE_BASIC_INFORMATION:
4453 case SMB_QUERY_FILE_BASIC_INFO:
4455 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4456 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4457 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4459 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4463 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4464 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4465 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4466 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4467 SIVAL(pdata,32,mode);
4469 DEBUG(5,("SMB_QFBI - "));
4470 DEBUG(5,("create: %s ", ctime(&create_time)));
4471 DEBUG(5,("access: %s ", ctime(&atime)));
4472 DEBUG(5,("write: %s ", ctime(&mtime)));
4473 DEBUG(5,("change: %s ", ctime(&c_time)));
4474 DEBUG(5,("mode: %x\n", mode));
4477 case SMB_FILE_STANDARD_INFORMATION:
4478 case SMB_QUERY_FILE_STANDARD_INFO:
4480 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4482 SOFF_T(pdata,0,allocation_size);
4483 SOFF_T(pdata,8,file_size);
4484 SIVAL(pdata,16,nlink);
4485 SCVAL(pdata,20,delete_pending?1:0);
4486 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4487 SSVAL(pdata,22,0); /* Padding. */
4490 case SMB_FILE_EA_INFORMATION:
4491 case SMB_QUERY_FILE_EA_INFO:
4493 unsigned int ea_size =
4494 estimate_ea_size(conn, fsp, smb_fname->base_name);
4495 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4497 SIVAL(pdata,0,ea_size);
4501 /* Get the 8.3 name - used if NT SMB was negotiated. */
4502 case SMB_QUERY_FILE_ALT_NAME_INFO:
4503 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4506 char mangled_name[13];
4507 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4508 if (!name_to_8_3(base_name,mangled_name,
4509 True,conn->params)) {
4510 return NT_STATUS_NO_MEMORY;
4512 len = srvstr_push(dstart, flags2,
4513 pdata+4, mangled_name,
4514 PTR_DIFF(dend, pdata+4),
4516 data_size = 4 + len;
4521 case SMB_QUERY_FILE_NAME_INFO:
4525 this must be *exactly* right for ACLs on mapped drives to work
4527 len = srvstr_push(dstart, flags2,
4529 PTR_DIFF(dend, pdata+4),
4531 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4532 data_size = 4 + len;
4537 case SMB_FILE_ALLOCATION_INFORMATION:
4538 case SMB_QUERY_FILE_ALLOCATION_INFO:
4539 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4541 SOFF_T(pdata,0,allocation_size);
4544 case SMB_FILE_END_OF_FILE_INFORMATION:
4545 case SMB_QUERY_FILE_END_OF_FILEINFO:
4546 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4548 SOFF_T(pdata,0,file_size);
4551 case SMB_QUERY_FILE_ALL_INFO:
4552 case SMB_FILE_ALL_INFORMATION:
4555 unsigned int ea_size =
4556 estimate_ea_size(conn, fsp, smb_fname->base_name);
4557 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4558 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4559 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4560 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4561 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4562 SIVAL(pdata,32,mode);
4563 SIVAL(pdata,36,0); /* padding. */
4565 SOFF_T(pdata,0,allocation_size);
4566 SOFF_T(pdata,8,file_size);
4567 SIVAL(pdata,16,nlink);
4568 SCVAL(pdata,20,delete_pending);
4569 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4572 SIVAL(pdata,0,ea_size);
4573 pdata += 4; /* EA info */
4574 len = srvstr_push(dstart, flags2,
4576 PTR_DIFF(dend, pdata+4),
4580 data_size = PTR_DIFF(pdata,(*ppdata));
4584 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4587 unsigned int ea_size =
4588 estimate_ea_size(conn, fsp, smb_fname->base_name);
4589 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4590 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4591 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4592 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4593 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4594 SIVAL(pdata, 0x20, mode);
4595 SIVAL(pdata, 0x24, 0); /* padding. */
4596 SBVAL(pdata, 0x28, allocation_size);
4597 SBVAL(pdata, 0x30, file_size);
4598 SIVAL(pdata, 0x38, nlink);
4599 SCVAL(pdata, 0x3C, delete_pending);
4600 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4601 SSVAL(pdata, 0x3E, 0); /* padding */
4602 SBVAL(pdata, 0x40, file_index);
4603 SIVAL(pdata, 0x48, ea_size);
4604 SIVAL(pdata, 0x4C, access_mask);
4605 SBVAL(pdata, 0x50, pos);
4606 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4607 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4611 len = srvstr_push(dstart, flags2,
4613 PTR_DIFF(dend, pdata+4),
4617 data_size = PTR_DIFF(pdata,(*ppdata));
4620 case SMB_FILE_INTERNAL_INFORMATION:
4622 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4623 SBVAL(pdata, 0, file_index);
4627 case SMB_FILE_ACCESS_INFORMATION:
4628 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4629 SIVAL(pdata, 0, access_mask);
4633 case SMB_FILE_NAME_INFORMATION:
4634 /* Pathname with leading '\'. */
4637 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4638 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4639 SIVAL(pdata,0,byte_len);
4640 data_size = 4 + byte_len;
4644 case SMB_FILE_DISPOSITION_INFORMATION:
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4647 SCVAL(pdata,0,delete_pending);
4650 case SMB_FILE_POSITION_INFORMATION:
4651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4653 SOFF_T(pdata,0,pos);
4656 case SMB_FILE_MODE_INFORMATION:
4657 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4658 SIVAL(pdata,0,mode);
4662 case SMB_FILE_ALIGNMENT_INFORMATION:
4663 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4664 SIVAL(pdata,0,0); /* No alignment needed. */
4669 * NT4 server just returns "invalid query" to this - if we try
4670 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4673 /* The first statement above is false - verified using Thursby
4674 * client against NT4 -- gcolley.
4676 case SMB_QUERY_FILE_STREAM_INFO:
4677 case SMB_FILE_STREAM_INFORMATION: {
4678 unsigned int num_streams = 0;
4679 struct stream_struct *streams = NULL;
4681 DEBUG(10,("smbd_do_qfilepathinfo: "
4682 "SMB_FILE_STREAM_INFORMATION\n"));
4684 if (is_ntfs_stream_smb_fname(smb_fname)) {
4685 return NT_STATUS_INVALID_PARAMETER;
4688 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4689 talloc_tos(), &num_streams, &streams);
4691 if (!NT_STATUS_IS_OK(status)) {
4692 DEBUG(10, ("could not get stream info: %s\n",
4693 nt_errstr(status)));
4697 status = marshall_stream_info(num_streams, streams,
4698 pdata, max_data_bytes,
4701 if (!NT_STATUS_IS_OK(status)) {
4702 DEBUG(10, ("marshall_stream_info failed: %s\n",
4703 nt_errstr(status)));
4707 TALLOC_FREE(streams);
4711 case SMB_QUERY_COMPRESSION_INFO:
4712 case SMB_FILE_COMPRESSION_INFORMATION:
4713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4714 SOFF_T(pdata,0,file_size);
4715 SIVAL(pdata,8,0); /* ??? */
4716 SIVAL(pdata,12,0); /* ??? */
4720 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4721 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4722 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4723 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4724 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4725 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4726 SOFF_T(pdata,32,allocation_size);
4727 SOFF_T(pdata,40,file_size);
4728 SIVAL(pdata,48,mode);
4729 SIVAL(pdata,52,0); /* ??? */
4733 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4735 SIVAL(pdata,0,mode);
4741 * CIFS UNIX Extensions.
4744 case SMB_QUERY_FILE_UNIX_BASIC:
4746 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4747 data_size = PTR_DIFF(pdata,(*ppdata));
4749 DEBUG(4,("smbd_do_qfilepathinfo: "
4750 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4751 dump_data(4, (uint8_t *)(*ppdata), data_size);
4755 case SMB_QUERY_FILE_UNIX_INFO2:
4757 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4758 data_size = PTR_DIFF(pdata,(*ppdata));
4762 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4764 for (i=0; i<100; i++)
4765 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4771 case SMB_QUERY_FILE_UNIX_LINK:
4774 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4777 return NT_STATUS_NO_MEMORY;
4780 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4782 if(!S_ISLNK(psbuf->st_ex_mode)) {
4783 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4786 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4788 len = SMB_VFS_READLINK(conn,
4789 smb_fname->base_name,
4792 return map_nt_error_from_unix(errno);
4795 len = srvstr_push(dstart, flags2,
4797 PTR_DIFF(dend, pdata),
4800 data_size = PTR_DIFF(pdata,(*ppdata));
4805 #if defined(HAVE_POSIX_ACLS)
4806 case SMB_QUERY_POSIX_ACL:
4808 SMB_ACL_T file_acl = NULL;
4809 SMB_ACL_T def_acl = NULL;
4810 uint16 num_file_acls = 0;
4811 uint16 num_def_acls = 0;
4813 if (fsp && fsp->fh->fd != -1) {
4814 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4817 SMB_VFS_SYS_ACL_GET_FILE(conn,
4818 smb_fname->base_name,
4819 SMB_ACL_TYPE_ACCESS);
4822 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4823 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4824 "not implemented on "
4825 "filesystem containing %s\n",
4826 smb_fname->base_name));
4827 return NT_STATUS_NOT_IMPLEMENTED;
4830 if (S_ISDIR(psbuf->st_ex_mode)) {
4831 if (fsp && fsp->is_directory) {
4833 SMB_VFS_SYS_ACL_GET_FILE(
4835 fsp->fsp_name->base_name,
4836 SMB_ACL_TYPE_DEFAULT);
4839 SMB_VFS_SYS_ACL_GET_FILE(
4841 smb_fname->base_name,
4842 SMB_ACL_TYPE_DEFAULT);
4844 def_acl = free_empty_sys_acl(conn, def_acl);
4847 num_file_acls = count_acl_entries(conn, file_acl);
4848 num_def_acls = count_acl_entries(conn, def_acl);
4850 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4851 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4853 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4854 SMB_POSIX_ACL_HEADER_SIZE) ));
4856 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4859 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4861 return NT_STATUS_BUFFER_TOO_SMALL;
4864 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4865 SSVAL(pdata,2,num_file_acls);
4866 SSVAL(pdata,4,num_def_acls);
4867 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4869 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4872 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4874 return NT_STATUS_INTERNAL_ERROR;
4876 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4878 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4881 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4883 return NT_STATUS_INTERNAL_ERROR;
4887 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4890 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4892 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4898 case SMB_QUERY_POSIX_LOCK:
4903 enum brl_type lock_type;
4905 /* We need an open file with a real fd for this. */
4906 if (!fsp || fsp->fh->fd == -1) {
4907 return NT_STATUS_INVALID_LEVEL;
4910 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4911 return NT_STATUS_INVALID_PARAMETER;
4914 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4915 case POSIX_LOCK_TYPE_READ:
4916 lock_type = READ_LOCK;
4918 case POSIX_LOCK_TYPE_WRITE:
4919 lock_type = WRITE_LOCK;
4921 case POSIX_LOCK_TYPE_UNLOCK:
4923 /* There's no point in asking for an unlock... */
4924 return NT_STATUS_INVALID_PARAMETER;
4927 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4928 #if defined(HAVE_LONGLONG)
4929 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4930 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4931 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4932 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4933 #else /* HAVE_LONGLONG */
4934 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4935 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4936 #endif /* HAVE_LONGLONG */
4938 status = query_lock(fsp,
4945 if (ERROR_WAS_LOCK_DENIED(status)) {
4946 /* Here we need to report who has it locked... */
4947 data_size = POSIX_LOCK_DATA_SIZE;
4949 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4950 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4951 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4952 #if defined(HAVE_LONGLONG)
4953 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4954 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4955 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4956 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4957 #else /* HAVE_LONGLONG */
4958 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4959 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4960 #endif /* HAVE_LONGLONG */
4962 } else if (NT_STATUS_IS_OK(status)) {
4963 /* For success we just return a copy of what we sent
4964 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4965 data_size = POSIX_LOCK_DATA_SIZE;
4966 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4967 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4975 return NT_STATUS_INVALID_LEVEL;
4978 *pdata_size = data_size;
4979 return NT_STATUS_OK;
4982 /****************************************************************************
4983 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4984 file name or file id).
4985 ****************************************************************************/
4987 static void call_trans2qfilepathinfo(connection_struct *conn,
4988 struct smb_request *req,
4989 unsigned int tran_call,
4990 char **pparams, int total_params,
4991 char **ppdata, int total_data,
4992 unsigned int max_data_bytes)
4994 char *params = *pparams;
4995 char *pdata = *ppdata;
4997 unsigned int data_size = 0;
4998 unsigned int param_size = 2;
4999 struct smb_filename *smb_fname = NULL;
5000 bool delete_pending = False;
5001 struct timespec write_time_ts;
5002 files_struct *fsp = NULL;
5003 struct file_id fileid;
5004 struct ea_list *ea_list = NULL;
5005 int lock_data_count = 0;
5006 char *lock_data = NULL;
5007 NTSTATUS status = NT_STATUS_OK;
5010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5014 ZERO_STRUCT(write_time_ts);
5016 if (tran_call == TRANSACT2_QFILEINFO) {
5017 if (total_params < 4) {
5018 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5023 call_trans2qpipeinfo(conn, req, tran_call,
5024 pparams, total_params,
5030 fsp = file_fsp(req, SVAL(params,0));
5031 info_level = SVAL(params,2);
5033 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5035 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5036 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5040 /* Initial check for valid fsp ptr. */
5041 if (!check_fsp_open(conn, req, fsp)) {
5045 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5047 if (!NT_STATUS_IS_OK(status)) {
5048 reply_nterror(req, status);
5052 if(fsp->fake_file_handle) {
5054 * This is actually for the QUOTA_FAKE_FILE --metze
5057 /* We know this name is ok, it's already passed the checks. */
5059 } else if(fsp->fh->fd == -1) {
5061 * This is actually a QFILEINFO on a directory
5062 * handle (returned from an NT SMB). NT5.0 seems
5063 * to do this call. JRA.
5066 if (INFO_LEVEL_IS_UNIX(info_level)) {
5067 /* Always do lstat for UNIX calls. */
5068 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5069 DEBUG(3,("call_trans2qfilepathinfo: "
5070 "SMB_VFS_LSTAT of %s failed "
5072 smb_fname_str_dbg(smb_fname),
5075 map_nt_error_from_unix(errno));
5078 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5079 DEBUG(3,("call_trans2qfilepathinfo: "
5080 "SMB_VFS_STAT of %s failed (%s)\n",
5081 smb_fname_str_dbg(smb_fname),
5084 map_nt_error_from_unix(errno));
5088 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5089 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5092 * Original code - this is an open file.
5094 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5095 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5096 fsp->fnum, strerror(errno)));
5098 map_nt_error_from_unix(errno));
5101 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5102 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5108 uint32_t ucf_flags = 0;
5111 if (total_params < 7) {
5112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5116 info_level = SVAL(params,0);
5118 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5120 if (INFO_LEVEL_IS_UNIX(info_level)) {
5121 if (!lp_unix_extensions()) {
5122 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5125 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5126 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5127 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5128 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5132 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5134 STR_TERMINATE, &status);
5135 if (!NT_STATUS_IS_OK(status)) {
5136 reply_nterror(req, status);
5140 status = filename_convert(req,
5142 req->flags2 & FLAGS2_DFS_PATHNAMES,
5147 if (!NT_STATUS_IS_OK(status)) {
5148 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5149 reply_botherror(req,
5150 NT_STATUS_PATH_NOT_COVERED,
5151 ERRSRV, ERRbadpath);
5154 reply_nterror(req, status);
5158 /* If this is a stream, check if there is a delete_pending. */
5159 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5160 && is_ntfs_stream_smb_fname(smb_fname)) {
5161 struct smb_filename *smb_fname_base = NULL;
5163 /* Create an smb_filename with stream_name == NULL. */
5165 create_synthetic_smb_fname(talloc_tos(),
5166 smb_fname->base_name,
5169 if (!NT_STATUS_IS_OK(status)) {
5170 reply_nterror(req, status);
5174 if (INFO_LEVEL_IS_UNIX(info_level)) {
5175 /* Always do lstat for UNIX calls. */
5176 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5177 DEBUG(3,("call_trans2qfilepathinfo: "
5178 "SMB_VFS_LSTAT of %s failed "
5180 smb_fname_str_dbg(smb_fname_base),
5182 TALLOC_FREE(smb_fname_base);
5184 map_nt_error_from_unix(errno));
5188 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5189 DEBUG(3,("call_trans2qfilepathinfo: "
5190 "fileinfo of %s failed "
5192 smb_fname_str_dbg(smb_fname_base),
5194 TALLOC_FREE(smb_fname_base);
5196 map_nt_error_from_unix(errno));
5201 status = file_name_hash(conn,
5202 smb_fname_str_dbg(smb_fname_base),
5204 if (!NT_STATUS_IS_OK(status)) {
5205 TALLOC_FREE(smb_fname_base);
5206 reply_nterror(req, status);
5210 fileid = vfs_file_id_from_sbuf(conn,
5211 &smb_fname_base->st);
5212 TALLOC_FREE(smb_fname_base);
5213 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5214 if (delete_pending) {
5215 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5220 if (INFO_LEVEL_IS_UNIX(info_level)) {
5221 /* Always do lstat for UNIX calls. */
5222 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5223 DEBUG(3,("call_trans2qfilepathinfo: "
5224 "SMB_VFS_LSTAT of %s failed (%s)\n",
5225 smb_fname_str_dbg(smb_fname),
5228 map_nt_error_from_unix(errno));
5233 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5234 DEBUG(3,("call_trans2qfilepathinfo: "
5235 "SMB_VFS_STAT of %s failed (%s)\n",
5236 smb_fname_str_dbg(smb_fname),
5239 map_nt_error_from_unix(errno));
5244 status = file_name_hash(conn,
5245 smb_fname_str_dbg(smb_fname),
5247 if (!NT_STATUS_IS_OK(status)) {
5248 reply_nterror(req, status);
5252 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5253 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5254 if (delete_pending) {
5255 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5260 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5261 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5262 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5264 /* Pull out any data sent here before we realloc. */
5265 switch (info_level) {
5266 case SMB_INFO_QUERY_EAS_FROM_LIST:
5268 /* Pull any EA list from the data portion. */
5271 if (total_data < 4) {
5273 req, NT_STATUS_INVALID_PARAMETER);
5276 ea_size = IVAL(pdata,0);
5278 if (total_data > 0 && ea_size != total_data) {
5279 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5280 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5282 req, NT_STATUS_INVALID_PARAMETER);
5286 if (!lp_ea_support(SNUM(conn))) {
5287 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5291 /* Pull out the list of names. */
5292 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5295 req, NT_STATUS_INVALID_PARAMETER);
5301 case SMB_QUERY_POSIX_LOCK:
5303 if (fsp == NULL || fsp->fh->fd == -1) {
5304 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5308 if (total_data != POSIX_LOCK_DATA_SIZE) {
5310 req, NT_STATUS_INVALID_PARAMETER);
5314 /* Copy the lock range data. */
5315 lock_data = (char *)talloc_memdup(
5316 req, pdata, total_data);
5318 reply_nterror(req, NT_STATUS_NO_MEMORY);
5321 lock_data_count = total_data;
5327 *pparams = (char *)SMB_REALLOC(*pparams,2);
5328 if (*pparams == NULL) {
5329 reply_nterror(req, NT_STATUS_NO_MEMORY);
5336 * draft-leach-cifs-v1-spec-02.txt
5337 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5340 * The requested information is placed in the Data portion of the
5341 * transaction response. For the information levels greater than 0x100,
5342 * the transaction response has 1 parameter word which should be
5343 * ignored by the client.
5345 * However Windows only follows this rule for the IS_NAME_VALID call.
5347 switch (info_level) {
5348 case SMB_INFO_IS_NAME_VALID:
5353 if ((info_level & 0xFF00) == 0xFF00) {
5355 * We use levels that start with 0xFF00
5356 * internally to represent SMB2 specific levels
5358 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5362 status = smbd_do_qfilepathinfo(conn, req, info_level,
5364 delete_pending, write_time_ts,
5366 lock_data_count, lock_data,
5367 req->flags2, max_data_bytes,
5368 ppdata, &data_size);
5369 if (!NT_STATUS_IS_OK(status)) {
5370 reply_nterror(req, status);
5374 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5380 /****************************************************************************
5381 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5383 ****************************************************************************/
5385 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5386 connection_struct *conn,
5387 struct smb_request *req,
5388 bool overwrite_if_exists,
5389 const struct smb_filename *smb_fname_old,
5390 struct smb_filename *smb_fname_new)
5392 NTSTATUS status = NT_STATUS_OK;
5394 /* source must already exist. */
5395 if (!VALID_STAT(smb_fname_old->st)) {
5396 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5399 if (VALID_STAT(smb_fname_new->st)) {
5400 if (overwrite_if_exists) {
5401 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5402 return NT_STATUS_FILE_IS_A_DIRECTORY;
5404 status = unlink_internals(conn,
5406 FILE_ATTRIBUTE_NORMAL,
5409 if (!NT_STATUS_IS_OK(status)) {
5413 /* Disallow if newname already exists. */
5414 return NT_STATUS_OBJECT_NAME_COLLISION;
5418 /* No links from a directory. */
5419 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5420 return NT_STATUS_FILE_IS_A_DIRECTORY;
5423 /* Setting a hardlink to/from a stream isn't currently supported. */
5424 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5425 is_ntfs_stream_smb_fname(smb_fname_new)) {
5426 return NT_STATUS_INVALID_PARAMETER;
5429 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5430 smb_fname_old->base_name, smb_fname_new->base_name));
5432 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5433 smb_fname_new->base_name) != 0) {
5434 status = map_nt_error_from_unix(errno);
5435 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5436 nt_errstr(status), smb_fname_old->base_name,
5437 smb_fname_new->base_name));
5442 /****************************************************************************
5443 Deal with setting the time from any of the setfilepathinfo functions.
5444 ****************************************************************************/
5446 NTSTATUS smb_set_file_time(connection_struct *conn,
5448 const struct smb_filename *smb_fname,
5449 struct smb_file_time *ft,
5450 bool setting_write_time)
5452 struct smb_filename smb_fname_base;
5454 FILE_NOTIFY_CHANGE_LAST_ACCESS
5455 |FILE_NOTIFY_CHANGE_LAST_WRITE
5456 |FILE_NOTIFY_CHANGE_CREATION;
5458 if (!VALID_STAT(smb_fname->st)) {
5459 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5462 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5463 return NT_STATUS_ACCESS_DENIED;
5466 /* get some defaults (no modifications) if any info is zero or -1. */
5467 if (null_timespec(ft->create_time)) {
5468 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5471 if (null_timespec(ft->atime)) {
5472 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5475 if (null_timespec(ft->mtime)) {
5476 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5479 if (!setting_write_time) {
5480 /* ft->mtime comes from change time, not write time. */
5481 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5484 /* Ensure the resolution is the correct for
5485 * what we can store on this filesystem. */
5487 round_timespec(conn->ts_res, &ft->create_time);
5488 round_timespec(conn->ts_res, &ft->ctime);
5489 round_timespec(conn->ts_res, &ft->atime);
5490 round_timespec(conn->ts_res, &ft->mtime);
5492 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5493 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5494 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5495 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5496 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5497 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5498 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5499 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5501 if (setting_write_time) {
5503 * This was a Windows setfileinfo on an open file.
5504 * NT does this a lot. We also need to
5505 * set the time here, as it can be read by
5506 * FindFirst/FindNext and with the patch for bug #2045
5507 * in smbd/fileio.c it ensures that this timestamp is
5508 * kept sticky even after a write. We save the request
5509 * away and will set it on file close and after a write. JRA.
5512 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5513 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5516 if (fsp->base_fsp) {
5517 set_sticky_write_time_fsp(fsp->base_fsp,
5520 set_sticky_write_time_fsp(fsp, ft->mtime);
5523 set_sticky_write_time_path(
5524 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5529 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5531 /* Always call ntimes on the base, even if a stream was passed in. */
5532 smb_fname_base = *smb_fname;
5533 smb_fname_base.stream_name = NULL;
5535 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5536 return map_nt_error_from_unix(errno);
5539 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5540 smb_fname->base_name);
5541 return NT_STATUS_OK;
5544 /****************************************************************************
5545 Deal with setting the dosmode from any of the setfilepathinfo functions.
5546 ****************************************************************************/
5548 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5549 const struct smb_filename *smb_fname,
5552 struct smb_filename *smb_fname_base = NULL;
5555 if (!VALID_STAT(smb_fname->st)) {
5556 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5559 /* Always operate on the base_name, even if a stream was passed in. */
5560 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5561 NULL, &smb_fname->st,
5563 if (!NT_STATUS_IS_OK(status)) {
5568 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5569 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5571 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5575 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5577 /* check the mode isn't different, before changing it */
5578 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5579 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5580 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5581 (unsigned int)dosmode));
5583 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5585 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5587 smb_fname_str_dbg(smb_fname_base),
5589 status = map_nt_error_from_unix(errno);
5593 status = NT_STATUS_OK;
5595 TALLOC_FREE(smb_fname_base);
5599 /****************************************************************************
5600 Deal with setting the size from any of the setfilepathinfo functions.
5601 ****************************************************************************/
5603 static NTSTATUS smb_set_file_size(connection_struct *conn,
5604 struct smb_request *req,
5606 const struct smb_filename *smb_fname,
5607 const SMB_STRUCT_STAT *psbuf,
5609 bool fail_after_createfile)
5611 NTSTATUS status = NT_STATUS_OK;
5612 struct smb_filename *smb_fname_tmp = NULL;
5613 files_struct *new_fsp = NULL;
5615 if (!VALID_STAT(*psbuf)) {
5616 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5619 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5620 return NT_STATUS_ACCESS_DENIED;
5623 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5625 if (size == get_file_size_stat(psbuf)) {
5626 return NT_STATUS_OK;
5629 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5630 smb_fname_str_dbg(smb_fname), (double)size));
5632 if (fsp && fsp->fh->fd != -1) {
5633 /* Handle based call. */
5634 if (vfs_set_filelen(fsp, size) == -1) {
5635 return map_nt_error_from_unix(errno);
5637 trigger_write_time_update_immediate(fsp);
5638 return NT_STATUS_OK;
5641 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5642 if (!NT_STATUS_IS_OK(status)) {
5646 smb_fname_tmp->st = *psbuf;
5648 status = SMB_VFS_CREATE_FILE(
5651 0, /* root_dir_fid */
5652 smb_fname_tmp, /* fname */
5653 FILE_WRITE_DATA, /* access_mask */
5654 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5656 FILE_OPEN, /* create_disposition*/
5657 0, /* create_options */
5658 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5659 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5660 0, /* allocation_size */
5661 0, /* private_flags */
5664 &new_fsp, /* result */
5667 TALLOC_FREE(smb_fname_tmp);
5669 if (!NT_STATUS_IS_OK(status)) {
5670 /* NB. We check for open_was_deferred in the caller. */
5674 /* See RAW-SFILEINFO-END-OF-FILE */
5675 if (fail_after_createfile) {
5676 close_file(req, new_fsp,NORMAL_CLOSE);
5677 return NT_STATUS_INVALID_LEVEL;
5680 if (vfs_set_filelen(new_fsp, size) == -1) {
5681 status = map_nt_error_from_unix(errno);
5682 close_file(req, new_fsp,NORMAL_CLOSE);
5686 trigger_write_time_update_immediate(new_fsp);
5687 close_file(req, new_fsp,NORMAL_CLOSE);
5688 return NT_STATUS_OK;
5691 /****************************************************************************
5692 Deal with SMB_INFO_SET_EA.
5693 ****************************************************************************/
5695 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5699 const struct smb_filename *smb_fname)
5701 struct ea_list *ea_list = NULL;
5702 TALLOC_CTX *ctx = NULL;
5703 NTSTATUS status = NT_STATUS_OK;
5705 if (total_data < 10) {
5707 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5708 length. They seem to have no effect. Bug #3212. JRA */
5710 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5711 /* We're done. We only get EA info in this call. */
5712 return NT_STATUS_OK;
5715 return NT_STATUS_INVALID_PARAMETER;
5718 if (IVAL(pdata,0) > total_data) {
5719 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5720 IVAL(pdata,0), (unsigned int)total_data));
5721 return NT_STATUS_INVALID_PARAMETER;
5725 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5727 return NT_STATUS_INVALID_PARAMETER;
5730 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5731 return NT_STATUS_ACCESS_DENIED;
5734 status = set_ea(conn, fsp, smb_fname, ea_list);
5739 /****************************************************************************
5740 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5741 ****************************************************************************/
5743 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5748 struct ea_list *ea_list = NULL;
5752 return NT_STATUS_INVALID_HANDLE;
5755 if (!lp_ea_support(SNUM(conn))) {
5756 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5757 "EA's not supported.\n",
5758 (unsigned int)total_data));
5759 return NT_STATUS_EAS_NOT_SUPPORTED;
5762 if (total_data < 10) {
5763 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5765 (unsigned int)total_data));
5766 return NT_STATUS_INVALID_PARAMETER;
5769 ea_list = read_nttrans_ea_list(talloc_tos(),
5774 return NT_STATUS_INVALID_PARAMETER;
5777 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5778 return NT_STATUS_ACCESS_DENIED;
5781 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5783 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5784 smb_fname_str_dbg(fsp->fsp_name),
5785 nt_errstr(status) ));
5791 /****************************************************************************
5792 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5793 ****************************************************************************/
5795 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5799 struct smb_filename *smb_fname)
5801 NTSTATUS status = NT_STATUS_OK;
5802 bool delete_on_close;
5805 if (total_data < 1) {
5806 return NT_STATUS_INVALID_PARAMETER;
5810 return NT_STATUS_INVALID_HANDLE;
5813 delete_on_close = (CVAL(pdata,0) ? True : False);
5814 dosmode = dos_mode(conn, smb_fname);
5816 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5817 "delete_on_close = %u\n",
5818 smb_fname_str_dbg(smb_fname),
5819 (unsigned int)dosmode,
5820 (unsigned int)delete_on_close ));
5822 if (delete_on_close) {
5823 status = can_set_delete_on_close(fsp, dosmode);
5824 if (!NT_STATUS_IS_OK(status)) {
5829 /* The set is across all open files on this dev/inode pair. */
5830 if (!set_delete_on_close(fsp, delete_on_close,
5831 conn->session_info->unix_token)) {
5832 return NT_STATUS_ACCESS_DENIED;
5834 return NT_STATUS_OK;
5837 /****************************************************************************
5838 Deal with SMB_FILE_POSITION_INFORMATION.
5839 ****************************************************************************/
5841 static NTSTATUS smb_file_position_information(connection_struct *conn,
5846 uint64_t position_information;
5848 if (total_data < 8) {
5849 return NT_STATUS_INVALID_PARAMETER;
5853 /* Ignore on pathname based set. */
5854 return NT_STATUS_OK;
5857 position_information = (uint64_t)IVAL(pdata,0);
5858 #ifdef LARGE_SMB_OFF_T
5859 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5860 #else /* LARGE_SMB_OFF_T */
5861 if (IVAL(pdata,4) != 0) {
5862 /* more than 32 bits? */
5863 return NT_STATUS_INVALID_PARAMETER;
5865 #endif /* LARGE_SMB_OFF_T */
5867 DEBUG(10,("smb_file_position_information: Set file position "
5868 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5869 (double)position_information));
5870 fsp->fh->position_information = position_information;
5871 return NT_STATUS_OK;
5874 /****************************************************************************
5875 Deal with SMB_FILE_MODE_INFORMATION.
5876 ****************************************************************************/
5878 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5884 if (total_data < 4) {
5885 return NT_STATUS_INVALID_PARAMETER;
5887 mode = IVAL(pdata,0);
5888 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5889 return NT_STATUS_INVALID_PARAMETER;
5891 return NT_STATUS_OK;
5894 /****************************************************************************
5895 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5896 ****************************************************************************/
5898 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5899 struct smb_request *req,
5902 const struct smb_filename *smb_fname)
5904 char *link_target = NULL;
5905 const char *newname = smb_fname->base_name;
5906 TALLOC_CTX *ctx = talloc_tos();
5908 /* Set a symbolic link. */
5909 /* Don't allow this if follow links is false. */
5911 if (total_data == 0) {
5912 return NT_STATUS_INVALID_PARAMETER;
5915 if (!lp_symlinks(SNUM(conn))) {
5916 return NT_STATUS_ACCESS_DENIED;
5919 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5920 total_data, STR_TERMINATE);
5923 return NT_STATUS_INVALID_PARAMETER;
5926 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5927 newname, link_target ));
5929 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5930 return map_nt_error_from_unix(errno);
5933 return NT_STATUS_OK;
5936 /****************************************************************************
5937 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5938 ****************************************************************************/
5940 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5941 struct smb_request *req,
5942 const char *pdata, int total_data,
5943 struct smb_filename *smb_fname_new)
5945 char *oldname = NULL;
5946 struct smb_filename *smb_fname_old = NULL;
5947 TALLOC_CTX *ctx = talloc_tos();
5948 NTSTATUS status = NT_STATUS_OK;
5950 /* Set a hard link. */
5951 if (total_data == 0) {
5952 return NT_STATUS_INVALID_PARAMETER;
5955 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5956 total_data, STR_TERMINATE, &status);
5957 if (!NT_STATUS_IS_OK(status)) {
5961 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5962 smb_fname_str_dbg(smb_fname_new), oldname));
5964 status = filename_convert(ctx,
5966 req->flags2 & FLAGS2_DFS_PATHNAMES,
5971 if (!NT_STATUS_IS_OK(status)) {
5975 return hardlink_internals(ctx, conn, req, false,
5976 smb_fname_old, smb_fname_new);
5979 /****************************************************************************
5980 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5981 ****************************************************************************/
5983 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5984 struct smb_request *req,
5988 struct smb_filename *smb_fname_src)
5992 char *newname = NULL;
5993 struct smb_filename *smb_fname_dst = NULL;
5994 NTSTATUS status = NT_STATUS_OK;
5995 TALLOC_CTX *ctx = talloc_tos();
5998 return NT_STATUS_INVALID_HANDLE;
6001 if (total_data < 20) {
6002 return NT_STATUS_INVALID_PARAMETER;
6005 overwrite = (CVAL(pdata,0) ? True : False);
6006 len = IVAL(pdata,16);
6008 if (len > (total_data - 20) || (len == 0)) {
6009 return NT_STATUS_INVALID_PARAMETER;
6012 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6013 &pdata[20], len, STR_TERMINATE,
6015 if (!NT_STATUS_IS_OK(status)) {
6019 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6022 status = filename_convert(ctx,
6024 req->flags2 & FLAGS2_DFS_PATHNAMES,
6029 if (!NT_STATUS_IS_OK(status)) {
6033 if (fsp->base_fsp) {
6034 /* newname must be a stream name. */
6035 if (newname[0] != ':') {
6036 return NT_STATUS_NOT_SUPPORTED;
6039 /* Create an smb_fname to call rename_internals_fsp() with. */
6040 status = create_synthetic_smb_fname(talloc_tos(),
6041 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6043 if (!NT_STATUS_IS_OK(status)) {
6048 * Set the original last component, since
6049 * rename_internals_fsp() requires it.
6051 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6053 if (smb_fname_dst->original_lcomp == NULL) {
6054 status = NT_STATUS_NO_MEMORY;
6060 DEBUG(10,("smb2_file_rename_information: "
6061 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6062 fsp->fnum, fsp_str_dbg(fsp),
6063 smb_fname_str_dbg(smb_fname_dst)));
6064 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6065 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6069 TALLOC_FREE(smb_fname_dst);
6073 static NTSTATUS smb_file_link_information(connection_struct *conn,
6074 struct smb_request *req,
6078 struct smb_filename *smb_fname_src)
6082 char *newname = NULL;
6083 struct smb_filename *smb_fname_dst = NULL;
6084 NTSTATUS status = NT_STATUS_OK;
6085 TALLOC_CTX *ctx = talloc_tos();
6088 return NT_STATUS_INVALID_HANDLE;
6091 if (total_data < 20) {
6092 return NT_STATUS_INVALID_PARAMETER;
6095 overwrite = (CVAL(pdata,0) ? true : false);
6096 len = IVAL(pdata,16);
6098 if (len > (total_data - 20) || (len == 0)) {
6099 return NT_STATUS_INVALID_PARAMETER;
6102 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6103 &pdata[20], len, STR_TERMINATE,
6105 if (!NT_STATUS_IS_OK(status)) {
6109 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6112 status = filename_convert(ctx,
6114 req->flags2 & FLAGS2_DFS_PATHNAMES,
6119 if (!NT_STATUS_IS_OK(status)) {
6123 if (fsp->base_fsp) {
6124 /* No stream names. */
6125 return NT_STATUS_NOT_SUPPORTED;
6128 DEBUG(10,("smb_file_link_information: "
6129 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6130 fsp->fnum, fsp_str_dbg(fsp),
6131 smb_fname_str_dbg(smb_fname_dst)));
6132 status = hardlink_internals(ctx,
6139 TALLOC_FREE(smb_fname_dst);
6143 /****************************************************************************
6144 Deal with SMB_FILE_RENAME_INFORMATION.
6145 ****************************************************************************/
6147 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6148 struct smb_request *req,
6152 struct smb_filename *smb_fname_src)
6157 char *newname = NULL;
6158 struct smb_filename *smb_fname_dst = NULL;
6159 bool dest_has_wcard = False;
6160 NTSTATUS status = NT_STATUS_OK;
6162 TALLOC_CTX *ctx = talloc_tos();
6164 if (total_data < 13) {
6165 return NT_STATUS_INVALID_PARAMETER;
6168 overwrite = (CVAL(pdata,0) ? True : False);
6169 root_fid = IVAL(pdata,4);
6170 len = IVAL(pdata,8);
6172 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6173 return NT_STATUS_INVALID_PARAMETER;
6176 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6179 if (!NT_STATUS_IS_OK(status)) {
6183 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6186 status = resolve_dfspath_wcard(ctx, conn,
6187 req->flags2 & FLAGS2_DFS_PATHNAMES,
6192 if (!NT_STATUS_IS_OK(status)) {
6196 /* Check the new name has no '/' characters. */
6197 if (strchr_m(newname, '/')) {
6198 return NT_STATUS_NOT_SUPPORTED;
6201 if (fsp && fsp->base_fsp) {
6202 /* newname must be a stream name. */
6203 if (newname[0] != ':') {
6204 return NT_STATUS_NOT_SUPPORTED;
6207 /* Create an smb_fname to call rename_internals_fsp() with. */
6208 status = create_synthetic_smb_fname(talloc_tos(),
6209 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6211 if (!NT_STATUS_IS_OK(status)) {
6216 * Set the original last component, since
6217 * rename_internals_fsp() requires it.
6219 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6221 if (smb_fname_dst->original_lcomp == NULL) {
6222 status = NT_STATUS_NO_MEMORY;
6228 * Build up an smb_fname_dst based on the filename passed in.
6229 * We basically just strip off the last component, and put on
6230 * the newname instead.
6232 char *base_name = NULL;
6234 /* newname must *not* be a stream name. */
6235 if (newname[0] == ':') {
6236 return NT_STATUS_NOT_SUPPORTED;
6240 * Strip off the last component (filename) of the path passed
6243 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6245 return NT_STATUS_NO_MEMORY;
6247 p = strrchr_m(base_name, '/');
6251 base_name = talloc_strdup(ctx, "");
6253 return NT_STATUS_NO_MEMORY;
6256 /* Append the new name. */
6257 base_name = talloc_asprintf_append(base_name,
6261 return NT_STATUS_NO_MEMORY;
6264 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6267 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6270 /* If an error we expect this to be
6271 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6273 if (!NT_STATUS_IS_OK(status)) {
6274 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6278 /* Create an smb_fname to call rename_internals_fsp() */
6279 status = create_synthetic_smb_fname(ctx,
6283 if (!NT_STATUS_IS_OK(status)) {
6290 DEBUG(10,("smb_file_rename_information: "
6291 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6292 fsp->fnum, fsp_str_dbg(fsp),
6293 smb_fname_str_dbg(smb_fname_dst)));
6294 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6297 DEBUG(10,("smb_file_rename_information: "
6298 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6299 smb_fname_str_dbg(smb_fname_src),
6300 smb_fname_str_dbg(smb_fname_dst)));
6301 status = rename_internals(ctx, conn, req, smb_fname_src,
6302 smb_fname_dst, 0, overwrite, false,
6304 FILE_WRITE_ATTRIBUTES);
6307 TALLOC_FREE(smb_fname_dst);
6311 /****************************************************************************
6312 Deal with SMB_SET_POSIX_ACL.
6313 ****************************************************************************/
6315 #if defined(HAVE_POSIX_ACLS)
6316 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6320 const struct smb_filename *smb_fname)
6322 uint16 posix_acl_version;
6323 uint16 num_file_acls;
6324 uint16 num_def_acls;
6325 bool valid_file_acls = True;
6326 bool valid_def_acls = True;
6328 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6329 return NT_STATUS_INVALID_PARAMETER;
6331 posix_acl_version = SVAL(pdata,0);
6332 num_file_acls = SVAL(pdata,2);
6333 num_def_acls = SVAL(pdata,4);
6335 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6336 valid_file_acls = False;
6340 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6341 valid_def_acls = False;
6345 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6346 return NT_STATUS_INVALID_PARAMETER;
6349 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6350 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6351 return NT_STATUS_INVALID_PARAMETER;
6354 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6355 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6356 (unsigned int)num_file_acls,
6357 (unsigned int)num_def_acls));
6359 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6360 smb_fname->base_name, num_file_acls,
6361 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6362 return map_nt_error_from_unix(errno);
6365 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6366 smb_fname->base_name, &smb_fname->st, num_def_acls,
6367 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6368 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6369 return map_nt_error_from_unix(errno);
6371 return NT_STATUS_OK;
6375 /****************************************************************************
6376 Deal with SMB_SET_POSIX_LOCK.
6377 ****************************************************************************/
6379 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6380 struct smb_request *req,
6388 bool blocking_lock = False;
6389 enum brl_type lock_type;
6391 NTSTATUS status = NT_STATUS_OK;
6393 if (fsp == NULL || fsp->fh->fd == -1) {
6394 return NT_STATUS_INVALID_HANDLE;
6397 if (total_data != POSIX_LOCK_DATA_SIZE) {
6398 return NT_STATUS_INVALID_PARAMETER;
6401 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6402 case POSIX_LOCK_TYPE_READ:
6403 lock_type = READ_LOCK;
6405 case POSIX_LOCK_TYPE_WRITE:
6406 /* Return the right POSIX-mappable error code for files opened read-only. */
6407 if (!fsp->can_write) {
6408 return NT_STATUS_INVALID_HANDLE;
6410 lock_type = WRITE_LOCK;
6412 case POSIX_LOCK_TYPE_UNLOCK:
6413 lock_type = UNLOCK_LOCK;
6416 return NT_STATUS_INVALID_PARAMETER;
6419 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6420 blocking_lock = False;
6421 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6422 blocking_lock = True;
6424 return NT_STATUS_INVALID_PARAMETER;
6427 if (!lp_blocking_locks(SNUM(conn))) {
6428 blocking_lock = False;
6431 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6432 #if defined(HAVE_LONGLONG)
6433 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6434 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6435 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6436 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6437 #else /* HAVE_LONGLONG */
6438 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6439 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6440 #endif /* HAVE_LONGLONG */
6442 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6443 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6445 (unsigned int)lock_type,
6446 (unsigned long long)smblctx,
6450 if (lock_type == UNLOCK_LOCK) {
6451 status = do_unlock(req->sconn->msg_ctx,
6458 uint64_t block_smblctx;
6460 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6472 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6474 * A blocking lock was requested. Package up
6475 * this smb into a queued request and push it
6476 * onto the blocking lock queue.
6478 if(push_blocking_lock_request(br_lck,
6481 -1, /* infinite timeout. */
6489 TALLOC_FREE(br_lck);
6493 TALLOC_FREE(br_lck);
6499 /****************************************************************************
6500 Deal with SMB_SET_FILE_BASIC_INFO.
6501 ****************************************************************************/
6503 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6507 const struct smb_filename *smb_fname)
6509 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6510 struct smb_file_time ft;
6512 NTSTATUS status = NT_STATUS_OK;
6516 if (total_data < 36) {
6517 return NT_STATUS_INVALID_PARAMETER;
6520 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6521 return NT_STATUS_ACCESS_DENIED;
6524 /* Set the attributes */
6525 dosmode = IVAL(pdata,32);
6526 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6527 if (!NT_STATUS_IS_OK(status)) {
6532 ft.create_time = interpret_long_date(pdata);
6535 ft.atime = interpret_long_date(pdata+8);
6538 ft.mtime = interpret_long_date(pdata+16);
6541 ft.ctime = interpret_long_date(pdata+24);
6543 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6544 smb_fname_str_dbg(smb_fname)));
6546 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6550 /****************************************************************************
6551 Deal with SMB_INFO_STANDARD.
6552 ****************************************************************************/
6554 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6558 const struct smb_filename *smb_fname)
6560 struct smb_file_time ft;
6564 if (total_data < 12) {
6565 return NT_STATUS_INVALID_PARAMETER;
6568 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6569 return NT_STATUS_ACCESS_DENIED;
6573 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6575 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6577 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6579 DEBUG(10,("smb_set_info_standard: file %s\n",
6580 smb_fname_str_dbg(smb_fname)));
6582 return smb_set_file_time(conn,
6589 /****************************************************************************
6590 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6591 ****************************************************************************/
6593 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6594 struct smb_request *req,
6598 struct smb_filename *smb_fname)
6600 uint64_t allocation_size = 0;
6601 NTSTATUS status = NT_STATUS_OK;
6602 files_struct *new_fsp = NULL;
6604 if (!VALID_STAT(smb_fname->st)) {
6605 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6608 if (total_data < 8) {
6609 return NT_STATUS_INVALID_PARAMETER;
6612 allocation_size = (uint64_t)IVAL(pdata,0);
6613 #ifdef LARGE_SMB_OFF_T
6614 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6615 #else /* LARGE_SMB_OFF_T */
6616 if (IVAL(pdata,4) != 0) {
6617 /* more than 32 bits? */
6618 return NT_STATUS_INVALID_PARAMETER;
6620 #endif /* LARGE_SMB_OFF_T */
6622 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6623 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6624 (double)allocation_size));
6626 if (allocation_size) {
6627 allocation_size = smb_roundup(conn, allocation_size);
6630 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6631 return NT_STATUS_ACCESS_DENIED;
6634 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6635 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6636 (double)allocation_size));
6638 if (fsp && fsp->fh->fd != -1) {
6639 /* Open file handle. */
6640 /* Only change if needed. */
6641 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6642 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6643 return map_nt_error_from_unix(errno);
6646 /* But always update the time. */
6648 * This is equivalent to a write. Ensure it's seen immediately
6649 * if there are no pending writes.
6651 trigger_write_time_update_immediate(fsp);
6652 return NT_STATUS_OK;
6655 /* Pathname or stat or directory file. */
6656 status = SMB_VFS_CREATE_FILE(
6659 0, /* root_dir_fid */
6660 smb_fname, /* fname */
6661 FILE_WRITE_DATA, /* access_mask */
6662 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6664 FILE_OPEN, /* create_disposition*/
6665 0, /* create_options */
6666 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6667 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6668 0, /* allocation_size */
6669 0, /* private_flags */
6672 &new_fsp, /* result */
6675 if (!NT_STATUS_IS_OK(status)) {
6676 /* NB. We check for open_was_deferred in the caller. */
6680 /* Only change if needed. */
6681 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6682 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6683 status = map_nt_error_from_unix(errno);
6684 close_file(req, new_fsp, NORMAL_CLOSE);
6689 /* Changing the allocation size should set the last mod time. */
6691 * This is equivalent to a write. Ensure it's seen immediately
6692 * if there are no pending writes.
6694 trigger_write_time_update_immediate(new_fsp);
6696 close_file(req, new_fsp, NORMAL_CLOSE);
6697 return NT_STATUS_OK;
6700 /****************************************************************************
6701 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6702 ****************************************************************************/
6704 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6705 struct smb_request *req,
6709 const struct smb_filename *smb_fname,
6710 bool fail_after_createfile)
6714 if (total_data < 8) {
6715 return NT_STATUS_INVALID_PARAMETER;
6718 size = IVAL(pdata,0);
6719 #ifdef LARGE_SMB_OFF_T
6720 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6721 #else /* LARGE_SMB_OFF_T */
6722 if (IVAL(pdata,4) != 0) {
6723 /* more than 32 bits? */
6724 return NT_STATUS_INVALID_PARAMETER;
6726 #endif /* LARGE_SMB_OFF_T */
6727 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6728 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6731 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6732 return NT_STATUS_ACCESS_DENIED;
6735 return smb_set_file_size(conn, req,
6740 fail_after_createfile);
6743 /****************************************************************************
6744 Allow a UNIX info mknod.
6745 ****************************************************************************/
6747 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6750 const struct smb_filename *smb_fname)
6752 uint32 file_type = IVAL(pdata,56);
6753 #if defined(HAVE_MAKEDEV)
6754 uint32 dev_major = IVAL(pdata,60);
6755 uint32 dev_minor = IVAL(pdata,68);
6757 SMB_DEV_T dev = (SMB_DEV_T)0;
6758 uint32 raw_unixmode = IVAL(pdata,84);
6762 if (total_data < 100) {
6763 return NT_STATUS_INVALID_PARAMETER;
6766 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6767 PERM_NEW_FILE, &unixmode);
6768 if (!NT_STATUS_IS_OK(status)) {
6772 #if defined(HAVE_MAKEDEV)
6773 dev = makedev(dev_major, dev_minor);
6776 switch (file_type) {
6777 #if defined(S_IFIFO)
6778 case UNIX_TYPE_FIFO:
6779 unixmode |= S_IFIFO;
6782 #if defined(S_IFSOCK)
6783 case UNIX_TYPE_SOCKET:
6784 unixmode |= S_IFSOCK;
6787 #if defined(S_IFCHR)
6788 case UNIX_TYPE_CHARDEV:
6789 unixmode |= S_IFCHR;
6792 #if defined(S_IFBLK)
6793 case UNIX_TYPE_BLKDEV:
6794 unixmode |= S_IFBLK;
6798 return NT_STATUS_INVALID_PARAMETER;
6801 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6802 "%.0f mode 0%o for file %s\n", (double)dev,
6803 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6805 /* Ok - do the mknod. */
6806 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6807 return map_nt_error_from_unix(errno);
6810 /* If any of the other "set" calls fail we
6811 * don't want to end up with a half-constructed mknod.
6814 if (lp_inherit_perms(SNUM(conn))) {
6816 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6818 return NT_STATUS_NO_MEMORY;
6820 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6822 TALLOC_FREE(parent);
6825 return NT_STATUS_OK;
6828 /****************************************************************************
6829 Deal with SMB_SET_FILE_UNIX_BASIC.
6830 ****************************************************************************/
6832 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6833 struct smb_request *req,
6837 const struct smb_filename *smb_fname)
6839 struct smb_file_time ft;
6840 uint32 raw_unixmode;
6843 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6844 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6845 NTSTATUS status = NT_STATUS_OK;
6846 bool delete_on_fail = False;
6847 enum perm_type ptype;
6848 files_struct *all_fsps = NULL;
6849 bool modify_mtime = true;
6851 struct smb_filename *smb_fname_tmp = NULL;
6852 SMB_STRUCT_STAT sbuf;
6856 if (total_data < 100) {
6857 return NT_STATUS_INVALID_PARAMETER;
6860 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6861 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6862 size=IVAL(pdata,0); /* first 8 Bytes are size */
6863 #ifdef LARGE_SMB_OFF_T
6864 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6865 #else /* LARGE_SMB_OFF_T */
6866 if (IVAL(pdata,4) != 0) {
6867 /* more than 32 bits? */
6868 return NT_STATUS_INVALID_PARAMETER;
6870 #endif /* LARGE_SMB_OFF_T */
6873 ft.atime = interpret_long_date(pdata+24); /* access_time */
6874 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6875 set_owner = (uid_t)IVAL(pdata,40);
6876 set_grp = (gid_t)IVAL(pdata,48);
6877 raw_unixmode = IVAL(pdata,84);
6879 if (VALID_STAT(smb_fname->st)) {
6880 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6881 ptype = PERM_EXISTING_DIR;
6883 ptype = PERM_EXISTING_FILE;
6886 ptype = PERM_NEW_FILE;
6889 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6891 if (!NT_STATUS_IS_OK(status)) {
6895 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6896 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6897 smb_fname_str_dbg(smb_fname), (double)size,
6898 (unsigned int)set_owner, (unsigned int)set_grp,
6899 (int)raw_unixmode));
6901 sbuf = smb_fname->st;
6903 if (!VALID_STAT(sbuf)) {
6905 * The only valid use of this is to create character and block
6906 * devices, and named pipes. This is deprecated (IMHO) and
6907 * a new info level should be used for mknod. JRA.
6910 status = smb_unix_mknod(conn,
6914 if (!NT_STATUS_IS_OK(status)) {
6918 status = copy_smb_filename(talloc_tos(), smb_fname,
6920 if (!NT_STATUS_IS_OK(status)) {
6924 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6925 status = map_nt_error_from_unix(errno);
6926 TALLOC_FREE(smb_fname_tmp);
6927 SMB_VFS_UNLINK(conn, smb_fname);
6931 sbuf = smb_fname_tmp->st;
6932 smb_fname = smb_fname_tmp;
6934 /* Ensure we don't try and change anything else. */
6935 raw_unixmode = SMB_MODE_NO_CHANGE;
6936 size = get_file_size_stat(&sbuf);
6937 ft.atime = sbuf.st_ex_atime;
6938 ft.mtime = sbuf.st_ex_mtime;
6940 * We continue here as we might want to change the
6943 delete_on_fail = True;
6947 /* Horrible backwards compatibility hack as an old server bug
6948 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6952 size = get_file_size_stat(&sbuf);
6957 * Deal with the UNIX specific mode set.
6960 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6961 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6962 "setting mode 0%o for file %s\n",
6963 (unsigned int)unixmode,
6964 smb_fname_str_dbg(smb_fname)));
6965 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6966 return map_nt_error_from_unix(errno);
6971 * Deal with the UNIX specific uid set.
6974 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6975 (sbuf.st_ex_uid != set_owner)) {
6978 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6979 "changing owner %u for path %s\n",
6980 (unsigned int)set_owner,
6981 smb_fname_str_dbg(smb_fname)));
6983 if (S_ISLNK(sbuf.st_ex_mode)) {
6984 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6985 set_owner, (gid_t)-1);
6987 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6988 set_owner, (gid_t)-1);
6992 status = map_nt_error_from_unix(errno);
6993 if (delete_on_fail) {
6994 SMB_VFS_UNLINK(conn, smb_fname);
7001 * Deal with the UNIX specific gid set.
7004 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7005 (sbuf.st_ex_gid != set_grp)) {
7006 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7007 "changing group %u for file %s\n",
7008 (unsigned int)set_owner,
7009 smb_fname_str_dbg(smb_fname)));
7010 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7012 status = map_nt_error_from_unix(errno);
7013 if (delete_on_fail) {
7014 SMB_VFS_UNLINK(conn, smb_fname);
7020 /* Deal with any size changes. */
7022 status = smb_set_file_size(conn, req,
7028 if (!NT_STATUS_IS_OK(status)) {
7032 /* Deal with any time changes. */
7033 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7034 /* No change, don't cancel anything. */
7038 id = vfs_file_id_from_sbuf(conn, &sbuf);
7039 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7040 all_fsps = file_find_di_next(all_fsps)) {
7042 * We're setting the time explicitly for UNIX.
7043 * Cancel any pending changes over all handles.
7045 all_fsps->update_write_time_on_close = false;
7046 TALLOC_FREE(all_fsps->update_write_time_event);
7050 * Override the "setting_write_time"
7051 * parameter here as it almost does what
7052 * we need. Just remember if we modified
7053 * mtime and send the notify ourselves.
7055 if (null_timespec(ft.mtime)) {
7056 modify_mtime = false;
7059 status = smb_set_file_time(conn,
7065 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7066 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7071 /****************************************************************************
7072 Deal with SMB_SET_FILE_UNIX_INFO2.
7073 ****************************************************************************/
7075 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7076 struct smb_request *req,
7080 const struct smb_filename *smb_fname)
7086 if (total_data < 116) {
7087 return NT_STATUS_INVALID_PARAMETER;
7090 /* Start by setting all the fields that are common between UNIX_BASIC
7093 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7095 if (!NT_STATUS_IS_OK(status)) {
7099 smb_fflags = IVAL(pdata, 108);
7100 smb_fmask = IVAL(pdata, 112);
7102 /* NB: We should only attempt to alter the file flags if the client
7103 * sends a non-zero mask.
7105 if (smb_fmask != 0) {
7106 int stat_fflags = 0;
7108 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7109 smb_fmask, &stat_fflags)) {
7110 /* Client asked to alter a flag we don't understand. */
7111 return NT_STATUS_INVALID_PARAMETER;
7114 if (fsp && fsp->fh->fd != -1) {
7115 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7116 return NT_STATUS_NOT_SUPPORTED;
7118 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7119 stat_fflags) != 0) {
7120 return map_nt_error_from_unix(errno);
7125 /* XXX: need to add support for changing the create_time here. You
7126 * can do this for paths on Darwin with setattrlist(2). The right way
7127 * to hook this up is probably by extending the VFS utimes interface.
7130 return NT_STATUS_OK;
7133 /****************************************************************************
7134 Create a directory with POSIX semantics.
7135 ****************************************************************************/
7137 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7138 struct smb_request *req,
7141 struct smb_filename *smb_fname,
7142 int *pdata_return_size)
7144 NTSTATUS status = NT_STATUS_OK;
7145 uint32 raw_unixmode = 0;
7146 uint32 mod_unixmode = 0;
7147 mode_t unixmode = (mode_t)0;
7148 files_struct *fsp = NULL;
7149 uint16 info_level_return = 0;
7151 char *pdata = *ppdata;
7153 if (total_data < 18) {
7154 return NT_STATUS_INVALID_PARAMETER;
7157 raw_unixmode = IVAL(pdata,8);
7158 /* Next 4 bytes are not yet defined. */
7160 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7161 PERM_NEW_DIR, &unixmode);
7162 if (!NT_STATUS_IS_OK(status)) {
7166 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7168 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7169 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7171 status = SMB_VFS_CREATE_FILE(
7174 0, /* root_dir_fid */
7175 smb_fname, /* fname */
7176 FILE_READ_ATTRIBUTES, /* access_mask */
7177 FILE_SHARE_NONE, /* share_access */
7178 FILE_CREATE, /* create_disposition*/
7179 FILE_DIRECTORY_FILE, /* create_options */
7180 mod_unixmode, /* file_attributes */
7181 0, /* oplock_request */
7182 0, /* allocation_size */
7183 0, /* private_flags */
7189 if (NT_STATUS_IS_OK(status)) {
7190 close_file(req, fsp, NORMAL_CLOSE);
7193 info_level_return = SVAL(pdata,16);
7195 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7196 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7197 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7198 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7200 *pdata_return_size = 12;
7203 /* Realloc the data size */
7204 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7205 if (*ppdata == NULL) {
7206 *pdata_return_size = 0;
7207 return NT_STATUS_NO_MEMORY;
7211 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7212 SSVAL(pdata,2,0); /* No fnum. */
7213 SIVAL(pdata,4,info); /* Was directory created. */
7215 switch (info_level_return) {
7216 case SMB_QUERY_FILE_UNIX_BASIC:
7217 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7218 SSVAL(pdata,10,0); /* Padding. */
7219 store_file_unix_basic(conn, pdata + 12, fsp,
7222 case SMB_QUERY_FILE_UNIX_INFO2:
7223 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7224 SSVAL(pdata,10,0); /* Padding. */
7225 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7229 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7230 SSVAL(pdata,10,0); /* Padding. */
7237 /****************************************************************************
7238 Open/Create a file with POSIX semantics.
7239 ****************************************************************************/
7241 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7242 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7244 static NTSTATUS smb_posix_open(connection_struct *conn,
7245 struct smb_request *req,
7248 struct smb_filename *smb_fname,
7249 int *pdata_return_size)
7251 bool extended_oplock_granted = False;
7252 char *pdata = *ppdata;
7254 uint32 wire_open_mode = 0;
7255 uint32 raw_unixmode = 0;
7256 uint32 mod_unixmode = 0;
7257 uint32 create_disp = 0;
7258 uint32 access_mask = 0;
7259 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7260 NTSTATUS status = NT_STATUS_OK;
7261 mode_t unixmode = (mode_t)0;
7262 files_struct *fsp = NULL;
7263 int oplock_request = 0;
7265 uint16 info_level_return = 0;
7267 if (total_data < 18) {
7268 return NT_STATUS_INVALID_PARAMETER;
7271 flags = IVAL(pdata,0);
7272 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7273 if (oplock_request) {
7274 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7277 wire_open_mode = IVAL(pdata,4);
7279 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7280 return smb_posix_mkdir(conn, req,
7287 switch (wire_open_mode & SMB_ACCMODE) {
7289 access_mask = SMB_O_RDONLY_MAPPING;
7292 access_mask = SMB_O_WRONLY_MAPPING;
7295 access_mask = (SMB_O_RDONLY_MAPPING|
7296 SMB_O_WRONLY_MAPPING);
7299 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7300 (unsigned int)wire_open_mode ));
7301 return NT_STATUS_INVALID_PARAMETER;
7304 wire_open_mode &= ~SMB_ACCMODE;
7306 /* First take care of O_CREAT|O_EXCL interactions. */
7307 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7308 case (SMB_O_CREAT | SMB_O_EXCL):
7309 /* File exists fail. File not exist create. */
7310 create_disp = FILE_CREATE;
7313 /* File exists open. File not exist create. */
7314 create_disp = FILE_OPEN_IF;
7317 /* File exists open. File not exist fail. */
7318 create_disp = FILE_OPEN;
7321 /* O_EXCL on its own without O_CREAT is undefined. */
7323 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7324 (unsigned int)wire_open_mode ));
7325 return NT_STATUS_INVALID_PARAMETER;
7328 /* Next factor in the effects of O_TRUNC. */
7329 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7331 if (wire_open_mode & SMB_O_TRUNC) {
7332 switch (create_disp) {
7334 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7335 /* Leave create_disp alone as
7336 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7338 /* File exists fail. File not exist create. */
7341 /* SMB_O_CREAT | SMB_O_TRUNC */
7342 /* File exists overwrite. File not exist create. */
7343 create_disp = FILE_OVERWRITE_IF;
7347 /* File exists overwrite. File not exist fail. */
7348 create_disp = FILE_OVERWRITE;
7351 /* Cannot get here. */
7352 smb_panic("smb_posix_open: logic error");
7353 return NT_STATUS_INVALID_PARAMETER;
7357 raw_unixmode = IVAL(pdata,8);
7358 /* Next 4 bytes are not yet defined. */
7360 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7361 (VALID_STAT(smb_fname->st) ?
7362 PERM_EXISTING_FILE : PERM_NEW_FILE),
7365 if (!NT_STATUS_IS_OK(status)) {
7369 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7371 if (wire_open_mode & SMB_O_SYNC) {
7372 create_options |= FILE_WRITE_THROUGH;
7374 if (wire_open_mode & SMB_O_APPEND) {
7375 access_mask |= FILE_APPEND_DATA;
7377 if (wire_open_mode & SMB_O_DIRECT) {
7378 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7381 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7382 VALID_STAT_OF_DIR(smb_fname->st)) {
7383 if (access_mask != SMB_O_RDONLY_MAPPING) {
7384 return NT_STATUS_FILE_IS_A_DIRECTORY;
7386 create_options &= ~FILE_NON_DIRECTORY_FILE;
7387 create_options |= FILE_DIRECTORY_FILE;
7390 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7391 smb_fname_str_dbg(smb_fname),
7392 (unsigned int)wire_open_mode,
7393 (unsigned int)unixmode ));
7395 status = SMB_VFS_CREATE_FILE(
7398 0, /* root_dir_fid */
7399 smb_fname, /* fname */
7400 access_mask, /* access_mask */
7401 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7403 create_disp, /* create_disposition*/
7404 create_options, /* create_options */
7405 mod_unixmode, /* file_attributes */
7406 oplock_request, /* oplock_request */
7407 0, /* allocation_size */
7408 0, /* private_flags */
7414 if (!NT_STATUS_IS_OK(status)) {
7418 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7419 extended_oplock_granted = True;
7422 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7423 extended_oplock_granted = True;
7426 info_level_return = SVAL(pdata,16);
7428 /* Allocate the correct return size. */
7430 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7431 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7432 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7433 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7435 *pdata_return_size = 12;
7438 /* Realloc the data size */
7439 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7440 if (*ppdata == NULL) {
7441 close_file(req, fsp, ERROR_CLOSE);
7442 *pdata_return_size = 0;
7443 return NT_STATUS_NO_MEMORY;
7447 if (extended_oplock_granted) {
7448 if (flags & REQUEST_BATCH_OPLOCK) {
7449 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7451 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7453 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7454 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7456 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7459 SSVAL(pdata,2,fsp->fnum);
7460 SIVAL(pdata,4,info); /* Was file created etc. */
7462 switch (info_level_return) {
7463 case SMB_QUERY_FILE_UNIX_BASIC:
7464 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7465 SSVAL(pdata,10,0); /* padding. */
7466 store_file_unix_basic(conn, pdata + 12, fsp,
7469 case SMB_QUERY_FILE_UNIX_INFO2:
7470 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7471 SSVAL(pdata,10,0); /* padding. */
7472 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7476 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7477 SSVAL(pdata,10,0); /* padding. */
7480 return NT_STATUS_OK;
7483 /****************************************************************************
7484 Delete a file with POSIX semantics.
7485 ****************************************************************************/
7487 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7488 struct smb_request *req,
7491 struct smb_filename *smb_fname)
7493 NTSTATUS status = NT_STATUS_OK;
7494 files_struct *fsp = NULL;
7498 int create_options = 0;
7500 struct share_mode_lock *lck = NULL;
7502 if (total_data < 2) {
7503 return NT_STATUS_INVALID_PARAMETER;
7506 flags = SVAL(pdata,0);
7508 if (!VALID_STAT(smb_fname->st)) {
7509 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7512 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7513 !VALID_STAT_OF_DIR(smb_fname->st)) {
7514 return NT_STATUS_NOT_A_DIRECTORY;
7517 DEBUG(10,("smb_posix_unlink: %s %s\n",
7518 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7519 smb_fname_str_dbg(smb_fname)));
7521 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7522 create_options |= FILE_DIRECTORY_FILE;
7525 status = SMB_VFS_CREATE_FILE(
7528 0, /* root_dir_fid */
7529 smb_fname, /* fname */
7530 DELETE_ACCESS, /* access_mask */
7531 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7533 FILE_OPEN, /* create_disposition*/
7534 create_options, /* create_options */
7535 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7536 0, /* oplock_request */
7537 0, /* allocation_size */
7538 0, /* private_flags */
7544 if (!NT_STATUS_IS_OK(status)) {
7549 * Don't lie to client. If we can't really delete due to
7550 * non-POSIX opens return SHARING_VIOLATION.
7553 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7556 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7557 "lock for file %s\n", fsp_str_dbg(fsp)));
7558 close_file(req, fsp, NORMAL_CLOSE);
7559 return NT_STATUS_INVALID_PARAMETER;
7563 * See if others still have the file open. If this is the case, then
7564 * don't delete. If all opens are POSIX delete we can set the delete
7565 * on close disposition.
7567 for (i=0; i<lck->num_share_modes; i++) {
7568 struct share_mode_entry *e = &lck->share_modes[i];
7569 if (is_valid_share_mode_entry(e)) {
7570 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7573 /* Fail with sharing violation. */
7574 close_file(req, fsp, NORMAL_CLOSE);
7576 return NT_STATUS_SHARING_VIOLATION;
7581 * Set the delete on close.
7583 status = smb_set_file_disposition_info(conn,
7589 if (!NT_STATUS_IS_OK(status)) {
7590 close_file(req, fsp, NORMAL_CLOSE);
7595 return close_file(req, fsp, NORMAL_CLOSE);
7598 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7599 struct smb_request *req,
7600 TALLOC_CTX *mem_ctx,
7601 uint16_t info_level,
7603 struct smb_filename *smb_fname,
7604 char **ppdata, int total_data,
7607 char *pdata = *ppdata;
7608 NTSTATUS status = NT_STATUS_OK;
7609 int data_return_size = 0;
7613 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7614 return NT_STATUS_INVALID_LEVEL;
7617 if (!CAN_WRITE(conn)) {
7618 /* Allow POSIX opens. The open path will deny
7619 * any non-readonly opens. */
7620 if (info_level != SMB_POSIX_PATH_OPEN) {
7621 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7625 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7626 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7627 fsp ? fsp->fnum : -1, info_level, total_data));
7629 switch (info_level) {
7631 case SMB_INFO_STANDARD:
7633 status = smb_set_info_standard(conn,
7641 case SMB_INFO_SET_EA:
7643 status = smb_info_set_ea(conn,
7651 case SMB_SET_FILE_BASIC_INFO:
7652 case SMB_FILE_BASIC_INFORMATION:
7654 status = smb_set_file_basic_info(conn,
7662 case SMB_FILE_ALLOCATION_INFORMATION:
7663 case SMB_SET_FILE_ALLOCATION_INFO:
7665 status = smb_set_file_allocation_info(conn, req,
7673 case SMB_FILE_END_OF_FILE_INFORMATION:
7674 case SMB_SET_FILE_END_OF_FILE_INFO:
7677 * XP/Win7 both fail after the createfile with
7678 * SMB_SET_FILE_END_OF_FILE_INFO but not
7679 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7680 * The level is known here, so pass it down
7684 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7686 status = smb_set_file_end_of_file_info(conn, req,
7695 case SMB_FILE_DISPOSITION_INFORMATION:
7696 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7699 /* JRA - We used to just ignore this on a path ?
7700 * Shouldn't this be invalid level on a pathname
7703 if (tran_call != TRANSACT2_SETFILEINFO) {
7704 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7707 status = smb_set_file_disposition_info(conn,
7715 case SMB_FILE_POSITION_INFORMATION:
7717 status = smb_file_position_information(conn,
7724 case SMB_FILE_FULL_EA_INFORMATION:
7726 status = smb_set_file_full_ea_info(conn,
7733 /* From tridge Samba4 :
7734 * MODE_INFORMATION in setfileinfo (I have no
7735 * idea what "mode information" on a file is - it takes a value of 0,
7736 * 2, 4 or 6. What could it be?).
7739 case SMB_FILE_MODE_INFORMATION:
7741 status = smb_file_mode_information(conn,
7748 * CIFS UNIX extensions.
7751 case SMB_SET_FILE_UNIX_BASIC:
7753 status = smb_set_file_unix_basic(conn, req,
7761 case SMB_SET_FILE_UNIX_INFO2:
7763 status = smb_set_file_unix_info2(conn, req,
7771 case SMB_SET_FILE_UNIX_LINK:
7774 /* We must have a pathname for this. */
7775 return NT_STATUS_INVALID_LEVEL;
7777 status = smb_set_file_unix_link(conn, req, pdata,
7778 total_data, smb_fname);
7782 case SMB_SET_FILE_UNIX_HLINK:
7785 /* We must have a pathname for this. */
7786 return NT_STATUS_INVALID_LEVEL;
7788 status = smb_set_file_unix_hlink(conn, req,
7794 case SMB_FILE_RENAME_INFORMATION:
7796 status = smb_file_rename_information(conn, req,
7802 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7804 /* SMB2 rename information. */
7805 status = smb2_file_rename_information(conn, req,
7811 case SMB_FILE_LINK_INFORMATION:
7813 status = smb_file_link_information(conn, req,
7819 #if defined(HAVE_POSIX_ACLS)
7820 case SMB_SET_POSIX_ACL:
7822 status = smb_set_posix_acl(conn,
7831 case SMB_SET_POSIX_LOCK:
7834 return NT_STATUS_INVALID_LEVEL;
7836 status = smb_set_posix_lock(conn, req,
7837 pdata, total_data, fsp);
7841 case SMB_POSIX_PATH_OPEN:
7844 /* We must have a pathname for this. */
7845 return NT_STATUS_INVALID_LEVEL;
7848 status = smb_posix_open(conn, req,
7856 case SMB_POSIX_PATH_UNLINK:
7859 /* We must have a pathname for this. */
7860 return NT_STATUS_INVALID_LEVEL;
7863 status = smb_posix_unlink(conn, req,
7871 return NT_STATUS_INVALID_LEVEL;
7874 if (!NT_STATUS_IS_OK(status)) {
7878 *ret_data_size = data_return_size;
7879 return NT_STATUS_OK;
7882 /****************************************************************************
7883 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7884 ****************************************************************************/
7886 static void call_trans2setfilepathinfo(connection_struct *conn,
7887 struct smb_request *req,
7888 unsigned int tran_call,
7889 char **pparams, int total_params,
7890 char **ppdata, int total_data,
7891 unsigned int max_data_bytes)
7893 char *params = *pparams;
7894 char *pdata = *ppdata;
7896 struct smb_filename *smb_fname = NULL;
7897 files_struct *fsp = NULL;
7898 NTSTATUS status = NT_STATUS_OK;
7899 int data_return_size = 0;
7902 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7906 if (tran_call == TRANSACT2_SETFILEINFO) {
7907 if (total_params < 4) {
7908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7912 fsp = file_fsp(req, SVAL(params,0));
7913 /* Basic check for non-null fsp. */
7914 if (!check_fsp_open(conn, req, fsp)) {
7917 info_level = SVAL(params,2);
7919 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7921 if (!NT_STATUS_IS_OK(status)) {
7922 reply_nterror(req, status);
7926 if(fsp->fh->fd == -1) {
7928 * This is actually a SETFILEINFO on a directory
7929 * handle (returned from an NT SMB). NT5.0 seems
7930 * to do this call. JRA.
7932 if (INFO_LEVEL_IS_UNIX(info_level)) {
7933 /* Always do lstat for UNIX calls. */
7934 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7935 DEBUG(3,("call_trans2setfilepathinfo: "
7936 "SMB_VFS_LSTAT of %s failed "
7938 smb_fname_str_dbg(smb_fname),
7940 reply_nterror(req, map_nt_error_from_unix(errno));
7944 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7945 DEBUG(3,("call_trans2setfilepathinfo: "
7946 "fileinfo of %s failed (%s)\n",
7947 smb_fname_str_dbg(smb_fname),
7949 reply_nterror(req, map_nt_error_from_unix(errno));
7953 } else if (fsp->print_file) {
7955 * Doing a DELETE_ON_CLOSE should cancel a print job.
7957 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7958 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7960 DEBUG(3,("call_trans2setfilepathinfo: "
7961 "Cancelling print job (%s)\n",
7965 send_trans2_replies(conn, req, params, 2,
7971 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7976 * Original code - this is an open file.
7978 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7979 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7980 "of fnum %d failed (%s)\n", fsp->fnum,
7982 reply_nterror(req, map_nt_error_from_unix(errno));
7990 if (total_params < 7) {
7991 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7995 info_level = SVAL(params,0);
7996 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7997 total_params - 6, STR_TERMINATE,
7999 if (!NT_STATUS_IS_OK(status)) {
8000 reply_nterror(req, status);
8004 status = filename_convert(req, conn,
8005 req->flags2 & FLAGS2_DFS_PATHNAMES,
8010 if (!NT_STATUS_IS_OK(status)) {
8011 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8012 reply_botherror(req,
8013 NT_STATUS_PATH_NOT_COVERED,
8014 ERRSRV, ERRbadpath);
8017 reply_nterror(req, status);
8021 if (INFO_LEVEL_IS_UNIX(info_level)) {
8023 * For CIFS UNIX extensions the target name may not exist.
8026 /* Always do lstat for UNIX calls. */
8027 SMB_VFS_LSTAT(conn, smb_fname);
8029 } else if (!VALID_STAT(smb_fname->st) &&
8030 SMB_VFS_STAT(conn, smb_fname)) {
8031 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8033 smb_fname_str_dbg(smb_fname),
8035 reply_nterror(req, map_nt_error_from_unix(errno));
8040 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8041 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8042 fsp ? fsp->fnum : -1, info_level,total_data));
8044 /* Realloc the parameter size */
8045 *pparams = (char *)SMB_REALLOC(*pparams,2);
8046 if (*pparams == NULL) {
8047 reply_nterror(req, NT_STATUS_NO_MEMORY);
8054 status = smbd_do_setfilepathinfo(conn, req, req,
8060 if (!NT_STATUS_IS_OK(status)) {
8061 if (open_was_deferred(req->sconn, req->mid)) {
8062 /* We have re-scheduled this call. */
8065 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8066 /* We have re-scheduled this call. */
8069 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8070 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8071 ERRSRV, ERRbadpath);
8074 if (info_level == SMB_POSIX_PATH_OPEN) {
8075 reply_openerror(req, status);
8079 reply_nterror(req, status);
8083 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8089 /****************************************************************************
8090 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8091 ****************************************************************************/
8093 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8094 char **pparams, int total_params,
8095 char **ppdata, int total_data,
8096 unsigned int max_data_bytes)
8098 struct smb_filename *smb_dname = NULL;
8099 char *params = *pparams;
8100 char *pdata = *ppdata;
8101 char *directory = NULL;
8102 NTSTATUS status = NT_STATUS_OK;
8103 struct ea_list *ea_list = NULL;
8104 TALLOC_CTX *ctx = talloc_tos();
8106 if (!CAN_WRITE(conn)) {
8107 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8111 if (total_params < 5) {
8112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8116 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8117 total_params - 4, STR_TERMINATE,
8119 if (!NT_STATUS_IS_OK(status)) {
8120 reply_nterror(req, status);
8124 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8126 status = filename_convert(ctx,
8128 req->flags2 & FLAGS2_DFS_PATHNAMES,
8134 if (!NT_STATUS_IS_OK(status)) {
8135 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8136 reply_botherror(req,
8137 NT_STATUS_PATH_NOT_COVERED,
8138 ERRSRV, ERRbadpath);
8141 reply_nterror(req, status);
8146 * OS/2 workplace shell seems to send SET_EA requests of "null"
8147 * length (4 bytes containing IVAL 4).
8148 * They seem to have no effect. Bug #3212. JRA.
8151 if (total_data && (total_data != 4)) {
8152 /* Any data in this call is an EA list. */
8153 if (total_data < 10) {
8154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8158 if (IVAL(pdata,0) > total_data) {
8159 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8160 IVAL(pdata,0), (unsigned int)total_data));
8161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8165 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8172 if (!lp_ea_support(SNUM(conn))) {
8173 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8177 /* If total_data == 4 Windows doesn't care what values
8178 * are placed in that field, it just ignores them.
8179 * The System i QNTC IBM SMB client puts bad values here,
8180 * so ignore them. */
8182 status = create_directory(conn, req, smb_dname);
8184 if (!NT_STATUS_IS_OK(status)) {
8185 reply_nterror(req, status);
8189 /* Try and set any given EA. */
8191 status = set_ea(conn, NULL, smb_dname, ea_list);
8192 if (!NT_STATUS_IS_OK(status)) {
8193 reply_nterror(req, status);
8198 /* Realloc the parameter and data sizes */
8199 *pparams = (char *)SMB_REALLOC(*pparams,2);
8200 if(*pparams == NULL) {
8201 reply_nterror(req, NT_STATUS_NO_MEMORY);
8208 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8211 TALLOC_FREE(smb_dname);
8215 /****************************************************************************
8216 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8217 We don't actually do this - we just send a null response.
8218 ****************************************************************************/
8220 static void call_trans2findnotifyfirst(connection_struct *conn,
8221 struct smb_request *req,
8222 char **pparams, int total_params,
8223 char **ppdata, int total_data,
8224 unsigned int max_data_bytes)
8226 char *params = *pparams;
8229 if (total_params < 6) {
8230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8234 info_level = SVAL(params,4);
8235 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8237 switch (info_level) {
8242 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8246 /* Realloc the parameter and data sizes */
8247 *pparams = (char *)SMB_REALLOC(*pparams,6);
8248 if (*pparams == NULL) {
8249 reply_nterror(req, NT_STATUS_NO_MEMORY);
8254 SSVAL(params,0,fnf_handle);
8255 SSVAL(params,2,0); /* No changes */
8256 SSVAL(params,4,0); /* No EA errors */
8263 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8268 /****************************************************************************
8269 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8270 changes). Currently this does nothing.
8271 ****************************************************************************/
8273 static void call_trans2findnotifynext(connection_struct *conn,
8274 struct smb_request *req,
8275 char **pparams, int total_params,
8276 char **ppdata, int total_data,
8277 unsigned int max_data_bytes)
8279 char *params = *pparams;
8281 DEBUG(3,("call_trans2findnotifynext\n"));
8283 /* Realloc the parameter and data sizes */
8284 *pparams = (char *)SMB_REALLOC(*pparams,4);
8285 if (*pparams == NULL) {
8286 reply_nterror(req, NT_STATUS_NO_MEMORY);
8291 SSVAL(params,0,0); /* No changes */
8292 SSVAL(params,2,0); /* No EA errors */
8294 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8299 /****************************************************************************
8300 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8301 ****************************************************************************/
8303 static void call_trans2getdfsreferral(connection_struct *conn,
8304 struct smb_request *req,
8305 char **pparams, int total_params,
8306 char **ppdata, int total_data,
8307 unsigned int max_data_bytes)
8309 char *params = *pparams;
8310 char *pathname = NULL;
8312 int max_referral_level;
8313 NTSTATUS status = NT_STATUS_OK;
8314 TALLOC_CTX *ctx = talloc_tos();
8316 DEBUG(10,("call_trans2getdfsreferral\n"));
8318 if (total_params < 3) {
8319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8323 max_referral_level = SVAL(params,0);
8325 if(!lp_host_msdfs()) {
8326 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8330 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8331 total_params - 2, STR_TERMINATE);
8333 reply_nterror(req, NT_STATUS_NOT_FOUND);
8336 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8337 ppdata,&status)) < 0) {
8338 reply_nterror(req, status);
8342 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8343 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8344 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8349 #define LMCAT_SPL 0x53
8350 #define LMFUNC_GETJOBID 0x60
8352 /****************************************************************************
8353 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8354 ****************************************************************************/
8356 static void call_trans2ioctl(connection_struct *conn,
8357 struct smb_request *req,
8358 char **pparams, int total_params,
8359 char **ppdata, int total_data,
8360 unsigned int max_data_bytes)
8362 char *pdata = *ppdata;
8363 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8365 /* check for an invalid fid before proceeding */
8368 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8372 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8373 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8374 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8375 if (*ppdata == NULL) {
8376 reply_nterror(req, NT_STATUS_NO_MEMORY);
8381 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8382 CAN ACCEPT THIS IN UNICODE. JRA. */
8385 if (fsp->print_file) {
8386 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8390 srvstr_push(pdata, req->flags2, pdata + 2,
8391 lp_netbios_name(), 15,
8392 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8393 srvstr_push(pdata, req->flags2, pdata+18,
8394 lp_servicename(SNUM(conn)), 13,
8395 STR_ASCII|STR_TERMINATE); /* Service name */
8396 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8401 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8402 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8405 /****************************************************************************
8406 Reply to a SMBfindclose (stop trans2 directory search).
8407 ****************************************************************************/
8409 void reply_findclose(struct smb_request *req)
8412 struct smbd_server_connection *sconn = req->sconn;
8414 START_PROFILE(SMBfindclose);
8417 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8418 END_PROFILE(SMBfindclose);
8422 dptr_num = SVALS(req->vwv+0, 0);
8424 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8426 dptr_close(sconn, &dptr_num);
8428 reply_outbuf(req, 0, 0);
8430 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8432 END_PROFILE(SMBfindclose);
8436 /****************************************************************************
8437 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8438 ****************************************************************************/
8440 void reply_findnclose(struct smb_request *req)
8444 START_PROFILE(SMBfindnclose);
8447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8448 END_PROFILE(SMBfindnclose);
8452 dptr_num = SVAL(req->vwv+0, 0);
8454 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8456 /* We never give out valid handles for a
8457 findnotifyfirst - so any dptr_num is ok here.
8460 reply_outbuf(req, 0, 0);
8462 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8464 END_PROFILE(SMBfindnclose);
8468 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8469 struct trans_state *state)
8471 if (get_Protocol() >= PROTOCOL_NT1) {
8472 req->flags2 |= 0x40; /* IS_LONG_NAME */
8473 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8476 if (conn->encrypt_level == Required && !req->encrypted) {
8477 if (state->call != TRANSACT2_QFSINFO &&
8478 state->call != TRANSACT2_SETFSINFO) {
8479 DEBUG(0,("handle_trans2: encryption required "
8481 (unsigned int)state->call));
8482 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8487 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8489 /* Now we must call the relevant TRANS2 function */
8490 switch(state->call) {
8491 case TRANSACT2_OPEN:
8493 START_PROFILE(Trans2_open);
8494 call_trans2open(conn, req,
8495 &state->param, state->total_param,
8496 &state->data, state->total_data,
8497 state->max_data_return);
8498 END_PROFILE(Trans2_open);
8502 case TRANSACT2_FINDFIRST:
8504 START_PROFILE(Trans2_findfirst);
8505 call_trans2findfirst(conn, req,
8506 &state->param, state->total_param,
8507 &state->data, state->total_data,
8508 state->max_data_return);
8509 END_PROFILE(Trans2_findfirst);
8513 case TRANSACT2_FINDNEXT:
8515 START_PROFILE(Trans2_findnext);
8516 call_trans2findnext(conn, req,
8517 &state->param, state->total_param,
8518 &state->data, state->total_data,
8519 state->max_data_return);
8520 END_PROFILE(Trans2_findnext);
8524 case TRANSACT2_QFSINFO:
8526 START_PROFILE(Trans2_qfsinfo);
8527 call_trans2qfsinfo(conn, req,
8528 &state->param, state->total_param,
8529 &state->data, state->total_data,
8530 state->max_data_return);
8531 END_PROFILE(Trans2_qfsinfo);
8535 case TRANSACT2_SETFSINFO:
8537 START_PROFILE(Trans2_setfsinfo);
8538 call_trans2setfsinfo(conn, req,
8539 &state->param, state->total_param,
8540 &state->data, state->total_data,
8541 state->max_data_return);
8542 END_PROFILE(Trans2_setfsinfo);
8546 case TRANSACT2_QPATHINFO:
8547 case TRANSACT2_QFILEINFO:
8549 START_PROFILE(Trans2_qpathinfo);
8550 call_trans2qfilepathinfo(conn, req, state->call,
8551 &state->param, state->total_param,
8552 &state->data, state->total_data,
8553 state->max_data_return);
8554 END_PROFILE(Trans2_qpathinfo);
8558 case TRANSACT2_SETPATHINFO:
8559 case TRANSACT2_SETFILEINFO:
8561 START_PROFILE(Trans2_setpathinfo);
8562 call_trans2setfilepathinfo(conn, req, state->call,
8563 &state->param, state->total_param,
8564 &state->data, state->total_data,
8565 state->max_data_return);
8566 END_PROFILE(Trans2_setpathinfo);
8570 case TRANSACT2_FINDNOTIFYFIRST:
8572 START_PROFILE(Trans2_findnotifyfirst);
8573 call_trans2findnotifyfirst(conn, req,
8574 &state->param, state->total_param,
8575 &state->data, state->total_data,
8576 state->max_data_return);
8577 END_PROFILE(Trans2_findnotifyfirst);
8581 case TRANSACT2_FINDNOTIFYNEXT:
8583 START_PROFILE(Trans2_findnotifynext);
8584 call_trans2findnotifynext(conn, req,
8585 &state->param, state->total_param,
8586 &state->data, state->total_data,
8587 state->max_data_return);
8588 END_PROFILE(Trans2_findnotifynext);
8592 case TRANSACT2_MKDIR:
8594 START_PROFILE(Trans2_mkdir);
8595 call_trans2mkdir(conn, req,
8596 &state->param, state->total_param,
8597 &state->data, state->total_data,
8598 state->max_data_return);
8599 END_PROFILE(Trans2_mkdir);
8603 case TRANSACT2_GET_DFS_REFERRAL:
8605 START_PROFILE(Trans2_get_dfs_referral);
8606 call_trans2getdfsreferral(conn, req,
8607 &state->param, state->total_param,
8608 &state->data, state->total_data,
8609 state->max_data_return);
8610 END_PROFILE(Trans2_get_dfs_referral);
8614 case TRANSACT2_IOCTL:
8616 START_PROFILE(Trans2_ioctl);
8617 call_trans2ioctl(conn, req,
8618 &state->param, state->total_param,
8619 &state->data, state->total_data,
8620 state->max_data_return);
8621 END_PROFILE(Trans2_ioctl);
8626 /* Error in request */
8627 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8628 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8632 /****************************************************************************
8633 Reply to a SMBtrans2.
8634 ****************************************************************************/
8636 void reply_trans2(struct smb_request *req)
8638 connection_struct *conn = req->conn;
8643 unsigned int tran_call;
8644 struct trans_state *state;
8647 START_PROFILE(SMBtrans2);
8649 if (req->wct < 14) {
8650 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8651 END_PROFILE(SMBtrans2);
8655 dsoff = SVAL(req->vwv+12, 0);
8656 dscnt = SVAL(req->vwv+11, 0);
8657 psoff = SVAL(req->vwv+10, 0);
8658 pscnt = SVAL(req->vwv+9, 0);
8659 tran_call = SVAL(req->vwv+14, 0);
8661 result = allow_new_trans(conn->pending_trans, req->mid);
8662 if (!NT_STATUS_IS_OK(result)) {
8663 DEBUG(2, ("Got invalid trans2 request: %s\n",
8664 nt_errstr(result)));
8665 reply_nterror(req, result);
8666 END_PROFILE(SMBtrans2);
8671 switch (tran_call) {
8672 /* List the allowed trans2 calls on IPC$ */
8673 case TRANSACT2_OPEN:
8674 case TRANSACT2_GET_DFS_REFERRAL:
8675 case TRANSACT2_QFILEINFO:
8676 case TRANSACT2_QFSINFO:
8677 case TRANSACT2_SETFSINFO:
8680 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8681 END_PROFILE(SMBtrans2);
8686 if ((state = talloc(conn, struct trans_state)) == NULL) {
8687 DEBUG(0, ("talloc failed\n"));
8688 reply_nterror(req, NT_STATUS_NO_MEMORY);
8689 END_PROFILE(SMBtrans2);
8693 state->cmd = SMBtrans2;
8695 state->mid = req->mid;
8696 state->vuid = req->vuid;
8697 state->setup_count = SVAL(req->vwv+13, 0);
8698 state->setup = NULL;
8699 state->total_param = SVAL(req->vwv+0, 0);
8700 state->param = NULL;
8701 state->total_data = SVAL(req->vwv+1, 0);
8703 state->max_param_return = SVAL(req->vwv+2, 0);
8704 state->max_data_return = SVAL(req->vwv+3, 0);
8705 state->max_setup_return = SVAL(req->vwv+4, 0);
8706 state->close_on_completion = BITSETW(req->vwv+5, 0);
8707 state->one_way = BITSETW(req->vwv+5, 1);
8709 state->call = tran_call;
8711 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8712 is so as a sanity check */
8713 if (state->setup_count != 1) {
8715 * Need to have rc=0 for ioctl to get job id for OS/2.
8716 * Network printing will fail if function is not successful.
8717 * Similar function in reply.c will be used if protocol
8718 * is LANMAN1.0 instead of LM1.2X002.
8719 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8720 * outbuf doesn't have to be set(only job id is used).
8722 if ( (state->setup_count == 4)
8723 && (tran_call == TRANSACT2_IOCTL)
8724 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8725 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8726 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8728 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8729 DEBUG(2,("Transaction is %d\n",tran_call));
8731 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8732 END_PROFILE(SMBtrans2);
8737 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8740 if (state->total_data) {
8742 if (trans_oob(state->total_data, 0, dscnt)
8743 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8747 /* Can't use talloc here, the core routines do realloc on the
8748 * params and data. */
8749 state->data = (char *)SMB_MALLOC(state->total_data);
8750 if (state->data == NULL) {
8751 DEBUG(0,("reply_trans2: data malloc fail for %u "
8752 "bytes !\n", (unsigned int)state->total_data));
8754 reply_nterror(req, NT_STATUS_NO_MEMORY);
8755 END_PROFILE(SMBtrans2);
8759 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8762 if (state->total_param) {
8764 if (trans_oob(state->total_param, 0, pscnt)
8765 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8769 /* Can't use talloc here, the core routines do realloc on the
8770 * params and data. */
8771 state->param = (char *)SMB_MALLOC(state->total_param);
8772 if (state->param == NULL) {
8773 DEBUG(0,("reply_trans: param malloc fail for %u "
8774 "bytes !\n", (unsigned int)state->total_param));
8775 SAFE_FREE(state->data);
8777 reply_nterror(req, NT_STATUS_NO_MEMORY);
8778 END_PROFILE(SMBtrans2);
8782 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8785 state->received_data = dscnt;
8786 state->received_param = pscnt;
8788 if ((state->received_param == state->total_param) &&
8789 (state->received_data == state->total_data)) {
8791 handle_trans2(conn, req, state);
8793 SAFE_FREE(state->data);
8794 SAFE_FREE(state->param);
8796 END_PROFILE(SMBtrans2);
8800 DLIST_ADD(conn->pending_trans, state);
8802 /* We need to send an interim response then receive the rest
8803 of the parameter/data bytes */
8804 reply_outbuf(req, 0, 0);
8805 show_msg((char *)req->outbuf);
8806 END_PROFILE(SMBtrans2);
8811 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8812 SAFE_FREE(state->data);
8813 SAFE_FREE(state->param);
8815 END_PROFILE(SMBtrans2);
8816 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8820 /****************************************************************************
8821 Reply to a SMBtranss2
8822 ****************************************************************************/
8824 void reply_transs2(struct smb_request *req)
8826 connection_struct *conn = req->conn;
8827 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8828 struct trans_state *state;
8830 START_PROFILE(SMBtranss2);
8832 show_msg((const char *)req->inbuf);
8835 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8836 END_PROFILE(SMBtranss2);
8840 for (state = conn->pending_trans; state != NULL;
8841 state = state->next) {
8842 if (state->mid == req->mid) {
8847 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8849 END_PROFILE(SMBtranss2);
8853 /* Revise state->total_param and state->total_data in case they have
8854 changed downwards */
8856 if (SVAL(req->vwv+0, 0) < state->total_param)
8857 state->total_param = SVAL(req->vwv+0, 0);
8858 if (SVAL(req->vwv+1, 0) < state->total_data)
8859 state->total_data = SVAL(req->vwv+1, 0);
8861 pcnt = SVAL(req->vwv+2, 0);
8862 poff = SVAL(req->vwv+3, 0);
8863 pdisp = SVAL(req->vwv+4, 0);
8865 dcnt = SVAL(req->vwv+5, 0);
8866 doff = SVAL(req->vwv+6, 0);
8867 ddisp = SVAL(req->vwv+7, 0);
8869 state->received_param += pcnt;
8870 state->received_data += dcnt;
8872 if ((state->received_data > state->total_data) ||
8873 (state->received_param > state->total_param))
8877 if (trans_oob(state->total_param, pdisp, pcnt)
8878 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8881 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8885 if (trans_oob(state->total_data, ddisp, dcnt)
8886 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8889 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8892 if ((state->received_param < state->total_param) ||
8893 (state->received_data < state->total_data)) {
8894 END_PROFILE(SMBtranss2);
8898 handle_trans2(conn, req, state);
8900 DLIST_REMOVE(conn->pending_trans, state);
8901 SAFE_FREE(state->data);
8902 SAFE_FREE(state->param);
8905 END_PROFILE(SMBtranss2);
8910 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8911 DLIST_REMOVE(conn->pending_trans, state);
8912 SAFE_FREE(state->data);
8913 SAFE_FREE(state->param);
8915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8916 END_PROFILE(SMBtranss2);