2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "../librpc/gen_ndr/xattr.h"
31 #include "../librpc/gen_ndr/ndr_security.h"
32 #include "libcli/security/security.h"
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct *conn,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
44 const SMB_STRUCT_STAT *psbuf);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
53 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type = get_remote_arch();
57 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58 val = SMB_ROUNDUP(val,rval);
63 /********************************************************************
64 Create a 64 bit FileIndex. If the file is on the same device as
65 the root of the share, just return the 64-bit inode. If it isn't,
66 mangle as we used to do.
67 ********************************************************************/
69 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
72 if (conn->base_share_dev == psbuf->st_ex_dev) {
73 return (uint64_t)psbuf->st_ex_ino;
75 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
76 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
80 /****************************************************************************
81 Utility functions for dealing with extended attributes.
82 ****************************************************************************/
84 /****************************************************************************
85 Refuse to allow clients to overwrite our private xattrs.
86 ****************************************************************************/
88 static bool samba_private_attr_name(const char *unix_ea_name)
90 static const char * const prohibited_ea_names[] = {
91 SAMBA_POSIX_INHERITANCE_EA_NAME,
92 SAMBA_XATTR_DOS_ATTRIB,
100 for (i = 0; prohibited_ea_names[i]; i++) {
101 if (strequal( prohibited_ea_names[i], unix_ea_name))
104 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
105 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
111 /****************************************************************************
112 Get one EA value. Fill in a struct ea_struct.
113 ****************************************************************************/
115 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
116 files_struct *fsp, const char *fname,
117 const char *ea_name, struct ea_struct *pea)
119 /* Get the value of this xattr. Max size is 64k. */
120 size_t attr_size = 256;
126 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
128 return NT_STATUS_NO_MEMORY;
131 if (fsp && fsp->fh->fd != -1) {
132 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
134 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
137 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
143 return map_nt_error_from_unix(errno);
146 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
147 dump_data(10, (uint8 *)val, sizeret);
150 if (strnequal(ea_name, "user.", 5)) {
151 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
153 pea->name = talloc_strdup(mem_ctx, ea_name);
155 if (pea->name == NULL) {
157 return NT_STATUS_NO_MEMORY;
159 pea->value.data = (unsigned char *)val;
160 pea->value.length = (size_t)sizeret;
164 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
165 files_struct *fsp, const char *fname,
166 char ***pnames, size_t *pnum_names)
168 /* Get a list of all xattrs. Max namesize is 64k. */
169 size_t ea_namelist_size = 1024;
170 char *ea_namelist = NULL;
175 ssize_t sizeret = -1;
177 if (!lp_ea_support(SNUM(conn))) {
186 * TALLOC the result early to get the talloc hierarchy right.
189 names = TALLOC_ARRAY(mem_ctx, char *, 1);
191 DEBUG(0, ("talloc failed\n"));
192 return NT_STATUS_NO_MEMORY;
195 while (ea_namelist_size <= 65536) {
197 ea_namelist = TALLOC_REALLOC_ARRAY(
198 names, ea_namelist, char, ea_namelist_size);
199 if (ea_namelist == NULL) {
200 DEBUG(0, ("talloc failed\n"));
202 return NT_STATUS_NO_MEMORY;
205 if (fsp && fsp->fh->fd != -1) {
206 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
209 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
213 if ((sizeret == -1) && (errno == ERANGE)) {
214 ea_namelist_size *= 2;
223 return map_nt_error_from_unix(errno);
226 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
227 (unsigned int)sizeret));
239 * Ensure the result is 0-terminated
242 if (ea_namelist[sizeret-1] != '\0') {
244 return NT_STATUS_INTERNAL_ERROR;
252 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
256 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
258 DEBUG(0, ("talloc failed\n"));
260 return NT_STATUS_NO_MEMORY;
266 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
267 names[num_names++] = p;
275 *pnum_names = num_names;
279 /****************************************************************************
280 Return a linked list of the total EA's. Plus the total size
281 ****************************************************************************/
283 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
284 const char *fname, size_t *pea_total_len)
286 /* Get a list of all xattrs. Max namesize is 64k. */
289 struct ea_list *ea_list_head = NULL;
294 if (!lp_ea_support(SNUM(conn))) {
298 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
301 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
305 for (i=0; i<num_names; i++) {
306 struct ea_list *listp;
309 if (strnequal(names[i], "system.", 7)
310 || samba_private_attr_name(names[i]))
313 listp = TALLOC_P(mem_ctx, struct ea_list);
318 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
324 push_ascii_fstring(dos_ea_name, listp->ea.name);
327 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
329 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
330 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
331 (unsigned int)listp->ea.value.length));
333 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
337 /* Add on 4 for total length. */
338 if (*pea_total_len) {
342 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
343 (unsigned int)*pea_total_len));
348 /****************************************************************************
349 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
351 ****************************************************************************/
353 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
354 connection_struct *conn, struct ea_list *ea_list)
356 unsigned int ret_data_size = 4;
359 SMB_ASSERT(total_data_size >= 4);
361 if (!lp_ea_support(SNUM(conn))) {
366 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
369 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
370 dos_namelen = strlen(dos_ea_name);
371 if (dos_namelen > 255 || dos_namelen == 0) {
374 if (ea_list->ea.value.length > 65535) {
377 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
381 /* We know we have room. */
382 SCVAL(p,0,ea_list->ea.flags);
383 SCVAL(p,1,dos_namelen);
384 SSVAL(p,2,ea_list->ea.value.length);
385 fstrcpy(p+4, dos_ea_name);
386 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
388 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
392 ret_data_size = PTR_DIFF(p, pdata);
393 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
394 SIVAL(pdata,0,ret_data_size);
395 return ret_data_size;
398 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
400 unsigned int total_data_size,
401 unsigned int *ret_data_size,
402 connection_struct *conn,
403 struct ea_list *ea_list)
405 uint8_t *p = (uint8_t *)pdata;
406 uint8_t *last_start = NULL;
410 if (!lp_ea_support(SNUM(conn))) {
411 return NT_STATUS_NO_EAS_ON_FILE;
414 for (; ea_list; ea_list = ea_list->next) {
420 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
424 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
425 dos_namelen = strlen(dos_ea_name);
426 if (dos_namelen > 255 || dos_namelen == 0) {
427 return NT_STATUS_INTERNAL_ERROR;
429 if (ea_list->ea.value.length > 65535) {
430 return NT_STATUS_INTERNAL_ERROR;
433 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
436 size_t pad = 4 - (this_size % 4);
440 if (this_size > total_data_size) {
441 return NT_STATUS_INFO_LENGTH_MISMATCH;
444 /* We know we have room. */
445 SIVAL(p, 0x00, 0); /* next offset */
446 SCVAL(p, 0x04, ea_list->ea.flags);
447 SCVAL(p, 0x05, dos_namelen);
448 SSVAL(p, 0x06, ea_list->ea.value.length);
449 fstrcpy((char *)(p+0x08), dos_ea_name);
450 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
452 total_data_size -= this_size;
456 *ret_data_size = PTR_DIFF(p, pdata);
457 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
461 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
463 size_t total_ea_len = 0;
464 TALLOC_CTX *mem_ctx = NULL;
466 if (!lp_ea_support(SNUM(conn))) {
469 mem_ctx = talloc_tos();
470 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
474 /****************************************************************************
475 Ensure the EA name is case insensitive by matching any existing EA name.
476 ****************************************************************************/
478 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
481 TALLOC_CTX *mem_ctx = talloc_tos();
482 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
484 for (; ea_list; ea_list = ea_list->next) {
485 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
486 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
487 &unix_ea_name[5], ea_list->ea.name));
488 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
494 /****************************************************************************
495 Set or delete an extended attribute.
496 ****************************************************************************/
498 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
499 const struct smb_filename *smb_fname, struct ea_list *ea_list)
503 if (!lp_ea_support(SNUM(conn))) {
504 return NT_STATUS_EAS_NOT_SUPPORTED;
507 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
508 return NT_STATUS_ACCESS_DENIED;
511 /* For now setting EAs on streams isn't supported. */
512 fname = smb_fname->base_name;
514 for (;ea_list; ea_list = ea_list->next) {
516 fstring unix_ea_name;
518 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
519 fstrcat(unix_ea_name, ea_list->ea.name);
521 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
523 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
525 if (samba_private_attr_name(unix_ea_name)) {
526 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
527 return NT_STATUS_ACCESS_DENIED;
530 if (ea_list->ea.value.length == 0) {
531 /* Remove the attribute. */
532 if (fsp && (fsp->fh->fd != -1)) {
533 DEBUG(10,("set_ea: deleting ea name %s on "
534 "file %s by file descriptor.\n",
535 unix_ea_name, fsp_str_dbg(fsp)));
536 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
538 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
539 unix_ea_name, fname));
540 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
543 /* Removing a non existent attribute always succeeds. */
544 if (ret == -1 && errno == ENOATTR) {
545 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
551 if (fsp && (fsp->fh->fd != -1)) {
552 DEBUG(10,("set_ea: setting ea name %s on file "
553 "%s by file descriptor.\n",
554 unix_ea_name, fsp_str_dbg(fsp)));
555 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
556 ea_list->ea.value.data, ea_list->ea.value.length, 0);
558 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
559 unix_ea_name, fname));
560 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
561 ea_list->ea.value.data, ea_list->ea.value.length, 0);
567 if (errno == ENOTSUP) {
568 return NT_STATUS_EAS_NOT_SUPPORTED;
571 return map_nt_error_from_unix(errno);
577 /****************************************************************************
578 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
579 ****************************************************************************/
581 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
583 struct ea_list *ea_list_head = NULL;
584 size_t converted_size, offset = 0;
586 while (offset + 2 < data_size) {
587 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
588 unsigned int namelen = CVAL(pdata,offset);
590 offset++; /* Go past the namelen byte. */
592 /* integer wrap paranioa. */
593 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
594 (offset > data_size) || (namelen > data_size) ||
595 (offset + namelen >= data_size)) {
598 /* Ensure the name is null terminated. */
599 if (pdata[offset + namelen] != '\0') {
602 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
604 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
605 "failed: %s", strerror(errno)));
611 offset += (namelen + 1); /* Go past the name + terminating zero. */
612 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
613 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
619 /****************************************************************************
620 Read one EA list entry from the buffer.
621 ****************************************************************************/
623 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
625 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
627 unsigned int namelen;
628 size_t converted_size;
638 eal->ea.flags = CVAL(pdata,0);
639 namelen = CVAL(pdata,1);
640 val_len = SVAL(pdata,2);
642 if (4 + namelen + 1 + val_len > data_size) {
646 /* Ensure the name is null terminated. */
647 if (pdata[namelen + 4] != '\0') {
650 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
651 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
658 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
659 if (!eal->ea.value.data) {
663 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
665 /* Ensure we're null terminated just in case we print the value. */
666 eal->ea.value.data[val_len] = '\0';
667 /* But don't count the null. */
668 eal->ea.value.length--;
671 *pbytes_used = 4 + namelen + 1 + val_len;
674 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
675 dump_data(10, eal->ea.value.data, eal->ea.value.length);
680 /****************************************************************************
681 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
682 ****************************************************************************/
684 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
686 struct ea_list *ea_list_head = NULL;
688 size_t bytes_used = 0;
690 while (offset < data_size) {
691 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
697 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
698 offset += bytes_used;
704 /****************************************************************************
705 Count the total EA size needed.
706 ****************************************************************************/
708 static size_t ea_list_size(struct ea_list *ealist)
711 struct ea_list *listp;
714 for (listp = ealist; listp; listp = listp->next) {
715 push_ascii_fstring(dos_ea_name, listp->ea.name);
716 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
718 /* Add on 4 for total length. */
726 /****************************************************************************
727 Return a union of EA's from a file list and a list of names.
728 The TALLOC context for the two lists *MUST* be identical as we steal
729 memory from one list to add to another. JRA.
730 ****************************************************************************/
732 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
734 struct ea_list *nlistp, *flistp;
736 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
737 for (flistp = file_list; flistp; flistp = flistp->next) {
738 if (strequal(nlistp->ea.name, flistp->ea.name)) {
744 /* Copy the data from this entry. */
745 nlistp->ea.flags = flistp->ea.flags;
746 nlistp->ea.value = flistp->ea.value;
749 nlistp->ea.flags = 0;
750 ZERO_STRUCT(nlistp->ea.value);
754 *total_ea_len = ea_list_size(name_list);
758 /****************************************************************************
759 Send the required number of replies back.
760 We assume all fields other than the data fields are
761 set correctly for the type of call.
762 HACK ! Always assumes smb_setup field is zero.
763 ****************************************************************************/
765 void send_trans2_replies(connection_struct *conn,
766 struct smb_request *req,
773 /* As we are using a protocol > LANMAN1 then the max_send
774 variable must have been set in the sessetupX call.
775 This takes precedence over the max_xmit field in the
776 global struct. These different max_xmit variables should
777 be merged as this is now too confusing */
779 int data_to_send = datasize;
780 int params_to_send = paramsize;
782 const char *pp = params;
783 const char *pd = pdata;
784 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
785 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
786 int data_alignment_offset = 0;
787 bool overflow = False;
788 struct smbd_server_connection *sconn = req->sconn;
789 int max_send = sconn->smb1.sessions.max_send;
791 /* Modify the data_to_send and datasize and set the error if
792 we're trying to send more than max_data_bytes. We still send
793 the part of the packet(s) that fit. Strange, but needed
796 if (max_data_bytes > 0 && datasize > max_data_bytes) {
797 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
798 max_data_bytes, datasize ));
799 datasize = data_to_send = max_data_bytes;
803 /* If there genuinely are no parameters or data to send just send the empty packet */
805 if(params_to_send == 0 && data_to_send == 0) {
806 reply_outbuf(req, 10, 0);
807 show_msg((char *)req->outbuf);
808 if (!srv_send_smb(sconn,
811 IS_CONN_ENCRYPTED(conn),
813 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
815 TALLOC_FREE(req->outbuf);
819 /* When sending params and data ensure that both are nicely aligned */
820 /* Only do this alignment when there is also data to send - else
821 can cause NT redirector problems. */
823 if (((params_to_send % 4) != 0) && (data_to_send != 0))
824 data_alignment_offset = 4 - (params_to_send % 4);
826 /* Space is bufsize minus Netbios over TCP header minus SMB header */
827 /* The alignment_offset is to align the param bytes on an even byte
828 boundary. NT 4.0 Beta needs this to work correctly. */
830 useable_space = max_send - (smb_size
833 + data_alignment_offset);
835 if (useable_space < 0) {
836 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
837 "= %d!!!", useable_space));
838 exit_server_cleanly("send_trans2_replies: Not enough space");
841 while (params_to_send || data_to_send) {
842 /* Calculate whether we will totally or partially fill this packet */
844 total_sent_thistime = params_to_send + data_to_send;
846 /* We can never send more than useable_space */
848 * Note that 'useable_space' does not include the alignment offsets,
849 * but we must include the alignment offsets in the calculation of
850 * the length of the data we send over the wire, as the alignment offsets
851 * are sent here. Fix from Marc_Jacobsen@hp.com.
854 total_sent_thistime = MIN(total_sent_thistime, useable_space);
856 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
857 + data_alignment_offset);
860 * We might have SMBtrans2s in req which was transferred to
861 * the outbuf, fix that.
863 SCVAL(req->outbuf, smb_com, SMBtrans2);
865 /* Set total params and data to be sent */
866 SSVAL(req->outbuf,smb_tprcnt,paramsize);
867 SSVAL(req->outbuf,smb_tdrcnt,datasize);
869 /* Calculate how many parameters and data we can fit into
870 * this packet. Parameters get precedence
873 params_sent_thistime = MIN(params_to_send,useable_space);
874 data_sent_thistime = useable_space - params_sent_thistime;
875 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
877 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
879 /* smb_proff is the offset from the start of the SMB header to the
880 parameter bytes, however the first 4 bytes of outbuf are
881 the Netbios over TCP header. Thus use smb_base() to subtract
882 them from the calculation */
884 SSVAL(req->outbuf,smb_proff,
885 ((smb_buf(req->outbuf)+alignment_offset)
886 - smb_base(req->outbuf)));
888 if(params_sent_thistime == 0)
889 SSVAL(req->outbuf,smb_prdisp,0);
891 /* Absolute displacement of param bytes sent in this packet */
892 SSVAL(req->outbuf,smb_prdisp,pp - params);
894 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
895 if(data_sent_thistime == 0) {
896 SSVAL(req->outbuf,smb_droff,0);
897 SSVAL(req->outbuf,smb_drdisp, 0);
899 /* The offset of the data bytes is the offset of the
900 parameter bytes plus the number of parameters being sent this time */
901 SSVAL(req->outbuf, smb_droff,
902 ((smb_buf(req->outbuf)+alignment_offset)
903 - smb_base(req->outbuf))
904 + params_sent_thistime + data_alignment_offset);
905 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
908 /* Initialize the padding for alignment */
910 if (alignment_offset != 0) {
911 memset(smb_buf(req->outbuf), 0, alignment_offset);
914 /* Copy the param bytes into the packet */
916 if(params_sent_thistime) {
917 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
918 params_sent_thistime);
921 /* Copy in the data bytes */
922 if(data_sent_thistime) {
923 if (data_alignment_offset != 0) {
924 memset((smb_buf(req->outbuf)+alignment_offset+
925 params_sent_thistime), 0,
926 data_alignment_offset);
928 memcpy(smb_buf(req->outbuf)+alignment_offset
929 +params_sent_thistime+data_alignment_offset,
930 pd,data_sent_thistime);
933 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
934 params_sent_thistime, data_sent_thistime, useable_space));
935 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
936 params_to_send, data_to_send, paramsize, datasize));
939 error_packet_set((char *)req->outbuf,
940 ERRDOS,ERRbufferoverflow,
941 STATUS_BUFFER_OVERFLOW,
945 /* Send the packet */
946 show_msg((char *)req->outbuf);
947 if (!srv_send_smb(sconn,
950 IS_CONN_ENCRYPTED(conn),
952 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
954 TALLOC_FREE(req->outbuf);
956 pp += params_sent_thistime;
957 pd += data_sent_thistime;
959 params_to_send -= params_sent_thistime;
960 data_to_send -= data_sent_thistime;
963 if(params_to_send < 0 || data_to_send < 0) {
964 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
965 params_to_send, data_to_send));
973 /****************************************************************************
974 Reply to a TRANSACT2_OPEN.
975 ****************************************************************************/
977 static void call_trans2open(connection_struct *conn,
978 struct smb_request *req,
979 char **pparams, int total_params,
980 char **ppdata, int total_data,
981 unsigned int max_data_bytes)
983 struct smb_filename *smb_fname = NULL;
984 char *params = *pparams;
985 char *pdata = *ppdata;
990 bool return_additional_info;
1000 SMB_INO_T inode = 0;
1003 struct ea_list *ea_list = NULL;
1008 uint32 create_disposition;
1009 uint32 create_options = 0;
1010 uint32_t private_flags = 0;
1011 TALLOC_CTX *ctx = talloc_tos();
1014 * Ensure we have enough parameters to perform the operation.
1017 if (total_params < 29) {
1018 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1022 flags = SVAL(params, 0);
1023 deny_mode = SVAL(params, 2);
1024 open_attr = SVAL(params,6);
1025 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1026 if (oplock_request) {
1027 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1031 return_additional_info = BITSETW(params,0);
1032 open_sattr = SVAL(params, 4);
1033 open_time = make_unix_date3(params+8);
1035 open_ofun = SVAL(params,12);
1036 open_size = IVAL(params,14);
1037 pname = ¶ms[28];
1040 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1044 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1045 total_params - 28, STR_TERMINATE,
1047 if (!NT_STATUS_IS_OK(status)) {
1048 reply_nterror(req, status);
1052 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1053 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1054 (unsigned int)open_ofun, open_size));
1056 status = filename_convert(ctx,
1058 req->flags2 & FLAGS2_DFS_PATHNAMES,
1063 if (!NT_STATUS_IS_OK(status)) {
1064 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1065 reply_botherror(req,
1066 NT_STATUS_PATH_NOT_COVERED,
1067 ERRSRV, ERRbadpath);
1070 reply_nterror(req, status);
1074 if (open_ofun == 0) {
1075 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1079 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1080 &access_mask, &share_mode,
1081 &create_disposition,
1084 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1088 /* Any data in this call is an EA list. */
1089 if (total_data && (total_data != 4)) {
1090 if (total_data < 10) {
1091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1095 if (IVAL(pdata,0) > total_data) {
1096 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1097 IVAL(pdata,0), (unsigned int)total_data));
1098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1102 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1109 if (!lp_ea_support(SNUM(conn))) {
1110 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1115 status = SMB_VFS_CREATE_FILE(
1118 0, /* root_dir_fid */
1119 smb_fname, /* fname */
1120 access_mask, /* access_mask */
1121 share_mode, /* share_access */
1122 create_disposition, /* create_disposition*/
1123 create_options, /* create_options */
1124 open_attr, /* file_attributes */
1125 oplock_request, /* oplock_request */
1126 open_size, /* allocation_size */
1129 ea_list, /* ea_list */
1131 &smb_action); /* psbuf */
1133 if (!NT_STATUS_IS_OK(status)) {
1134 if (open_was_deferred(req->mid)) {
1135 /* We have re-scheduled this call. */
1138 reply_openerror(req, status);
1142 size = get_file_size_stat(&smb_fname->st);
1143 fattr = dos_mode(conn, smb_fname);
1144 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1145 inode = smb_fname->st.st_ex_ino;
1147 close_file(req, fsp, ERROR_CLOSE);
1148 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1152 /* Realloc the size of parameters and data we will return */
1153 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1154 if(*pparams == NULL ) {
1155 reply_nterror(req, NT_STATUS_NO_MEMORY);
1160 SSVAL(params,0,fsp->fnum);
1161 SSVAL(params,2,fattr);
1162 srv_put_dos_date2(params,4, mtime);
1163 SIVAL(params,8, (uint32)size);
1164 SSVAL(params,12,deny_mode);
1165 SSVAL(params,14,0); /* open_type - file or directory. */
1166 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1168 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1169 smb_action |= EXTENDED_OPLOCK_GRANTED;
1172 SSVAL(params,18,smb_action);
1175 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1177 SIVAL(params,20,inode);
1178 SSVAL(params,24,0); /* Padding. */
1180 uint32 ea_size = estimate_ea_size(conn, fsp,
1181 fsp->fsp_name->base_name);
1182 SIVAL(params, 26, ea_size);
1184 SIVAL(params, 26, 0);
1187 /* Send the required number of replies */
1188 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1190 TALLOC_FREE(smb_fname);
1193 /*********************************************************
1194 Routine to check if a given string matches exactly.
1195 as a special case a mask of "." does NOT match. That
1196 is required for correct wildcard semantics
1197 Case can be significant or not.
1198 **********************************************************/
1200 static bool exact_match(bool has_wild,
1201 bool case_sensitive,
1205 if (mask[0] == '.' && mask[1] == 0) {
1213 if (case_sensitive) {
1214 return strcmp(str,mask)==0;
1216 return StrCaseCmp(str,mask) == 0;
1220 /****************************************************************************
1221 Return the filetype for UNIX extensions.
1222 ****************************************************************************/
1224 static uint32 unix_filetype(mode_t mode)
1227 return UNIX_TYPE_FILE;
1228 else if(S_ISDIR(mode))
1229 return UNIX_TYPE_DIR;
1231 else if(S_ISLNK(mode))
1232 return UNIX_TYPE_SYMLINK;
1235 else if(S_ISCHR(mode))
1236 return UNIX_TYPE_CHARDEV;
1239 else if(S_ISBLK(mode))
1240 return UNIX_TYPE_BLKDEV;
1243 else if(S_ISFIFO(mode))
1244 return UNIX_TYPE_FIFO;
1247 else if(S_ISSOCK(mode))
1248 return UNIX_TYPE_SOCKET;
1251 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1252 return UNIX_TYPE_UNKNOWN;
1255 /****************************************************************************
1256 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1257 ****************************************************************************/
1259 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1261 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1262 const SMB_STRUCT_STAT *psbuf,
1264 enum perm_type ptype,
1269 if (perms == SMB_MODE_NO_CHANGE) {
1270 if (!VALID_STAT(*psbuf)) {
1271 return NT_STATUS_INVALID_PARAMETER;
1273 *ret_perms = psbuf->st_ex_mode;
1274 return NT_STATUS_OK;
1278 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1279 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1280 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1281 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1282 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1283 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1284 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1285 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1286 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1288 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1291 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1294 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1299 /* Apply mode mask */
1300 ret &= lp_create_mask(SNUM(conn));
1301 /* Add in force bits */
1302 ret |= lp_force_create_mode(SNUM(conn));
1305 ret &= lp_dir_mask(SNUM(conn));
1306 /* Add in force bits */
1307 ret |= lp_force_dir_mode(SNUM(conn));
1309 case PERM_EXISTING_FILE:
1310 /* Apply mode mask */
1311 ret &= lp_security_mask(SNUM(conn));
1312 /* Add in force bits */
1313 ret |= lp_force_security_mode(SNUM(conn));
1315 case PERM_EXISTING_DIR:
1316 /* Apply mode mask */
1317 ret &= lp_dir_security_mask(SNUM(conn));
1318 /* Add in force bits */
1319 ret |= lp_force_dir_security_mode(SNUM(conn));
1324 return NT_STATUS_OK;
1327 /****************************************************************************
1328 Needed to show the msdfs symlinks as directories. Modifies psbuf
1329 to be a directory if it's a msdfs link.
1330 ****************************************************************************/
1332 static bool check_msdfs_link(connection_struct *conn,
1333 const char *pathname,
1334 SMB_STRUCT_STAT *psbuf)
1336 int saved_errno = errno;
1337 if(lp_host_msdfs() &&
1338 lp_msdfs_root(SNUM(conn)) &&
1339 is_msdfs_link(conn, pathname, psbuf)) {
1341 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1344 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1345 errno = saved_errno;
1348 errno = saved_errno;
1353 /****************************************************************************
1354 Get a level dependent lanman2 dir entry.
1355 ****************************************************************************/
1357 struct smbd_dirptr_lanman2_state {
1358 connection_struct *conn;
1359 uint32_t info_level;
1360 bool check_mangled_names;
1362 bool got_exact_match;
1365 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1371 struct smbd_dirptr_lanman2_state *state =
1372 (struct smbd_dirptr_lanman2_state *)private_data;
1374 char mangled_name[13]; /* mangled 8.3 name. */
1378 /* Mangle fname if it's an illegal name. */
1379 if (mangle_must_mangle(dname, state->conn->params)) {
1380 ok = name_to_8_3(dname, mangled_name,
1381 true, state->conn->params);
1385 fname = mangled_name;
1390 got_match = exact_match(state->has_wild,
1391 state->conn->case_sensitive,
1393 state->got_exact_match = got_match;
1395 got_match = mask_match(fname, mask,
1396 state->conn->case_sensitive);
1399 if(!got_match && state->check_mangled_names &&
1400 !mangle_is_8_3(fname, false, state->conn->params)) {
1402 * It turns out that NT matches wildcards against
1403 * both long *and* short names. This may explain some
1404 * of the wildcard wierdness from old DOS clients
1405 * that some people have been seeing.... JRA.
1407 /* Force the mangling into 8.3. */
1408 ok = name_to_8_3(fname, mangled_name,
1409 false, state->conn->params);
1414 got_match = exact_match(state->has_wild,
1415 state->conn->case_sensitive,
1416 mangled_name, mask);
1417 state->got_exact_match = got_match;
1419 got_match = mask_match(mangled_name, mask,
1420 state->conn->case_sensitive);
1428 *_fname = talloc_strdup(ctx, fname);
1429 if (*_fname == NULL) {
1436 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1438 struct smb_filename *smb_fname,
1441 struct smbd_dirptr_lanman2_state *state =
1442 (struct smbd_dirptr_lanman2_state *)private_data;
1443 bool ms_dfs_link = false;
1446 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1447 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1448 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1449 "Couldn't lstat [%s] (%s)\n",
1450 smb_fname_str_dbg(smb_fname),
1454 } else if (!VALID_STAT(smb_fname->st) &&
1455 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1456 /* Needed to show the msdfs symlinks as
1459 ms_dfs_link = check_msdfs_link(state->conn,
1460 smb_fname->base_name,
1463 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1464 "Couldn't stat [%s] (%s)\n",
1465 smb_fname_str_dbg(smb_fname),
1472 mode = dos_mode_msdfs(state->conn, smb_fname);
1474 mode = dos_mode(state->conn, smb_fname);
1481 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1482 connection_struct *conn,
1484 uint32_t info_level,
1485 struct ea_list *name_list,
1486 bool check_mangled_names,
1487 bool requires_resume_key,
1490 const struct smb_filename *smb_fname,
1491 int space_remaining,
1498 uint64_t *last_entry_off)
1500 char *p, *q, *pdata = *ppdata;
1502 uint64_t file_size = 0;
1503 uint64_t allocation_size = 0;
1504 uint64_t file_index = 0;
1506 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1507 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1508 time_t c_date = (time_t)0;
1510 char *last_entry_ptr;
1515 *out_of_space = false;
1517 ZERO_STRUCT(mdate_ts);
1518 ZERO_STRUCT(adate_ts);
1519 ZERO_STRUCT(create_date_ts);
1520 ZERO_STRUCT(cdate_ts);
1522 if (!(mode & aDIR)) {
1523 file_size = get_file_size_stat(&smb_fname->st);
1525 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1527 file_index = get_FileIndex(conn, &smb_fname->st);
1529 mdate_ts = smb_fname->st.st_ex_mtime;
1530 adate_ts = smb_fname->st.st_ex_atime;
1531 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1532 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1534 if (lp_dos_filetime_resolution(SNUM(conn))) {
1535 dos_filetime_timespec(&create_date_ts);
1536 dos_filetime_timespec(&mdate_ts);
1537 dos_filetime_timespec(&adate_ts);
1538 dos_filetime_timespec(&cdate_ts);
1541 create_date = convert_timespec_to_time_t(create_date_ts);
1542 mdate = convert_timespec_to_time_t(mdate_ts);
1543 adate = convert_timespec_to_time_t(adate_ts);
1544 c_date = convert_timespec_to_time_t(cdate_ts);
1546 /* align the record */
1547 SMB_ASSERT(align >= 1);
1549 off = (int)PTR_DIFF(pdata, base_data);
1550 pad = (off + (align-1)) & ~(align-1);
1553 if (pad && pad > space_remaining) {
1554 *out_of_space = true;
1555 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1556 "for padding (wanted %u, had %d)\n",
1559 return false; /* Not finished - just out of space */
1563 /* initialize padding to 0 */
1565 memset(pdata, 0, pad);
1567 space_remaining -= pad;
1569 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1579 switch (info_level) {
1580 case SMB_FIND_INFO_STANDARD:
1581 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1582 if(requires_resume_key) {
1586 srv_put_dos_date2(p,0,create_date);
1587 srv_put_dos_date2(p,4,adate);
1588 srv_put_dos_date2(p,8,mdate);
1589 SIVAL(p,12,(uint32)file_size);
1590 SIVAL(p,16,(uint32)allocation_size);
1594 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1595 p += ucs2_align(base_data, p, 0);
1597 len = srvstr_push(base_data, flags2, p,
1598 fname, PTR_DIFF(end_data, p),
1600 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1602 SCVAL(nameptr, -1, len - 2);
1604 SCVAL(nameptr, -1, 0);
1608 SCVAL(nameptr, -1, len - 1);
1610 SCVAL(nameptr, -1, 0);
1616 case SMB_FIND_EA_SIZE:
1617 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1618 if (requires_resume_key) {
1622 srv_put_dos_date2(p,0,create_date);
1623 srv_put_dos_date2(p,4,adate);
1624 srv_put_dos_date2(p,8,mdate);
1625 SIVAL(p,12,(uint32)file_size);
1626 SIVAL(p,16,(uint32)allocation_size);
1629 unsigned int ea_size = estimate_ea_size(conn, NULL,
1630 smb_fname->base_name);
1631 SIVAL(p,22,ea_size); /* Extended attributes */
1635 len = srvstr_push(base_data, flags2,
1636 p, fname, PTR_DIFF(end_data, p),
1637 STR_TERMINATE | STR_NOALIGN);
1638 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1651 SCVAL(nameptr,0,len);
1653 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1656 case SMB_FIND_EA_LIST:
1658 struct ea_list *file_list = NULL;
1661 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1665 if (requires_resume_key) {
1669 srv_put_dos_date2(p,0,create_date);
1670 srv_put_dos_date2(p,4,adate);
1671 srv_put_dos_date2(p,8,mdate);
1672 SIVAL(p,12,(uint32)file_size);
1673 SIVAL(p,16,(uint32)allocation_size);
1675 p += 22; /* p now points to the EA area. */
1677 file_list = get_ea_list_from_file(ctx, conn, NULL,
1678 smb_fname->base_name,
1680 name_list = ea_list_union(name_list, file_list, &ea_len);
1682 /* We need to determine if this entry will fit in the space available. */
1683 /* Max string size is 255 bytes. */
1684 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1685 *out_of_space = true;
1686 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1687 "(wanted %u, had %d)\n",
1688 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1690 return False; /* Not finished - just out of space */
1693 /* Push the ea_data followed by the name. */
1694 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1696 len = srvstr_push(base_data, flags2,
1697 p + 1, fname, PTR_DIFF(end_data, p+1),
1698 STR_TERMINATE | STR_NOALIGN);
1699 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1712 SCVAL(nameptr,0,len);
1714 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1718 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1719 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1720 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1722 SIVAL(p,0,reskey); p += 4;
1723 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1724 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1725 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1726 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1727 SOFF_T(p,0,file_size); p += 8;
1728 SOFF_T(p,0,allocation_size); p += 8;
1729 SIVAL(p,0,mode); p += 4;
1730 q = p; p += 4; /* q is placeholder for name length. */
1732 unsigned int ea_size = estimate_ea_size(conn, NULL,
1733 smb_fname->base_name);
1734 SIVAL(p,0,ea_size); /* Extended attributes */
1737 /* Clear the short name buffer. This is
1738 * IMPORTANT as not doing so will trigger
1739 * a Win2k client bug. JRA.
1741 if (!was_8_3 && check_mangled_names) {
1742 char mangled_name[13]; /* mangled 8.3 name. */
1743 if (!name_to_8_3(fname,mangled_name,True,
1745 /* Error - mangle failed ! */
1746 memset(mangled_name,'\0',12);
1748 mangled_name[12] = 0;
1749 len = srvstr_push(base_data, flags2,
1750 p+2, mangled_name, 24,
1751 STR_UPPER|STR_UNICODE);
1753 memset(p + 2 + len,'\0',24 - len);
1760 len = srvstr_push(base_data, flags2, p,
1761 fname, PTR_DIFF(end_data, p),
1762 STR_TERMINATE_ASCII);
1766 len = PTR_DIFF(p, pdata);
1767 pad = (len + (align-1)) & ~(align-1);
1769 * offset to the next entry, the caller
1770 * will overwrite it for the last entry
1771 * that's why we always include the padding
1775 * set padding to zero
1778 memset(p, 0, pad - len);
1785 case SMB_FIND_FILE_DIRECTORY_INFO:
1786 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1788 SIVAL(p,0,reskey); p += 4;
1789 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1790 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1791 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1792 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1793 SOFF_T(p,0,file_size); p += 8;
1794 SOFF_T(p,0,allocation_size); p += 8;
1795 SIVAL(p,0,mode); p += 4;
1796 len = srvstr_push(base_data, flags2,
1797 p + 4, fname, PTR_DIFF(end_data, p+4),
1798 STR_TERMINATE_ASCII);
1802 len = PTR_DIFF(p, pdata);
1803 pad = (len + (align-1)) & ~(align-1);
1805 * offset to the next entry, the caller
1806 * will overwrite it for the last entry
1807 * that's why we always include the padding
1811 * set padding to zero
1814 memset(p, 0, pad - len);
1821 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1822 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1824 SIVAL(p,0,reskey); p += 4;
1825 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1826 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1827 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1828 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1829 SOFF_T(p,0,file_size); p += 8;
1830 SOFF_T(p,0,allocation_size); p += 8;
1831 SIVAL(p,0,mode); p += 4;
1832 q = p; p += 4; /* q is placeholder for name length. */
1834 unsigned int ea_size = estimate_ea_size(conn, NULL,
1835 smb_fname->base_name);
1836 SIVAL(p,0,ea_size); /* Extended attributes */
1839 len = srvstr_push(base_data, flags2, p,
1840 fname, PTR_DIFF(end_data, p),
1841 STR_TERMINATE_ASCII);
1845 len = PTR_DIFF(p, pdata);
1846 pad = (len + (align-1)) & ~(align-1);
1848 * offset to the next entry, the caller
1849 * will overwrite it for the last entry
1850 * that's why we always include the padding
1854 * set padding to zero
1857 memset(p, 0, pad - len);
1864 case SMB_FIND_FILE_NAMES_INFO:
1865 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1867 SIVAL(p,0,reskey); p += 4;
1869 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1870 acl on a dir (tridge) */
1871 len = srvstr_push(base_data, flags2, p,
1872 fname, PTR_DIFF(end_data, p),
1873 STR_TERMINATE_ASCII);
1877 len = PTR_DIFF(p, pdata);
1878 pad = (len + (align-1)) & ~(align-1);
1880 * offset to the next entry, the caller
1881 * will overwrite it for the last entry
1882 * that's why we always include the padding
1886 * set padding to zero
1889 memset(p, 0, pad - len);
1896 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1897 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1899 SIVAL(p,0,reskey); p += 4;
1900 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1901 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1902 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1903 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1904 SOFF_T(p,0,file_size); p += 8;
1905 SOFF_T(p,0,allocation_size); p += 8;
1906 SIVAL(p,0,mode); p += 4;
1907 q = p; p += 4; /* q is placeholder for name length. */
1909 unsigned int ea_size = estimate_ea_size(conn, NULL,
1910 smb_fname->base_name);
1911 SIVAL(p,0,ea_size); /* Extended attributes */
1914 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1915 SBVAL(p,0,file_index); p += 8;
1916 len = srvstr_push(base_data, flags2, p,
1917 fname, PTR_DIFF(end_data, p),
1918 STR_TERMINATE_ASCII);
1922 len = PTR_DIFF(p, pdata);
1923 pad = (len + (align-1)) & ~(align-1);
1925 * offset to the next entry, the caller
1926 * will overwrite it for the last entry
1927 * that's why we always include the padding
1931 * set padding to zero
1934 memset(p, 0, pad - len);
1941 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1942 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1943 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1945 SIVAL(p,0,reskey); p += 4;
1946 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1947 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1948 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1949 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1950 SOFF_T(p,0,file_size); p += 8;
1951 SOFF_T(p,0,allocation_size); p += 8;
1952 SIVAL(p,0,mode); p += 4;
1953 q = p; p += 4; /* q is placeholder for name length */
1955 unsigned int ea_size = estimate_ea_size(conn, NULL,
1956 smb_fname->base_name);
1957 SIVAL(p,0,ea_size); /* Extended attributes */
1960 /* Clear the short name buffer. This is
1961 * IMPORTANT as not doing so will trigger
1962 * a Win2k client bug. JRA.
1964 if (!was_8_3 && check_mangled_names) {
1965 char mangled_name[13]; /* mangled 8.3 name. */
1966 if (!name_to_8_3(fname,mangled_name,True,
1968 /* Error - mangle failed ! */
1969 memset(mangled_name,'\0',12);
1971 mangled_name[12] = 0;
1972 len = srvstr_push(base_data, flags2,
1973 p+2, mangled_name, 24,
1974 STR_UPPER|STR_UNICODE);
1977 memset(p + 2 + len,'\0',24 - len);
1984 SSVAL(p,0,0); p += 2; /* Reserved ? */
1985 SBVAL(p,0,file_index); p += 8;
1986 len = srvstr_push(base_data, flags2, p,
1987 fname, PTR_DIFF(end_data, p),
1988 STR_TERMINATE_ASCII);
1992 len = PTR_DIFF(p, pdata);
1993 pad = (len + (align-1)) & ~(align-1);
1995 * offset to the next entry, the caller
1996 * will overwrite it for the last entry
1997 * that's why we always include the padding
2001 * set padding to zero
2004 memset(p, 0, pad - len);
2011 /* CIFS UNIX Extension. */
2013 case SMB_FIND_FILE_UNIX:
2014 case SMB_FIND_FILE_UNIX_INFO2:
2016 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2018 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2020 if (info_level == SMB_FIND_FILE_UNIX) {
2021 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2022 p = store_file_unix_basic(conn, p,
2023 NULL, &smb_fname->st);
2024 len = srvstr_push(base_data, flags2, p,
2025 fname, PTR_DIFF(end_data, p),
2028 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2029 p = store_file_unix_basic_info2(conn, p,
2030 NULL, &smb_fname->st);
2033 len = srvstr_push(base_data, flags2, p, fname,
2034 PTR_DIFF(end_data, p), 0);
2035 SIVAL(nameptr, 0, len);
2040 len = PTR_DIFF(p, pdata);
2041 pad = (len + (align-1)) & ~(align-1);
2043 * offset to the next entry, the caller
2044 * will overwrite it for the last entry
2045 * that's why we always include the padding
2049 * set padding to zero
2052 memset(p, 0, pad - len);
2057 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2065 if (PTR_DIFF(p,pdata) > space_remaining) {
2066 *out_of_space = true;
2067 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2068 "(wanted %u, had %d)\n",
2069 (unsigned int)PTR_DIFF(p,pdata),
2071 return false; /* Not finished - just out of space */
2074 /* Setup the last entry pointer, as an offset from base_data */
2075 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2076 /* Advance the data pointer to the next slot */
2082 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2083 connection_struct *conn,
2084 struct dptr_struct *dirptr,
2086 const char *path_mask,
2089 int requires_resume_key,
2097 int space_remaining,
2099 bool *got_exact_match,
2100 int *_last_entry_off,
2101 struct ea_list *name_list)
2104 const char *mask = NULL;
2105 long prev_dirpos = 0;
2108 struct smb_filename *smb_fname = NULL;
2109 struct smbd_dirptr_lanman2_state state;
2111 uint64_t last_entry_off = 0;
2115 state.info_level = info_level;
2116 state.check_mangled_names = lp_manglednames(conn->params);
2117 state.has_wild = dptr_has_wild(dirptr);
2118 state.got_exact_match = false;
2120 *out_of_space = false;
2121 *got_exact_match = false;
2123 p = strrchr_m(path_mask,'/');
2134 ok = smbd_dirptr_get_entry(ctx,
2140 smbd_dirptr_lanman2_match_fn,
2141 smbd_dirptr_lanman2_mode_fn,
2151 *got_exact_match = state.got_exact_match;
2153 ok = smbd_marshall_dir_entry(ctx,
2158 state.check_mangled_names,
2159 requires_resume_key,
2172 TALLOC_FREE(smb_fname);
2173 if (*out_of_space) {
2174 dptr_SeekDir(dirptr, prev_dirpos);
2181 *_last_entry_off = last_entry_off;
2185 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2186 connection_struct *conn,
2187 struct dptr_struct *dirptr,
2189 const char *path_mask,
2192 bool requires_resume_key,
2198 int space_remaining,
2200 bool *got_exact_match,
2201 int *last_entry_off,
2202 struct ea_list *name_list)
2205 const bool do_pad = true;
2207 if (info_level >= 1 && info_level <= 3) {
2208 /* No alignment on earlier info levels. */
2212 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2213 path_mask, dirtype, info_level,
2214 requires_resume_key, dont_descend, ask_sharemode,
2216 ppdata, base_data, end_data,
2218 out_of_space, got_exact_match,
2219 last_entry_off, name_list);
2222 /****************************************************************************
2223 Reply to a TRANS2_FINDFIRST.
2224 ****************************************************************************/
2226 static void call_trans2findfirst(connection_struct *conn,
2227 struct smb_request *req,
2228 char **pparams, int total_params,
2229 char **ppdata, int total_data,
2230 unsigned int max_data_bytes)
2232 /* We must be careful here that we don't return more than the
2233 allowed number of data bytes. If this means returning fewer than
2234 maxentries then so be it. We assume that the redirector has
2235 enough room for the fixed number of parameter bytes it has
2237 struct smb_filename *smb_dname = NULL;
2238 char *params = *pparams;
2239 char *pdata = *ppdata;
2243 uint16 findfirst_flags;
2244 bool close_after_first;
2246 bool requires_resume_key;
2248 char *directory = NULL;
2251 int last_entry_off=0;
2255 bool finished = False;
2256 bool dont_descend = False;
2257 bool out_of_space = False;
2258 int space_remaining;
2259 bool mask_contains_wcard = False;
2260 struct ea_list *ea_list = NULL;
2261 NTSTATUS ntstatus = NT_STATUS_OK;
2262 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2263 TALLOC_CTX *ctx = talloc_tos();
2264 struct dptr_struct *dirptr = NULL;
2265 struct smbd_server_connection *sconn = req->sconn;
2267 if (total_params < 13) {
2268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2272 dirtype = SVAL(params,0);
2273 maxentries = SVAL(params,2);
2274 findfirst_flags = SVAL(params,4);
2275 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2276 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2277 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2278 info_level = SVAL(params,6);
2280 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2281 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2282 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2283 info_level, max_data_bytes));
2286 /* W2K3 seems to treat zero as 1. */
2290 switch (info_level) {
2291 case SMB_FIND_INFO_STANDARD:
2292 case SMB_FIND_EA_SIZE:
2293 case SMB_FIND_EA_LIST:
2294 case SMB_FIND_FILE_DIRECTORY_INFO:
2295 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2296 case SMB_FIND_FILE_NAMES_INFO:
2297 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2298 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2299 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2301 case SMB_FIND_FILE_UNIX:
2302 case SMB_FIND_FILE_UNIX_INFO2:
2303 /* Always use filesystem for UNIX mtime query. */
2304 ask_sharemode = false;
2305 if (!lp_unix_extensions()) {
2306 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2311 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2315 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2316 params+12, total_params - 12,
2317 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2318 if (!NT_STATUS_IS_OK(ntstatus)) {
2319 reply_nterror(req, ntstatus);
2323 ntstatus = filename_convert(ctx, conn,
2324 req->flags2 & FLAGS2_DFS_PATHNAMES,
2327 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2328 &mask_contains_wcard,
2330 if (!NT_STATUS_IS_OK(ntstatus)) {
2331 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2332 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2333 ERRSRV, ERRbadpath);
2336 reply_nterror(req, ntstatus);
2340 mask = smb_dname->original_lcomp;
2342 directory = smb_dname->base_name;
2344 p = strrchr_m(directory,'/');
2346 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2347 if((directory[0] == '.') && (directory[1] == '\0')) {
2348 mask = talloc_strdup(ctx,"*");
2350 reply_nterror(req, NT_STATUS_NO_MEMORY);
2353 mask_contains_wcard = True;
2359 if (p == NULL || p == directory) {
2360 /* Ensure we don't have a directory name of "". */
2361 directory = talloc_strdup(talloc_tos(), ".");
2363 reply_nterror(req, NT_STATUS_NO_MEMORY);
2368 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2370 if (info_level == SMB_FIND_EA_LIST) {
2373 if (total_data < 4) {
2374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2378 ea_size = IVAL(pdata,0);
2379 if (ea_size != total_data) {
2380 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2381 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2382 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2386 if (!lp_ea_support(SNUM(conn))) {
2387 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2391 /* Pull out the list of names. */
2392 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2394 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2399 *ppdata = (char *)SMB_REALLOC(
2400 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2401 if(*ppdata == NULL ) {
2402 reply_nterror(req, NT_STATUS_NO_MEMORY);
2406 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2408 /* Realloc the params space */
2409 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2410 if (*pparams == NULL) {
2411 reply_nterror(req, NT_STATUS_NO_MEMORY);
2416 /* Save the wildcard match and attribs we are using on this directory -
2417 needed as lanman2 assumes these are being saved between calls */
2419 ntstatus = dptr_create(conn,
2426 mask_contains_wcard,
2430 if (!NT_STATUS_IS_OK(ntstatus)) {
2431 reply_nterror(req, ntstatus);
2435 dptr_num = dptr_dnum(dirptr);
2436 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2438 /* Initialize per TRANS2_FIND_FIRST operation data */
2439 dptr_init_search_op(dirptr);
2441 /* We don't need to check for VOL here as this is returned by
2442 a different TRANS2 call. */
2444 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2445 directory,lp_dontdescend(SNUM(conn))));
2446 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2447 dont_descend = True;
2450 space_remaining = max_data_bytes;
2451 out_of_space = False;
2453 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2454 bool got_exact_match = False;
2456 /* this is a heuristic to avoid seeking the dirptr except when
2457 absolutely necessary. It allows for a filename of about 40 chars */
2458 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2459 out_of_space = True;
2462 finished = !get_lanman2_dir_entry(ctx,
2466 mask,dirtype,info_level,
2467 requires_resume_key,dont_descend,
2470 space_remaining, &out_of_space,
2472 &last_entry_off, ea_list);
2475 if (finished && out_of_space)
2478 if (!finished && !out_of_space)
2482 * As an optimisation if we know we aren't looking
2483 * for a wildcard name (ie. the name matches the wildcard exactly)
2484 * then we can finish on any (first) match.
2485 * This speeds up large directory searches. JRA.
2491 /* Ensure space_remaining never goes -ve. */
2492 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2493 space_remaining = 0;
2494 out_of_space = true;
2496 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2500 /* Check if we can close the dirptr */
2501 if(close_after_first || (finished && close_if_end)) {
2502 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2503 dptr_close(sconn, &dptr_num);
2507 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2508 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2509 * the protocol level is less than NT1. Tested with smbclient. JRA.
2510 * This should fix the OS/2 client bug #2335.
2513 if(numentries == 0) {
2514 dptr_close(sconn, &dptr_num);
2515 if (get_Protocol() < PROTOCOL_NT1) {
2516 reply_force_doserror(req, ERRDOS, ERRnofiles);
2519 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2520 ERRDOS, ERRbadfile);
2525 /* At this point pdata points to numentries directory entries. */
2527 /* Set up the return parameter block */
2528 SSVAL(params,0,dptr_num);
2529 SSVAL(params,2,numentries);
2530 SSVAL(params,4,finished);
2531 SSVAL(params,6,0); /* Never an EA error */
2532 SSVAL(params,8,last_entry_off);
2534 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2537 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2538 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2540 reply_nterror(req, NT_STATUS_NO_MEMORY);
2544 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2545 smb_fn_name(req->cmd),
2546 mask, directory, dirtype, numentries ) );
2549 * Force a name mangle here to ensure that the
2550 * mask as an 8.3 name is top of the mangled cache.
2551 * The reasons for this are subtle. Don't remove
2552 * this code unless you know what you are doing
2553 * (see PR#13758). JRA.
2556 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2557 char mangled_name[13];
2558 name_to_8_3(mask, mangled_name, True, conn->params);
2561 TALLOC_FREE(smb_dname);
2565 /****************************************************************************
2566 Reply to a TRANS2_FINDNEXT.
2567 ****************************************************************************/
2569 static void call_trans2findnext(connection_struct *conn,
2570 struct smb_request *req,
2571 char **pparams, int total_params,
2572 char **ppdata, int total_data,
2573 unsigned int max_data_bytes)
2575 /* We must be careful here that we don't return more than the
2576 allowed number of data bytes. If this means returning fewer than
2577 maxentries then so be it. We assume that the redirector has
2578 enough room for the fixed number of parameter bytes it has
2580 char *params = *pparams;
2581 char *pdata = *ppdata;
2587 uint16 findnext_flags;
2588 bool close_after_request;
2590 bool requires_resume_key;
2592 bool mask_contains_wcard = False;
2593 char *resume_name = NULL;
2594 const char *mask = NULL;
2595 const char *directory = NULL;
2599 int i, last_entry_off=0;
2600 bool finished = False;
2601 bool dont_descend = False;
2602 bool out_of_space = False;
2603 int space_remaining;
2604 struct ea_list *ea_list = NULL;
2605 NTSTATUS ntstatus = NT_STATUS_OK;
2606 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2607 TALLOC_CTX *ctx = talloc_tos();
2608 struct dptr_struct *dirptr;
2609 struct smbd_server_connection *sconn = req->sconn;
2611 if (total_params < 13) {
2612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2616 dptr_num = SVAL(params,0);
2617 maxentries = SVAL(params,2);
2618 info_level = SVAL(params,4);
2619 resume_key = IVAL(params,6);
2620 findnext_flags = SVAL(params,10);
2621 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2622 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2623 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2624 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2626 if (!continue_bit) {
2627 /* We only need resume_name if continue_bit is zero. */
2628 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2630 total_params - 12, STR_TERMINATE, &ntstatus,
2631 &mask_contains_wcard);
2632 if (!NT_STATUS_IS_OK(ntstatus)) {
2633 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2634 complain (it thinks we're asking for the directory above the shared
2635 path or an invalid name). Catch this as the resume name is only compared, never used in
2636 a file access. JRA. */
2637 srvstr_pull_talloc(ctx, params, req->flags2,
2638 &resume_name, params+12,
2642 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2643 reply_nterror(req, ntstatus);
2649 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2650 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2651 resume_key = %d resume name = %s continue=%d level = %d\n",
2652 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2653 requires_resume_key, resume_key,
2654 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2657 /* W2K3 seems to treat zero as 1. */
2661 switch (info_level) {
2662 case SMB_FIND_INFO_STANDARD:
2663 case SMB_FIND_EA_SIZE:
2664 case SMB_FIND_EA_LIST:
2665 case SMB_FIND_FILE_DIRECTORY_INFO:
2666 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2667 case SMB_FIND_FILE_NAMES_INFO:
2668 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2669 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2670 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2672 case SMB_FIND_FILE_UNIX:
2673 case SMB_FIND_FILE_UNIX_INFO2:
2674 /* Always use filesystem for UNIX mtime query. */
2675 ask_sharemode = false;
2676 if (!lp_unix_extensions()) {
2677 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2682 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2686 if (info_level == SMB_FIND_EA_LIST) {
2689 if (total_data < 4) {
2690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2694 ea_size = IVAL(pdata,0);
2695 if (ea_size != total_data) {
2696 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2697 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2702 if (!lp_ea_support(SNUM(conn))) {
2703 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2707 /* Pull out the list of names. */
2708 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2710 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2715 *ppdata = (char *)SMB_REALLOC(
2716 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2717 if(*ppdata == NULL) {
2718 reply_nterror(req, NT_STATUS_NO_MEMORY);
2723 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2725 /* Realloc the params space */
2726 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2727 if(*pparams == NULL ) {
2728 reply_nterror(req, NT_STATUS_NO_MEMORY);
2734 /* Check that the dptr is valid */
2735 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2736 reply_nterror(req, STATUS_NO_MORE_FILES);
2740 directory = dptr_path(sconn, dptr_num);
2742 /* Get the wildcard mask from the dptr */
2743 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2744 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2745 reply_nterror(req, STATUS_NO_MORE_FILES);
2751 /* Get the attr mask from the dptr */
2752 dirtype = dptr_attr(sconn, dptr_num);
2754 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2755 dptr_num, mask, dirtype,
2757 dptr_TellDir(dirptr)));
2759 /* Initialize per TRANS2_FIND_NEXT operation data */
2760 dptr_init_search_op(dirptr);
2762 /* We don't need to check for VOL here as this is returned by
2763 a different TRANS2 call. */
2765 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2766 directory,lp_dontdescend(SNUM(conn))));
2767 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2768 dont_descend = True;
2771 space_remaining = max_data_bytes;
2772 out_of_space = False;
2775 * Seek to the correct position. We no longer use the resume key but
2776 * depend on the last file name instead.
2779 if(!continue_bit && resume_name && *resume_name) {
2782 long current_pos = 0;
2784 * Remember, name_to_8_3 is called by
2785 * get_lanman2_dir_entry(), so the resume name
2786 * could be mangled. Ensure we check the unmangled name.
2789 if (mangle_is_mangled(resume_name, conn->params)) {
2790 char *new_resume_name = NULL;
2791 mangle_lookup_name_from_8_3(ctx,
2795 if (new_resume_name) {
2796 resume_name = new_resume_name;
2801 * Fix for NT redirector problem triggered by resume key indexes
2802 * changing between directory scans. We now return a resume key of 0
2803 * and instead look for the filename to continue from (also given
2804 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2805 * findfirst/findnext (as is usual) then the directory pointer
2806 * should already be at the correct place.
2809 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2810 } /* end if resume_name && !continue_bit */
2812 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2813 bool got_exact_match = False;
2815 /* this is a heuristic to avoid seeking the dirptr except when
2816 absolutely necessary. It allows for a filename of about 40 chars */
2817 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2818 out_of_space = True;
2821 finished = !get_lanman2_dir_entry(ctx,
2825 mask,dirtype,info_level,
2826 requires_resume_key,dont_descend,
2829 space_remaining, &out_of_space,
2831 &last_entry_off, ea_list);
2834 if (finished && out_of_space)
2837 if (!finished && !out_of_space)
2841 * As an optimisation if we know we aren't looking
2842 * for a wildcard name (ie. the name matches the wildcard exactly)
2843 * then we can finish on any (first) match.
2844 * This speeds up large directory searches. JRA.
2850 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2853 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2854 smb_fn_name(req->cmd),
2855 mask, directory, dirtype, numentries ) );
2857 /* Check if we can close the dirptr */
2858 if(close_after_request || (finished && close_if_end)) {
2859 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2860 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2863 /* Set up the return parameter block */
2864 SSVAL(params,0,numentries);
2865 SSVAL(params,2,finished);
2866 SSVAL(params,4,0); /* Never an EA error */
2867 SSVAL(params,6,last_entry_off);
2869 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2875 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2877 E_md4hash(lp_servicename(SNUM(conn)),objid);
2881 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2883 SMB_ASSERT(extended_info != NULL);
2885 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2886 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2887 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2888 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2889 #ifdef SAMBA_VERSION_REVISION
2890 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2892 extended_info->samba_subversion = 0;
2893 #ifdef SAMBA_VERSION_RC_RELEASE
2894 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2896 #ifdef SAMBA_VERSION_PRE_RELEASE
2897 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2900 #ifdef SAMBA_VERSION_VENDOR_PATCH
2901 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2903 extended_info->samba_gitcommitdate = 0;
2904 #ifdef SAMBA_VERSION_COMMIT_TIME
2905 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2908 memset(extended_info->samba_version_string, 0,
2909 sizeof(extended_info->samba_version_string));
2911 snprintf (extended_info->samba_version_string,
2912 sizeof(extended_info->samba_version_string),
2913 "%s", samba_version_string());
2916 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2917 TALLOC_CTX *mem_ctx,
2918 uint16_t info_level,
2920 unsigned int max_data_bytes,
2924 char *pdata, *end_data;
2925 int data_len = 0, len;
2926 const char *vname = volume_label(SNUM(conn));
2927 int snum = SNUM(conn);
2928 char *fstype = lp_fstype(SNUM(conn));
2929 uint32 additional_flags = 0;
2930 struct smb_filename smb_fname_dot;
2934 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2935 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2936 "info level (0x%x) on IPC$.\n",
2937 (unsigned int)info_level));
2938 return NT_STATUS_ACCESS_DENIED;
2942 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2944 ZERO_STRUCT(smb_fname_dot);
2945 smb_fname_dot.base_name = discard_const_p(char, ".");
2947 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2948 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2949 return map_nt_error_from_unix(errno);
2952 st = smb_fname_dot.st;
2954 *ppdata = (char *)SMB_REALLOC(
2955 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2956 if (*ppdata == NULL) {
2957 return NT_STATUS_NO_MEMORY;
2961 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2962 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2964 switch (info_level) {
2965 case SMB_INFO_ALLOCATION:
2967 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2969 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2970 return map_nt_error_from_unix(errno);
2973 block_size = lp_block_size(snum);
2974 if (bsize < block_size) {
2975 uint64_t factor = block_size/bsize;
2980 if (bsize > block_size) {
2981 uint64_t factor = bsize/block_size;
2986 bytes_per_sector = 512;
2987 sectors_per_unit = bsize/bytes_per_sector;
2989 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2990 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2991 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2993 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2994 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2995 SIVAL(pdata,l1_cUnit,dsize);
2996 SIVAL(pdata,l1_cUnitAvail,dfree);
2997 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3001 case SMB_INFO_VOLUME:
3002 /* Return volume name */
3004 * Add volume serial number - hash of a combination of
3005 * the called hostname and the service name.
3007 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3009 * Win2k3 and previous mess this up by sending a name length
3010 * one byte short. I believe only older clients (OS/2 Win9x) use
3011 * this call so try fixing this by adding a terminating null to
3012 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3016 pdata+l2_vol_szVolLabel, vname,
3017 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3018 STR_NOALIGN|STR_TERMINATE);
3019 SCVAL(pdata,l2_vol_cch,len);
3020 data_len = l2_vol_szVolLabel + len;
3021 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3022 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3026 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3027 case SMB_FS_ATTRIBUTE_INFORMATION:
3029 additional_flags = 0;
3030 #if defined(HAVE_SYS_QUOTAS)
3031 additional_flags |= FILE_VOLUME_QUOTAS;
3034 if(lp_nt_acl_support(SNUM(conn))) {
3035 additional_flags |= FILE_PERSISTENT_ACLS;
3038 /* Capabilities are filled in at connection time through STATVFS call */
3039 additional_flags |= conn->fs_capabilities;
3040 additional_flags |= lp_parm_int(conn->params->service,
3041 "share", "fake_fscaps",
3044 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3045 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3046 additional_flags); /* FS ATTRIBUTES */
3048 SIVAL(pdata,4,255); /* Max filename component length */
3049 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3050 and will think we can't do long filenames */
3051 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3052 PTR_DIFF(end_data, pdata+12),
3055 data_len = 12 + len;
3058 case SMB_QUERY_FS_LABEL_INFO:
3059 case SMB_FS_LABEL_INFORMATION:
3060 len = srvstr_push(pdata, flags2, pdata+4, vname,
3061 PTR_DIFF(end_data, pdata+4), 0);
3066 case SMB_QUERY_FS_VOLUME_INFO:
3067 case SMB_FS_VOLUME_INFORMATION:
3070 * Add volume serial number - hash of a combination of
3071 * the called hostname and the service name.
3073 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3074 (str_checksum(get_local_machine_name())<<16));
3076 /* Max label len is 32 characters. */
3077 len = srvstr_push(pdata, flags2, pdata+18, vname,
3078 PTR_DIFF(end_data, pdata+18),
3080 SIVAL(pdata,12,len);
3083 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3084 (int)strlen(vname),vname, lp_servicename(snum)));
3087 case SMB_QUERY_FS_SIZE_INFO:
3088 case SMB_FS_SIZE_INFORMATION:
3090 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3092 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3093 return map_nt_error_from_unix(errno);
3095 block_size = lp_block_size(snum);
3096 if (bsize < block_size) {
3097 uint64_t factor = block_size/bsize;
3102 if (bsize > block_size) {
3103 uint64_t factor = bsize/block_size;
3108 bytes_per_sector = 512;
3109 sectors_per_unit = bsize/bytes_per_sector;
3110 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3111 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3112 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3113 SBIG_UINT(pdata,0,dsize);
3114 SBIG_UINT(pdata,8,dfree);
3115 SIVAL(pdata,16,sectors_per_unit);
3116 SIVAL(pdata,20,bytes_per_sector);
3120 case SMB_FS_FULL_SIZE_INFORMATION:
3122 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3124 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3125 return map_nt_error_from_unix(errno);
3127 block_size = lp_block_size(snum);
3128 if (bsize < block_size) {
3129 uint64_t factor = block_size/bsize;
3134 if (bsize > block_size) {
3135 uint64_t factor = bsize/block_size;
3140 bytes_per_sector = 512;
3141 sectors_per_unit = bsize/bytes_per_sector;
3142 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3143 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3144 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3145 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3146 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3147 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3148 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3149 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3153 case SMB_QUERY_FS_DEVICE_INFO:
3154 case SMB_FS_DEVICE_INFORMATION:
3156 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3158 if (!CAN_WRITE(conn)) {
3159 characteristics |= FILE_READ_ONLY_DEVICE;
3162 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3163 SIVAL(pdata,4,characteristics);
3167 #ifdef HAVE_SYS_QUOTAS
3168 case SMB_FS_QUOTA_INFORMATION:
3170 * what we have to send --metze:
3172 * Unknown1: 24 NULL bytes
3173 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3174 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3175 * Quota Flags: 2 byte :
3176 * Unknown3: 6 NULL bytes
3180 * details for Quota Flags:
3182 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3183 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3184 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3185 * 0x0001 Enable Quotas: enable quota for this fs
3189 /* we need to fake up a fsp here,
3190 * because its not send in this call
3193 SMB_NTQUOTA_STRUCT quotas;
3196 ZERO_STRUCT(quotas);
3202 if (conn->server_info->utok.uid != sec_initial_uid()) {
3203 DEBUG(0,("set_user_quota: access_denied "
3204 "service [%s] user [%s]\n",
3205 lp_servicename(SNUM(conn)),
3206 conn->server_info->unix_name));
3207 return NT_STATUS_ACCESS_DENIED;
3210 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3211 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3212 return map_nt_error_from_unix(errno);
3217 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3218 lp_servicename(SNUM(conn))));
3220 /* Unknown1 24 NULL bytes*/
3221 SBIG_UINT(pdata,0,(uint64_t)0);
3222 SBIG_UINT(pdata,8,(uint64_t)0);
3223 SBIG_UINT(pdata,16,(uint64_t)0);
3225 /* Default Soft Quota 8 bytes */
3226 SBIG_UINT(pdata,24,quotas.softlim);
3228 /* Default Hard Quota 8 bytes */
3229 SBIG_UINT(pdata,32,quotas.hardlim);
3231 /* Quota flag 2 bytes */
3232 SSVAL(pdata,40,quotas.qflags);
3234 /* Unknown3 6 NULL bytes */
3240 #endif /* HAVE_SYS_QUOTAS */
3241 case SMB_FS_OBJECTID_INFORMATION:
3243 unsigned char objid[16];
3244 struct smb_extended_info extended_info;
3245 memcpy(pdata,create_volume_objectid(conn, objid),16);
3246 samba_extended_info_version (&extended_info);
3247 SIVAL(pdata,16,extended_info.samba_magic);
3248 SIVAL(pdata,20,extended_info.samba_version);
3249 SIVAL(pdata,24,extended_info.samba_subversion);
3250 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3251 memcpy(pdata+36,extended_info.samba_version_string,28);
3257 * Query the version and capabilities of the CIFS UNIX extensions
3261 case SMB_QUERY_CIFS_UNIX_INFO:
3263 bool large_write = lp_min_receive_file_size() &&
3264 !srv_is_signing_active(conn->sconn);
3265 bool large_read = !srv_is_signing_active(conn->sconn);
3266 int encrypt_caps = 0;
3268 if (!lp_unix_extensions()) {
3269 return NT_STATUS_INVALID_LEVEL;
3272 switch (conn->encrypt_level) {
3278 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3281 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3282 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3283 large_write = false;
3289 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3290 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3292 /* We have POSIX ACLs, pathname, encryption,
3293 * large read/write, and locking capability. */
3295 SBIG_UINT(pdata,4,((uint64_t)(
3296 CIFS_UNIX_POSIX_ACLS_CAP|
3297 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3298 CIFS_UNIX_FCNTL_LOCKS_CAP|
3299 CIFS_UNIX_EXTATTR_CAP|
3300 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3302 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3304 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3308 case SMB_QUERY_POSIX_FS_INFO:
3311 vfs_statvfs_struct svfs;
3313 if (!lp_unix_extensions()) {
3314 return NT_STATUS_INVALID_LEVEL;
3317 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3321 SIVAL(pdata,0,svfs.OptimalTransferSize);
3322 SIVAL(pdata,4,svfs.BlockSize);
3323 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3324 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3325 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3326 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3327 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3328 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3329 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3331 } else if (rc == EOPNOTSUPP) {
3332 return NT_STATUS_INVALID_LEVEL;
3333 #endif /* EOPNOTSUPP */
3335 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3336 return NT_STATUS_DOS(ERRSRV, ERRerror);
3341 case SMB_QUERY_POSIX_WHOAMI:
3347 if (!lp_unix_extensions()) {
3348 return NT_STATUS_INVALID_LEVEL;
3351 if (max_data_bytes < 40) {
3352 return NT_STATUS_BUFFER_TOO_SMALL;
3355 /* We ARE guest if global_sid_Builtin_Guests is
3356 * in our list of SIDs.
3358 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3359 conn->server_info->ptok)) {
3360 flags |= SMB_WHOAMI_GUEST;
3363 /* We are NOT guest if global_sid_Authenticated_Users
3364 * is in our list of SIDs.
3366 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3367 conn->server_info->ptok)) {
3368 flags &= ~SMB_WHOAMI_GUEST;
3371 /* NOTE: 8 bytes for UID/GID, irrespective of native
3372 * platform size. This matches
3373 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3375 data_len = 4 /* flags */
3382 + 4 /* pad/reserved */
3383 + (conn->server_info->utok.ngroups * 8)
3385 + (conn->server_info->ptok->num_sids *
3389 SIVAL(pdata, 0, flags);
3390 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3392 (uint64_t)conn->server_info->utok.uid);
3393 SBIG_UINT(pdata, 16,
3394 (uint64_t)conn->server_info->utok.gid);
3397 if (data_len >= max_data_bytes) {
3398 /* Potential overflow, skip the GIDs and SIDs. */
3400 SIVAL(pdata, 24, 0); /* num_groups */
3401 SIVAL(pdata, 28, 0); /* num_sids */
3402 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3403 SIVAL(pdata, 36, 0); /* reserved */
3409 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3410 SIVAL(pdata, 28, conn->server_info->ptok->num_sids);
3412 /* We walk the SID list twice, but this call is fairly
3413 * infrequent, and I don't expect that it's performance
3414 * sensitive -- jpeach
3416 for (i = 0, sid_bytes = 0;
3417 i < conn->server_info->ptok->num_sids; ++i) {
3418 sid_bytes += ndr_size_dom_sid(
3419 &conn->server_info->ptok->sids[i],
3423 /* SID list byte count */
3424 SIVAL(pdata, 32, sid_bytes);
3426 /* 4 bytes pad/reserved - must be zero */
3427 SIVAL(pdata, 36, 0);
3431 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3432 SBIG_UINT(pdata, data_len,
3433 (uint64_t)conn->server_info->utok.groups[i]);
3439 i < conn->server_info->ptok->num_sids; ++i) {
3440 int sid_len = ndr_size_dom_sid(
3441 &conn->server_info->ptok->sids[i],
3444 sid_linearize(pdata + data_len, sid_len,
3445 &conn->server_info->ptok->sids[i]);
3446 data_len += sid_len;
3452 case SMB_MAC_QUERY_FS_INFO:
3454 * Thursby MAC extension... ONLY on NTFS filesystems
3455 * once we do streams then we don't need this
3457 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3459 SIVAL(pdata,84,0x100); /* Don't support mac... */
3464 return NT_STATUS_INVALID_LEVEL;
3467 *ret_data_len = data_len;
3468 return NT_STATUS_OK;
3471 /****************************************************************************
3472 Reply to a TRANS2_QFSINFO (query filesystem info).
3473 ****************************************************************************/
3475 static void call_trans2qfsinfo(connection_struct *conn,
3476 struct smb_request *req,
3477 char **pparams, int total_params,
3478 char **ppdata, int total_data,
3479 unsigned int max_data_bytes)
3481 char *params = *pparams;
3482 uint16_t info_level;
3486 if (total_params < 2) {
3487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3491 info_level = SVAL(params,0);
3493 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3494 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3495 DEBUG(0,("call_trans2qfsinfo: encryption required "
3496 "and info level 0x%x sent.\n",
3497 (unsigned int)info_level));
3498 exit_server_cleanly("encryption required "
3504 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3506 status = smbd_do_qfsinfo(conn, req,
3511 if (!NT_STATUS_IS_OK(status)) {
3512 reply_nterror(req, status);
3516 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3519 DEBUG( 4, ( "%s info_level = %d\n",
3520 smb_fn_name(req->cmd), info_level) );
3525 /****************************************************************************
3526 Reply to a TRANS2_SETFSINFO (set filesystem info).
3527 ****************************************************************************/
3529 static void call_trans2setfsinfo(connection_struct *conn,
3530 struct smb_request *req,
3531 char **pparams, int total_params,
3532 char **ppdata, int total_data,
3533 unsigned int max_data_bytes)
3535 char *pdata = *ppdata;
3536 char *params = *pparams;
3539 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3542 if (total_params < 4) {
3543 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3549 info_level = SVAL(params,2);
3552 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3553 info_level != SMB_SET_CIFS_UNIX_INFO) {
3554 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3555 "info level (0x%x) on IPC$.\n",
3556 (unsigned int)info_level));
3557 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3562 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3563 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3564 DEBUG(0,("call_trans2setfsinfo: encryption required "
3565 "and info level 0x%x sent.\n",
3566 (unsigned int)info_level));
3567 exit_server_cleanly("encryption required "
3573 switch(info_level) {
3574 case SMB_SET_CIFS_UNIX_INFO:
3576 uint16 client_unix_major;
3577 uint16 client_unix_minor;
3578 uint32 client_unix_cap_low;
3579 uint32 client_unix_cap_high;
3581 if (!lp_unix_extensions()) {
3583 NT_STATUS_INVALID_LEVEL);
3587 /* There should be 12 bytes of capabilities set. */
3588 if (total_data < 8) {
3591 NT_STATUS_INVALID_PARAMETER);
3594 client_unix_major = SVAL(pdata,0);
3595 client_unix_minor = SVAL(pdata,2);
3596 client_unix_cap_low = IVAL(pdata,4);
3597 client_unix_cap_high = IVAL(pdata,8);
3598 /* Just print these values for now. */
3599 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3600 cap_low = 0x%x, cap_high = 0x%x\n",
3601 (unsigned int)client_unix_major,
3602 (unsigned int)client_unix_minor,
3603 (unsigned int)client_unix_cap_low,
3604 (unsigned int)client_unix_cap_high ));
3606 /* Here is where we must switch to posix pathname processing... */
3607 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3608 lp_set_posix_pathnames();
3609 mangle_change_to_posix();
3612 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3613 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3614 /* Client that knows how to do posix locks,
3615 * but not posix open/mkdir operations. Set a
3616 * default type for read/write checks. */
3618 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3624 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3627 size_t param_len = 0;
3628 size_t data_len = total_data;
3630 if (!lp_unix_extensions()) {
3633 NT_STATUS_INVALID_LEVEL);
3637 if (lp_smb_encrypt(SNUM(conn)) == false) {
3640 NT_STATUS_NOT_SUPPORTED);
3644 if (req->sconn->smb1.echo_handler.trusted_fde) {
3645 DEBUG( 2,("call_trans2setfsinfo: "
3646 "request transport encryption disabled"
3647 "with 'fork echo handler = yes'\n"));
3650 NT_STATUS_NOT_SUPPORTED);
3654 DEBUG( 4,("call_trans2setfsinfo: "
3655 "request transport encryption.\n"));
3657 status = srv_request_encryption_setup(conn,
3658 (unsigned char **)ppdata,
3660 (unsigned char **)pparams,
3663 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3664 !NT_STATUS_IS_OK(status)) {
3665 reply_nterror(req, status);
3669 send_trans2_replies(conn, req,
3676 if (NT_STATUS_IS_OK(status)) {
3677 /* Server-side transport
3678 * encryption is now *on*. */
3679 status = srv_encryption_start(conn);
3680 if (!NT_STATUS_IS_OK(status)) {
3681 exit_server_cleanly(
3682 "Failure in setting "
3683 "up encrypted transport");
3689 case SMB_FS_QUOTA_INFORMATION:
3691 files_struct *fsp = NULL;
3692 SMB_NTQUOTA_STRUCT quotas;
3694 ZERO_STRUCT(quotas);
3697 if ((conn->server_info->utok.uid != sec_initial_uid())
3698 ||!CAN_WRITE(conn)) {
3699 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3700 lp_servicename(SNUM(conn)),
3701 conn->server_info->unix_name));
3702 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3706 /* note: normaly there're 48 bytes,
3707 * but we didn't use the last 6 bytes for now
3710 fsp = file_fsp(req, SVAL(params,0));
3712 if (!check_fsp_ntquota_handle(conn, req,
3714 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3716 req, NT_STATUS_INVALID_HANDLE);
3720 if (total_data < 42) {
3721 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3725 NT_STATUS_INVALID_PARAMETER);
3729 /* unknown_1 24 NULL bytes in pdata*/
3731 /* the soft quotas 8 bytes (uint64_t)*/
3732 quotas.softlim = (uint64_t)IVAL(pdata,24);
3733 #ifdef LARGE_SMB_OFF_T
3734 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3735 #else /* LARGE_SMB_OFF_T */
3736 if ((IVAL(pdata,28) != 0)&&
3737 ((quotas.softlim != 0xFFFFFFFF)||
3738 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3739 /* more than 32 bits? */
3742 NT_STATUS_INVALID_PARAMETER);
3745 #endif /* LARGE_SMB_OFF_T */
3747 /* the hard quotas 8 bytes (uint64_t)*/
3748 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3749 #ifdef LARGE_SMB_OFF_T
3750 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3751 #else /* LARGE_SMB_OFF_T */
3752 if ((IVAL(pdata,36) != 0)&&
3753 ((quotas.hardlim != 0xFFFFFFFF)||
3754 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3755 /* more than 32 bits? */
3758 NT_STATUS_INVALID_PARAMETER);
3761 #endif /* LARGE_SMB_OFF_T */
3763 /* quota_flags 2 bytes **/
3764 quotas.qflags = SVAL(pdata,40);
3766 /* unknown_2 6 NULL bytes follow*/
3768 /* now set the quotas */
3769 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3770 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3771 reply_nterror(req, map_nt_error_from_unix(errno));
3778 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3780 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3786 * sending this reply works fine,
3787 * but I'm not sure it's the same
3788 * like windows do...
3791 reply_outbuf(req, 10, 0);
3794 #if defined(HAVE_POSIX_ACLS)
3795 /****************************************************************************
3796 Utility function to count the number of entries in a POSIX acl.
3797 ****************************************************************************/
3799 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3801 unsigned int ace_count = 0;
3802 int entry_id = SMB_ACL_FIRST_ENTRY;
3803 SMB_ACL_ENTRY_T entry;
3805 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3807 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3808 entry_id = SMB_ACL_NEXT_ENTRY;
3815 /****************************************************************************
3816 Utility function to marshall a POSIX acl into wire format.
3817 ****************************************************************************/
3819 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3821 int entry_id = SMB_ACL_FIRST_ENTRY;
3822 SMB_ACL_ENTRY_T entry;
3824 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3825 SMB_ACL_TAG_T tagtype;
3826 SMB_ACL_PERMSET_T permset;
3827 unsigned char perms = 0;
3828 unsigned int own_grp;
3831 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3832 entry_id = SMB_ACL_NEXT_ENTRY;
3835 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3836 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3840 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3841 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3845 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3846 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3847 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3849 SCVAL(pdata,1,perms);
3852 case SMB_ACL_USER_OBJ:
3853 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3854 own_grp = (unsigned int)pst->st_ex_uid;
3855 SIVAL(pdata,2,own_grp);
3860 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3862 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3865 own_grp = (unsigned int)*puid;
3866 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3867 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3868 SIVAL(pdata,2,own_grp);
3872 case SMB_ACL_GROUP_OBJ:
3873 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3874 own_grp = (unsigned int)pst->st_ex_gid;
3875 SIVAL(pdata,2,own_grp);
3880 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3882 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3885 own_grp = (unsigned int)*pgid;
3886 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3887 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3888 SIVAL(pdata,2,own_grp);
3893 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3894 SIVAL(pdata,2,0xFFFFFFFF);
3895 SIVAL(pdata,6,0xFFFFFFFF);
3898 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3899 SIVAL(pdata,2,0xFFFFFFFF);
3900 SIVAL(pdata,6,0xFFFFFFFF);
3903 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3906 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3913 /****************************************************************************
3914 Store the FILE_UNIX_BASIC info.
3915 ****************************************************************************/
3917 static char *store_file_unix_basic(connection_struct *conn,
3920 const SMB_STRUCT_STAT *psbuf)
3922 uint64_t file_index = get_FileIndex(conn, psbuf);
3924 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3925 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3927 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3930 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3933 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3934 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3935 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3938 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3942 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3946 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3949 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3953 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3957 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3960 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3964 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3971 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3972 * the chflags(2) (or equivalent) flags.
3974 * XXX: this really should be behind the VFS interface. To do this, we would
3975 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3976 * Each VFS module could then implement its own mapping as appropriate for the
3977 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3979 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3983 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3987 { UF_IMMUTABLE, EXT_IMMUTABLE },
3991 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3995 { UF_HIDDEN, EXT_HIDDEN },
3998 /* Do not remove. We need to guarantee that this array has at least one
3999 * entry to build on HP-UX.
4005 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4006 uint32 *smb_fflags, uint32 *smb_fmask)
4010 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4011 *smb_fmask |= info2_flags_map[i].smb_fflag;
4012 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4013 *smb_fflags |= info2_flags_map[i].smb_fflag;
4018 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4019 const uint32 smb_fflags,
4020 const uint32 smb_fmask,
4023 uint32 max_fmask = 0;
4026 *stat_fflags = psbuf->st_ex_flags;
4028 /* For each flags requested in smb_fmask, check the state of the
4029 * corresponding flag in smb_fflags and set or clear the matching
4033 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4034 max_fmask |= info2_flags_map[i].smb_fflag;
4035 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4036 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4037 *stat_fflags |= info2_flags_map[i].stat_fflag;
4039 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4044 /* If smb_fmask is asking to set any bits that are not supported by
4045 * our flag mappings, we should fail.
4047 if ((smb_fmask & max_fmask) != smb_fmask) {
4055 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4056 * of file flags and birth (create) time.
4058 static char *store_file_unix_basic_info2(connection_struct *conn,
4061 const SMB_STRUCT_STAT *psbuf)
4063 uint32 file_flags = 0;
4064 uint32 flags_mask = 0;
4066 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4068 /* Create (birth) time 64 bit */
4069 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4072 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4073 SIVAL(pdata, 0, file_flags); /* flags */
4074 SIVAL(pdata, 4, flags_mask); /* mask */
4080 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4081 const struct stream_struct *streams,
4083 unsigned int max_data_bytes,
4084 unsigned int *data_size)
4087 unsigned int ofs = 0;
4089 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4090 unsigned int next_offset;
4092 smb_ucs2_t *namebuf;
4094 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4095 streams[i].name, &namelen) ||
4098 return NT_STATUS_INVALID_PARAMETER;
4102 * name_buf is now null-terminated, we need to marshall as not
4108 SIVAL(data, ofs+4, namelen);
4109 SOFF_T(data, ofs+8, streams[i].size);
4110 SOFF_T(data, ofs+16, streams[i].alloc_size);
4111 memcpy(data+ofs+24, namebuf, namelen);
4112 TALLOC_FREE(namebuf);
4114 next_offset = ofs + 24 + namelen;
4116 if (i == num_streams-1) {
4117 SIVAL(data, ofs, 0);
4120 unsigned int align = ndr_align_size(next_offset, 8);
4122 memset(data+next_offset, 0, align);
4123 next_offset += align;
4125 SIVAL(data, ofs, next_offset - ofs);
4134 return NT_STATUS_OK;
4137 /****************************************************************************
4138 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4139 ****************************************************************************/
4141 static void call_trans2qpipeinfo(connection_struct *conn,
4142 struct smb_request *req,
4143 unsigned int tran_call,
4144 char **pparams, int total_params,
4145 char **ppdata, int total_data,
4146 unsigned int max_data_bytes)
4148 char *params = *pparams;
4149 char *pdata = *ppdata;
4150 unsigned int data_size = 0;
4151 unsigned int param_size = 2;
4156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4160 if (total_params < 4) {
4161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4165 fsp = file_fsp(req, SVAL(params,0));
4166 if (!fsp_is_np(fsp)) {
4167 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4171 info_level = SVAL(params,2);
4173 *pparams = (char *)SMB_REALLOC(*pparams,2);
4174 if (*pparams == NULL) {
4175 reply_nterror(req, NT_STATUS_NO_MEMORY);
4180 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4181 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4182 if (*ppdata == NULL ) {
4183 reply_nterror(req, NT_STATUS_NO_MEMORY);
4188 switch (info_level) {
4189 case SMB_FILE_STANDARD_INFORMATION:
4191 SOFF_T(pdata,0,4096LL);
4198 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4202 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4208 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4209 TALLOC_CTX *mem_ctx,
4210 uint16_t info_level,
4212 struct smb_filename *smb_fname,
4213 bool delete_pending,
4214 struct timespec write_time_ts,
4215 struct ea_list *ea_list,
4216 int lock_data_count,
4219 unsigned int max_data_bytes,
4221 unsigned int *pdata_size)
4223 char *pdata = *ppdata;
4224 char *dstart, *dend;
4225 unsigned int data_size;
4226 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4227 time_t create_time, mtime, atime, c_time;
4228 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4235 uint64_t file_size = 0;
4237 uint64_t allocation_size = 0;
4238 uint64_t file_index = 0;
4239 uint32_t access_mask = 0;
4241 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4242 return NT_STATUS_INVALID_LEVEL;
4245 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4246 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4247 info_level, max_data_bytes));
4249 mode = dos_mode(conn, smb_fname);
4250 nlink = psbuf->st_ex_nlink;
4252 if (nlink && (mode&aDIR)) {
4256 if ((nlink > 0) && delete_pending) {
4260 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4261 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4262 if (*ppdata == NULL) {
4263 return NT_STATUS_NO_MEMORY;
4267 dend = dstart + data_size - 1;
4269 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4270 update_stat_ex_mtime(psbuf, write_time_ts);
4273 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4274 mtime_ts = psbuf->st_ex_mtime;
4275 atime_ts = psbuf->st_ex_atime;
4276 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4278 if (lp_dos_filetime_resolution(SNUM(conn))) {
4279 dos_filetime_timespec(&create_time_ts);
4280 dos_filetime_timespec(&mtime_ts);
4281 dos_filetime_timespec(&atime_ts);
4282 dos_filetime_timespec(&ctime_ts);
4285 create_time = convert_timespec_to_time_t(create_time_ts);
4286 mtime = convert_timespec_to_time_t(mtime_ts);
4287 atime = convert_timespec_to_time_t(atime_ts);
4288 c_time = convert_timespec_to_time_t(ctime_ts);
4290 p = strrchr_m(smb_fname->base_name,'/');
4292 base_name = smb_fname->base_name;
4296 /* NT expects the name to be in an exact form of the *full*
4297 filename. See the trans2 torture test */
4298 if (ISDOT(base_name)) {
4299 dos_fname = talloc_strdup(mem_ctx, "\\");
4301 return NT_STATUS_NO_MEMORY;
4304 dos_fname = talloc_asprintf(mem_ctx,
4306 smb_fname->base_name);
4308 return NT_STATUS_NO_MEMORY;
4310 if (is_ntfs_stream_smb_fname(smb_fname)) {
4311 dos_fname = talloc_asprintf(dos_fname, "%s",
4312 smb_fname->stream_name);
4314 return NT_STATUS_NO_MEMORY;
4318 string_replace(dos_fname, '/', '\\');
4321 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4324 /* Do we have this path open ? */
4326 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4327 fsp1 = file_find_di_first(conn->sconn, fileid);
4328 if (fsp1 && fsp1->initial_allocation_size) {
4329 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4333 if (!(mode & aDIR)) {
4334 file_size = get_file_size_stat(psbuf);
4338 pos = fsp->fh->position_information;
4342 access_mask = fsp->access_mask;
4344 /* GENERIC_EXECUTE mapping from Windows */
4345 access_mask = 0x12019F;
4348 /* This should be an index number - looks like
4351 I think this causes us to fail the IFSKIT
4352 BasicFileInformationTest. -tpot */
4353 file_index = get_FileIndex(conn, psbuf);
4355 switch (info_level) {
4356 case SMB_INFO_STANDARD:
4357 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4359 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4360 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4361 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4362 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4363 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4364 SSVAL(pdata,l1_attrFile,mode);
4367 case SMB_INFO_QUERY_EA_SIZE:
4369 unsigned int ea_size =
4370 estimate_ea_size(conn, fsp,
4371 smb_fname->base_name);
4372 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4374 srv_put_dos_date2(pdata,0,create_time);
4375 srv_put_dos_date2(pdata,4,atime);
4376 srv_put_dos_date2(pdata,8,mtime); /* write time */
4377 SIVAL(pdata,12,(uint32)file_size);
4378 SIVAL(pdata,16,(uint32)allocation_size);
4379 SSVAL(pdata,20,mode);
4380 SIVAL(pdata,22,ea_size);
4384 case SMB_INFO_IS_NAME_VALID:
4385 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4387 /* os/2 needs this ? really ?*/
4388 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4390 /* This is only reached for qpathinfo */
4394 case SMB_INFO_QUERY_EAS_FROM_LIST:
4396 size_t total_ea_len = 0;
4397 struct ea_list *ea_file_list = NULL;
4399 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4402 get_ea_list_from_file(mem_ctx, conn, fsp,
4403 smb_fname->base_name,
4405 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4407 if (!ea_list || (total_ea_len > data_size)) {
4409 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4413 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4417 case SMB_INFO_QUERY_ALL_EAS:
4419 /* We have data_size bytes to put EA's into. */
4420 size_t total_ea_len = 0;
4422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4424 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4425 smb_fname->base_name,
4427 if (!ea_list || (total_ea_len > data_size)) {
4429 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4433 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4437 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4439 /* This is FileFullEaInformation - 0xF which maps to
4440 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4442 /* We have data_size bytes to put EA's into. */
4443 size_t total_ea_len = 0;
4444 struct ea_list *ea_file_list = NULL;
4446 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4448 /*TODO: add filtering and index handling */
4451 get_ea_list_from_file(mem_ctx, conn, fsp,
4452 smb_fname->base_name,
4454 if (!ea_file_list) {
4455 return NT_STATUS_NO_EAS_ON_FILE;
4458 status = fill_ea_chained_buffer(mem_ctx,
4462 conn, ea_file_list);
4463 if (!NT_STATUS_IS_OK(status)) {
4469 case SMB_FILE_BASIC_INFORMATION:
4470 case SMB_QUERY_FILE_BASIC_INFO:
4472 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4473 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4474 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4480 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4481 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4482 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4483 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4484 SIVAL(pdata,32,mode);
4486 DEBUG(5,("SMB_QFBI - "));
4487 DEBUG(5,("create: %s ", ctime(&create_time)));
4488 DEBUG(5,("access: %s ", ctime(&atime)));
4489 DEBUG(5,("write: %s ", ctime(&mtime)));
4490 DEBUG(5,("change: %s ", ctime(&c_time)));
4491 DEBUG(5,("mode: %x\n", mode));
4494 case SMB_FILE_STANDARD_INFORMATION:
4495 case SMB_QUERY_FILE_STANDARD_INFO:
4497 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4499 SOFF_T(pdata,0,allocation_size);
4500 SOFF_T(pdata,8,file_size);
4501 SIVAL(pdata,16,nlink);
4502 SCVAL(pdata,20,delete_pending?1:0);
4503 SCVAL(pdata,21,(mode&aDIR)?1:0);
4504 SSVAL(pdata,22,0); /* Padding. */
4507 case SMB_FILE_EA_INFORMATION:
4508 case SMB_QUERY_FILE_EA_INFO:
4510 unsigned int ea_size =
4511 estimate_ea_size(conn, fsp, smb_fname->base_name);
4512 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4514 SIVAL(pdata,0,ea_size);
4518 /* Get the 8.3 name - used if NT SMB was negotiated. */
4519 case SMB_QUERY_FILE_ALT_NAME_INFO:
4520 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4523 char mangled_name[13];
4524 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4525 if (!name_to_8_3(base_name,mangled_name,
4526 True,conn->params)) {
4527 return NT_STATUS_NO_MEMORY;
4529 len = srvstr_push(dstart, flags2,
4530 pdata+4, mangled_name,
4531 PTR_DIFF(dend, pdata+4),
4533 data_size = 4 + len;
4538 case SMB_QUERY_FILE_NAME_INFO:
4542 this must be *exactly* right for ACLs on mapped drives to work
4544 len = srvstr_push(dstart, flags2,
4546 PTR_DIFF(dend, pdata+4),
4548 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4549 data_size = 4 + len;
4554 case SMB_FILE_ALLOCATION_INFORMATION:
4555 case SMB_QUERY_FILE_ALLOCATION_INFO:
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4558 SOFF_T(pdata,0,allocation_size);
4561 case SMB_FILE_END_OF_FILE_INFORMATION:
4562 case SMB_QUERY_FILE_END_OF_FILEINFO:
4563 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4565 SOFF_T(pdata,0,file_size);
4568 case SMB_QUERY_FILE_ALL_INFO:
4569 case SMB_FILE_ALL_INFORMATION:
4572 unsigned int ea_size =
4573 estimate_ea_size(conn, fsp, smb_fname->base_name);
4574 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4575 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4576 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4577 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4578 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4579 SIVAL(pdata,32,mode);
4580 SIVAL(pdata,36,0); /* padding. */
4582 SOFF_T(pdata,0,allocation_size);
4583 SOFF_T(pdata,8,file_size);
4584 SIVAL(pdata,16,nlink);
4585 SCVAL(pdata,20,delete_pending);
4586 SCVAL(pdata,21,(mode&aDIR)?1:0);
4589 SIVAL(pdata,0,ea_size);
4590 pdata += 4; /* EA info */
4591 len = srvstr_push(dstart, flags2,
4593 PTR_DIFF(dend, pdata+4),
4597 data_size = PTR_DIFF(pdata,(*ppdata));
4601 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4604 unsigned int ea_size =
4605 estimate_ea_size(conn, fsp, smb_fname->base_name);
4606 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4607 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4608 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4609 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4610 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4611 SIVAL(pdata, 0x20, mode);
4612 SIVAL(pdata, 0x24, 0); /* padding. */
4613 SBVAL(pdata, 0x28, allocation_size);
4614 SBVAL(pdata, 0x30, file_size);
4615 SIVAL(pdata, 0x38, nlink);
4616 SCVAL(pdata, 0x3C, delete_pending);
4617 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4618 SSVAL(pdata, 0x3E, 0); /* padding */
4619 SBVAL(pdata, 0x40, file_index);
4620 SIVAL(pdata, 0x48, ea_size);
4621 SIVAL(pdata, 0x4C, access_mask);
4622 SBVAL(pdata, 0x50, pos);
4623 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4624 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4628 len = srvstr_push(dstart, flags2,
4630 PTR_DIFF(dend, pdata+4),
4634 data_size = PTR_DIFF(pdata,(*ppdata));
4637 case SMB_FILE_INTERNAL_INFORMATION:
4639 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4640 SBVAL(pdata, 0, file_index);
4644 case SMB_FILE_ACCESS_INFORMATION:
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4646 SIVAL(pdata, 0, access_mask);
4650 case SMB_FILE_NAME_INFORMATION:
4651 /* Pathname with leading '\'. */
4654 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4655 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4656 SIVAL(pdata,0,byte_len);
4657 data_size = 4 + byte_len;
4661 case SMB_FILE_DISPOSITION_INFORMATION:
4662 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4664 SCVAL(pdata,0,delete_pending);
4667 case SMB_FILE_POSITION_INFORMATION:
4668 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4670 SOFF_T(pdata,0,pos);
4673 case SMB_FILE_MODE_INFORMATION:
4674 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4675 SIVAL(pdata,0,mode);
4679 case SMB_FILE_ALIGNMENT_INFORMATION:
4680 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4681 SIVAL(pdata,0,0); /* No alignment needed. */
4686 * NT4 server just returns "invalid query" to this - if we try
4687 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4690 /* The first statement above is false - verified using Thursby
4691 * client against NT4 -- gcolley.
4693 case SMB_QUERY_FILE_STREAM_INFO:
4694 case SMB_FILE_STREAM_INFORMATION: {
4695 unsigned int num_streams;
4696 struct stream_struct *streams;
4698 DEBUG(10,("smbd_do_qfilepathinfo: "
4699 "SMB_FILE_STREAM_INFORMATION\n"));
4701 if (is_ntfs_stream_smb_fname(smb_fname)) {
4702 return NT_STATUS_INVALID_PARAMETER;
4705 status = SMB_VFS_STREAMINFO(
4706 conn, fsp, smb_fname->base_name, talloc_tos(),
4707 &num_streams, &streams);
4709 if (!NT_STATUS_IS_OK(status)) {
4710 DEBUG(10, ("could not get stream info: %s\n",
4711 nt_errstr(status)));
4715 status = marshall_stream_info(num_streams, streams,
4716 pdata, max_data_bytes,
4719 if (!NT_STATUS_IS_OK(status)) {
4720 DEBUG(10, ("marshall_stream_info failed: %s\n",
4721 nt_errstr(status)));
4725 TALLOC_FREE(streams);
4729 case SMB_QUERY_COMPRESSION_INFO:
4730 case SMB_FILE_COMPRESSION_INFORMATION:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4732 SOFF_T(pdata,0,file_size);
4733 SIVAL(pdata,8,0); /* ??? */
4734 SIVAL(pdata,12,0); /* ??? */
4738 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4739 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4740 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4741 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4742 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4743 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4744 SOFF_T(pdata,32,allocation_size);
4745 SOFF_T(pdata,40,file_size);
4746 SIVAL(pdata,48,mode);
4747 SIVAL(pdata,52,0); /* ??? */
4751 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4752 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4753 SIVAL(pdata,0,mode);
4759 * CIFS UNIX Extensions.
4762 case SMB_QUERY_FILE_UNIX_BASIC:
4764 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4765 data_size = PTR_DIFF(pdata,(*ppdata));
4767 DEBUG(4,("smbd_do_qfilepathinfo: "
4768 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4769 dump_data(4, (uint8_t *)(*ppdata), data_size);
4773 case SMB_QUERY_FILE_UNIX_INFO2:
4775 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4776 data_size = PTR_DIFF(pdata,(*ppdata));
4780 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4782 for (i=0; i<100; i++)
4783 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4789 case SMB_QUERY_FILE_UNIX_LINK:
4792 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4795 return NT_STATUS_NO_MEMORY;
4798 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4800 if(!S_ISLNK(psbuf->st_ex_mode)) {
4801 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4804 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4806 len = SMB_VFS_READLINK(conn,
4807 smb_fname->base_name,
4810 return map_nt_error_from_unix(errno);
4813 len = srvstr_push(dstart, flags2,
4815 PTR_DIFF(dend, pdata),
4818 data_size = PTR_DIFF(pdata,(*ppdata));
4823 #if defined(HAVE_POSIX_ACLS)
4824 case SMB_QUERY_POSIX_ACL:
4826 SMB_ACL_T file_acl = NULL;
4827 SMB_ACL_T def_acl = NULL;
4828 uint16 num_file_acls = 0;
4829 uint16 num_def_acls = 0;
4831 if (fsp && fsp->fh->fd != -1) {
4832 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4835 SMB_VFS_SYS_ACL_GET_FILE(conn,
4836 smb_fname->base_name,
4837 SMB_ACL_TYPE_ACCESS);
4840 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4841 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4842 "not implemented on "
4843 "filesystem containing %s\n",
4844 smb_fname->base_name));
4845 return NT_STATUS_NOT_IMPLEMENTED;
4848 if (S_ISDIR(psbuf->st_ex_mode)) {
4849 if (fsp && fsp->is_directory) {
4851 SMB_VFS_SYS_ACL_GET_FILE(
4853 fsp->fsp_name->base_name,
4854 SMB_ACL_TYPE_DEFAULT);
4857 SMB_VFS_SYS_ACL_GET_FILE(
4859 smb_fname->base_name,
4860 SMB_ACL_TYPE_DEFAULT);
4862 def_acl = free_empty_sys_acl(conn, def_acl);
4865 num_file_acls = count_acl_entries(conn, file_acl);
4866 num_def_acls = count_acl_entries(conn, def_acl);
4868 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4869 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4871 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4872 SMB_POSIX_ACL_HEADER_SIZE) ));
4874 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4877 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4879 return NT_STATUS_BUFFER_TOO_SMALL;
4882 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4883 SSVAL(pdata,2,num_file_acls);
4884 SSVAL(pdata,4,num_def_acls);
4885 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4887 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4890 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4892 return NT_STATUS_INTERNAL_ERROR;
4894 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4896 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4899 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4901 return NT_STATUS_INTERNAL_ERROR;
4905 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4908 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4910 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4916 case SMB_QUERY_POSIX_LOCK:
4921 enum brl_type lock_type;
4923 /* We need an open file with a real fd for this. */
4924 if (!fsp || fsp->fh->fd == -1) {
4925 return NT_STATUS_INVALID_LEVEL;
4928 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4929 return NT_STATUS_INVALID_PARAMETER;
4932 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4933 case POSIX_LOCK_TYPE_READ:
4934 lock_type = READ_LOCK;
4936 case POSIX_LOCK_TYPE_WRITE:
4937 lock_type = WRITE_LOCK;
4939 case POSIX_LOCK_TYPE_UNLOCK:
4941 /* There's no point in asking for an unlock... */
4942 return NT_STATUS_INVALID_PARAMETER;
4945 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4946 #if defined(HAVE_LONGLONG)
4947 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4948 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4949 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4950 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4951 #else /* HAVE_LONGLONG */
4952 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4953 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4954 #endif /* HAVE_LONGLONG */
4956 status = query_lock(fsp,
4963 if (ERROR_WAS_LOCK_DENIED(status)) {
4964 /* Here we need to report who has it locked... */
4965 data_size = POSIX_LOCK_DATA_SIZE;
4967 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4968 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4969 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4970 #if defined(HAVE_LONGLONG)
4971 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4972 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4973 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4974 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4975 #else /* HAVE_LONGLONG */
4976 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4977 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4978 #endif /* HAVE_LONGLONG */
4980 } else if (NT_STATUS_IS_OK(status)) {
4981 /* For success we just return a copy of what we sent
4982 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4983 data_size = POSIX_LOCK_DATA_SIZE;
4984 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4985 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4993 return NT_STATUS_INVALID_LEVEL;
4996 *pdata_size = data_size;
4997 return NT_STATUS_OK;
5000 /****************************************************************************
5001 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5002 file name or file id).
5003 ****************************************************************************/
5005 static void call_trans2qfilepathinfo(connection_struct *conn,
5006 struct smb_request *req,
5007 unsigned int tran_call,
5008 char **pparams, int total_params,
5009 char **ppdata, int total_data,
5010 unsigned int max_data_bytes)
5012 char *params = *pparams;
5013 char *pdata = *ppdata;
5015 unsigned int data_size = 0;
5016 unsigned int param_size = 2;
5017 struct smb_filename *smb_fname = NULL;
5018 bool delete_pending = False;
5019 struct timespec write_time_ts;
5020 files_struct *fsp = NULL;
5021 struct file_id fileid;
5022 struct ea_list *ea_list = NULL;
5023 int lock_data_count = 0;
5024 char *lock_data = NULL;
5025 NTSTATUS status = NT_STATUS_OK;
5028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5032 ZERO_STRUCT(write_time_ts);
5034 if (tran_call == TRANSACT2_QFILEINFO) {
5035 if (total_params < 4) {
5036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5041 call_trans2qpipeinfo(conn, req, tran_call,
5042 pparams, total_params,
5048 fsp = file_fsp(req, SVAL(params,0));
5049 info_level = SVAL(params,2);
5051 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5053 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5054 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5058 /* Initial check for valid fsp ptr. */
5059 if (!check_fsp_open(conn, req, fsp)) {
5063 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5065 if (!NT_STATUS_IS_OK(status)) {
5066 reply_nterror(req, status);
5070 if(fsp->fake_file_handle) {
5072 * This is actually for the QUOTA_FAKE_FILE --metze
5075 /* We know this name is ok, it's already passed the checks. */
5077 } else if(fsp->fh->fd == -1) {
5079 * This is actually a QFILEINFO on a directory
5080 * handle (returned from an NT SMB). NT5.0 seems
5081 * to do this call. JRA.
5084 if (INFO_LEVEL_IS_UNIX(info_level)) {
5085 /* Always do lstat for UNIX calls. */
5086 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5087 DEBUG(3,("call_trans2qfilepathinfo: "
5088 "SMB_VFS_LSTAT of %s failed "
5090 smb_fname_str_dbg(smb_fname),
5093 map_nt_error_from_unix(errno));
5096 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5097 DEBUG(3,("call_trans2qfilepathinfo: "
5098 "SMB_VFS_STAT of %s failed (%s)\n",
5099 smb_fname_str_dbg(smb_fname),
5102 map_nt_error_from_unix(errno));
5106 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5107 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5110 * Original code - this is an open file.
5112 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5113 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5114 fsp->fnum, strerror(errno)));
5116 map_nt_error_from_unix(errno));
5119 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5120 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5128 if (total_params < 7) {
5129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5133 info_level = SVAL(params,0);
5135 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5137 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5138 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5142 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5144 STR_TERMINATE, &status);
5145 if (!NT_STATUS_IS_OK(status)) {
5146 reply_nterror(req, status);
5150 status = filename_convert(req,
5152 req->flags2 & FLAGS2_DFS_PATHNAMES,
5157 if (!NT_STATUS_IS_OK(status)) {
5158 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5159 reply_botherror(req,
5160 NT_STATUS_PATH_NOT_COVERED,
5161 ERRSRV, ERRbadpath);
5164 reply_nterror(req, status);
5168 /* If this is a stream, check if there is a delete_pending. */
5169 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5170 && is_ntfs_stream_smb_fname(smb_fname)) {
5171 struct smb_filename *smb_fname_base = NULL;
5173 /* Create an smb_filename with stream_name == NULL. */
5175 create_synthetic_smb_fname(talloc_tos(),
5176 smb_fname->base_name,
5179 if (!NT_STATUS_IS_OK(status)) {
5180 reply_nterror(req, status);
5184 if (INFO_LEVEL_IS_UNIX(info_level)) {
5185 /* Always do lstat for UNIX calls. */
5186 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5187 DEBUG(3,("call_trans2qfilepathinfo: "
5188 "SMB_VFS_LSTAT of %s failed "
5190 smb_fname_str_dbg(smb_fname_base),
5192 TALLOC_FREE(smb_fname_base);
5194 map_nt_error_from_unix(errno));
5198 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5199 DEBUG(3,("call_trans2qfilepathinfo: "
5200 "fileinfo of %s failed "
5202 smb_fname_str_dbg(smb_fname_base),
5204 TALLOC_FREE(smb_fname_base);
5206 map_nt_error_from_unix(errno));
5211 status = file_name_hash(conn,
5212 smb_fname_str_dbg(smb_fname_base),
5214 if (!NT_STATUS_IS_OK(status)) {
5215 TALLOC_FREE(smb_fname_base);
5216 reply_nterror(req, status);
5220 fileid = vfs_file_id_from_sbuf(conn,
5221 &smb_fname_base->st);
5222 TALLOC_FREE(smb_fname_base);
5223 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5224 if (delete_pending) {
5225 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5230 if (INFO_LEVEL_IS_UNIX(info_level)) {
5231 /* Always do lstat for UNIX calls. */
5232 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5233 DEBUG(3,("call_trans2qfilepathinfo: "
5234 "SMB_VFS_LSTAT of %s failed (%s)\n",
5235 smb_fname_str_dbg(smb_fname),
5238 map_nt_error_from_unix(errno));
5243 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5244 DEBUG(3,("call_trans2qfilepathinfo: "
5245 "SMB_VFS_STAT of %s failed (%s)\n",
5246 smb_fname_str_dbg(smb_fname),
5249 map_nt_error_from_unix(errno));
5254 status = file_name_hash(conn,
5255 smb_fname_str_dbg(smb_fname),
5257 if (!NT_STATUS_IS_OK(status)) {
5258 reply_nterror(req, status);
5262 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5263 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5264 if (delete_pending) {
5265 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5270 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5271 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5272 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5274 /* Pull out any data sent here before we realloc. */
5275 switch (info_level) {
5276 case SMB_INFO_QUERY_EAS_FROM_LIST:
5278 /* Pull any EA list from the data portion. */
5281 if (total_data < 4) {
5283 req, NT_STATUS_INVALID_PARAMETER);
5286 ea_size = IVAL(pdata,0);
5288 if (total_data > 0 && ea_size != total_data) {
5289 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5290 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5292 req, NT_STATUS_INVALID_PARAMETER);
5296 if (!lp_ea_support(SNUM(conn))) {
5297 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5301 /* Pull out the list of names. */
5302 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5305 req, NT_STATUS_INVALID_PARAMETER);
5311 case SMB_QUERY_POSIX_LOCK:
5313 if (fsp == NULL || fsp->fh->fd == -1) {
5314 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5318 if (total_data != POSIX_LOCK_DATA_SIZE) {
5320 req, NT_STATUS_INVALID_PARAMETER);
5324 /* Copy the lock range data. */
5325 lock_data = (char *)TALLOC_MEMDUP(
5326 req, pdata, total_data);
5328 reply_nterror(req, NT_STATUS_NO_MEMORY);
5331 lock_data_count = total_data;
5337 *pparams = (char *)SMB_REALLOC(*pparams,2);
5338 if (*pparams == NULL) {
5339 reply_nterror(req, NT_STATUS_NO_MEMORY);
5346 * draft-leach-cifs-v1-spec-02.txt
5347 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5350 * The requested information is placed in the Data portion of the
5351 * transaction response. For the information levels greater than 0x100,
5352 * the transaction response has 1 parameter word which should be
5353 * ignored by the client.
5355 * However Windows only follows this rule for the IS_NAME_VALID call.
5357 switch (info_level) {
5358 case SMB_INFO_IS_NAME_VALID:
5363 if ((info_level & 0xFF00) == 0xFF00) {
5365 * We use levels that start with 0xFF00
5366 * internally to represent SMB2 specific levels
5368 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5372 status = smbd_do_qfilepathinfo(conn, req, info_level,
5374 delete_pending, write_time_ts,
5376 lock_data_count, lock_data,
5377 req->flags2, max_data_bytes,
5378 ppdata, &data_size);
5379 if (!NT_STATUS_IS_OK(status)) {
5380 reply_nterror(req, status);
5384 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5390 /****************************************************************************
5391 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5393 ****************************************************************************/
5395 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5396 connection_struct *conn,
5397 struct smb_request *req,
5398 bool overwrite_if_exists,
5399 const struct smb_filename *smb_fname_old,
5400 struct smb_filename *smb_fname_new)
5402 NTSTATUS status = NT_STATUS_OK;
5404 /* source must already exist. */
5405 if (!VALID_STAT(smb_fname_old->st)) {
5406 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5409 if (VALID_STAT(smb_fname_new->st)) {
5410 if (overwrite_if_exists) {
5411 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5412 return NT_STATUS_FILE_IS_A_DIRECTORY;
5414 status = unlink_internals(conn,
5416 FILE_ATTRIBUTE_NORMAL,
5419 if (!NT_STATUS_IS_OK(status)) {
5423 /* Disallow if newname already exists. */
5424 return NT_STATUS_OBJECT_NAME_COLLISION;
5428 /* No links from a directory. */
5429 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5430 return NT_STATUS_FILE_IS_A_DIRECTORY;
5433 /* Setting a hardlink to/from a stream isn't currently supported. */
5434 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5435 is_ntfs_stream_smb_fname(smb_fname_new)) {
5436 return NT_STATUS_INVALID_PARAMETER;
5439 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5440 smb_fname_old->base_name, smb_fname_new->base_name));
5442 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5443 smb_fname_new->base_name) != 0) {
5444 status = map_nt_error_from_unix(errno);
5445 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5446 nt_errstr(status), smb_fname_old->base_name,
5447 smb_fname_new->base_name));
5452 /****************************************************************************
5453 Deal with setting the time from any of the setfilepathinfo functions.
5454 ****************************************************************************/
5456 NTSTATUS smb_set_file_time(connection_struct *conn,
5458 const struct smb_filename *smb_fname,
5459 struct smb_file_time *ft,
5460 bool setting_write_time)
5462 struct smb_filename smb_fname_base;
5464 FILE_NOTIFY_CHANGE_LAST_ACCESS
5465 |FILE_NOTIFY_CHANGE_LAST_WRITE
5466 |FILE_NOTIFY_CHANGE_CREATION;
5468 if (!VALID_STAT(smb_fname->st)) {
5469 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5472 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5473 return NT_STATUS_ACCESS_DENIED;
5476 /* get some defaults (no modifications) if any info is zero or -1. */
5477 if (null_timespec(ft->create_time)) {
5478 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5481 if (null_timespec(ft->atime)) {
5482 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5485 if (null_timespec(ft->mtime)) {
5486 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5489 if (!setting_write_time) {
5490 /* ft->mtime comes from change time, not write time. */
5491 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5494 /* Ensure the resolution is the correct for
5495 * what we can store on this filesystem. */
5497 round_timespec(conn->ts_res, &ft->create_time);
5498 round_timespec(conn->ts_res, &ft->ctime);
5499 round_timespec(conn->ts_res, &ft->atime);
5500 round_timespec(conn->ts_res, &ft->mtime);
5502 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5503 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5504 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5505 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5506 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5507 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5508 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5509 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5511 if (setting_write_time) {
5513 * This was a Windows setfileinfo on an open file.
5514 * NT does this a lot. We also need to
5515 * set the time here, as it can be read by
5516 * FindFirst/FindNext and with the patch for bug #2045
5517 * in smbd/fileio.c it ensures that this timestamp is
5518 * kept sticky even after a write. We save the request
5519 * away and will set it on file close and after a write. JRA.
5522 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5523 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5526 if (fsp->base_fsp) {
5527 set_sticky_write_time_fsp(fsp->base_fsp,
5530 set_sticky_write_time_fsp(fsp, ft->mtime);
5533 set_sticky_write_time_path(
5534 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5539 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5541 /* Always call ntimes on the base, even if a stream was passed in. */
5542 smb_fname_base = *smb_fname;
5543 smb_fname_base.stream_name = NULL;
5545 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5546 return map_nt_error_from_unix(errno);
5549 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5550 smb_fname->base_name);
5551 return NT_STATUS_OK;
5554 /****************************************************************************
5555 Deal with setting the dosmode from any of the setfilepathinfo functions.
5556 ****************************************************************************/
5558 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5559 const struct smb_filename *smb_fname,
5562 struct smb_filename *smb_fname_base = NULL;
5565 if (!VALID_STAT(smb_fname->st)) {
5566 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5569 /* Always operate on the base_name, even if a stream was passed in. */
5570 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5571 NULL, &smb_fname->st,
5573 if (!NT_STATUS_IS_OK(status)) {
5578 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5585 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5587 /* check the mode isn't different, before changing it */
5588 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5589 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5590 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5591 (unsigned int)dosmode));
5593 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5595 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5597 smb_fname_str_dbg(smb_fname_base),
5599 status = map_nt_error_from_unix(errno);
5603 status = NT_STATUS_OK;
5605 TALLOC_FREE(smb_fname_base);
5609 /****************************************************************************
5610 Deal with setting the size from any of the setfilepathinfo functions.
5611 ****************************************************************************/
5613 static NTSTATUS smb_set_file_size(connection_struct *conn,
5614 struct smb_request *req,
5616 const struct smb_filename *smb_fname,
5617 const SMB_STRUCT_STAT *psbuf,
5619 bool fail_after_createfile)
5621 NTSTATUS status = NT_STATUS_OK;
5622 struct smb_filename *smb_fname_tmp = NULL;
5623 files_struct *new_fsp = NULL;
5625 if (!VALID_STAT(*psbuf)) {
5626 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5629 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5630 return NT_STATUS_ACCESS_DENIED;
5633 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5635 if (size == get_file_size_stat(psbuf)) {
5636 return NT_STATUS_OK;
5639 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5640 smb_fname_str_dbg(smb_fname), (double)size));
5642 if (fsp && fsp->fh->fd != -1) {
5643 /* Handle based call. */
5644 if (vfs_set_filelen(fsp, size) == -1) {
5645 return map_nt_error_from_unix(errno);
5647 trigger_write_time_update_immediate(fsp);
5648 return NT_STATUS_OK;
5651 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5652 if (!NT_STATUS_IS_OK(status)) {
5656 smb_fname_tmp->st = *psbuf;
5658 status = SMB_VFS_CREATE_FILE(
5661 0, /* root_dir_fid */
5662 smb_fname_tmp, /* fname */
5663 FILE_WRITE_DATA, /* access_mask */
5664 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5666 FILE_OPEN, /* create_disposition*/
5667 0, /* create_options */
5668 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5669 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5670 0, /* allocation_size */
5671 0, /* private_flags */
5674 &new_fsp, /* result */
5677 TALLOC_FREE(smb_fname_tmp);
5679 if (!NT_STATUS_IS_OK(status)) {
5680 /* NB. We check for open_was_deferred in the caller. */
5684 /* See RAW-SFILEINFO-END-OF-FILE */
5685 if (fail_after_createfile) {
5686 close_file(req, new_fsp,NORMAL_CLOSE);
5687 return NT_STATUS_INVALID_LEVEL;
5690 if (vfs_set_filelen(new_fsp, size) == -1) {
5691 status = map_nt_error_from_unix(errno);
5692 close_file(req, new_fsp,NORMAL_CLOSE);
5696 trigger_write_time_update_immediate(new_fsp);
5697 close_file(req, new_fsp,NORMAL_CLOSE);
5698 return NT_STATUS_OK;
5701 /****************************************************************************
5702 Deal with SMB_INFO_SET_EA.
5703 ****************************************************************************/
5705 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5709 const struct smb_filename *smb_fname)
5711 struct ea_list *ea_list = NULL;
5712 TALLOC_CTX *ctx = NULL;
5713 NTSTATUS status = NT_STATUS_OK;
5715 if (total_data < 10) {
5717 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5718 length. They seem to have no effect. Bug #3212. JRA */
5720 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5721 /* We're done. We only get EA info in this call. */
5722 return NT_STATUS_OK;
5725 return NT_STATUS_INVALID_PARAMETER;
5728 if (IVAL(pdata,0) > total_data) {
5729 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5730 IVAL(pdata,0), (unsigned int)total_data));
5731 return NT_STATUS_INVALID_PARAMETER;
5735 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5737 return NT_STATUS_INVALID_PARAMETER;
5740 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5741 return NT_STATUS_ACCESS_DENIED;
5744 status = set_ea(conn, fsp, smb_fname, ea_list);
5749 /****************************************************************************
5750 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5751 ****************************************************************************/
5753 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5758 struct ea_list *ea_list = NULL;
5762 return NT_STATUS_INVALID_HANDLE;
5765 if (!lp_ea_support(SNUM(conn))) {
5766 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5767 "EA's not supported.\n",
5768 (unsigned int)total_data));
5769 return NT_STATUS_EAS_NOT_SUPPORTED;
5772 if (total_data < 10) {
5773 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5775 (unsigned int)total_data));
5776 return NT_STATUS_INVALID_PARAMETER;
5779 ea_list = read_nttrans_ea_list(talloc_tos(),
5784 return NT_STATUS_INVALID_PARAMETER;
5787 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5788 return NT_STATUS_ACCESS_DENIED;
5791 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5793 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5794 smb_fname_str_dbg(fsp->fsp_name),
5795 nt_errstr(status) ));
5801 /****************************************************************************
5802 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5803 ****************************************************************************/
5805 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5809 struct smb_filename *smb_fname)
5811 NTSTATUS status = NT_STATUS_OK;
5812 bool delete_on_close;
5815 if (total_data < 1) {
5816 return NT_STATUS_INVALID_PARAMETER;
5820 return NT_STATUS_INVALID_HANDLE;
5823 delete_on_close = (CVAL(pdata,0) ? True : False);
5824 dosmode = dos_mode(conn, smb_fname);
5826 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5827 "delete_on_close = %u\n",
5828 smb_fname_str_dbg(smb_fname),
5829 (unsigned int)dosmode,
5830 (unsigned int)delete_on_close ));
5832 if (delete_on_close) {
5833 status = can_set_delete_on_close(fsp, dosmode);
5834 if (!NT_STATUS_IS_OK(status)) {
5839 /* The set is across all open files on this dev/inode pair. */
5840 if (!set_delete_on_close(fsp, delete_on_close,
5841 &conn->server_info->utok)) {
5842 return NT_STATUS_ACCESS_DENIED;
5844 return NT_STATUS_OK;
5847 /****************************************************************************
5848 Deal with SMB_FILE_POSITION_INFORMATION.
5849 ****************************************************************************/
5851 static NTSTATUS smb_file_position_information(connection_struct *conn,
5856 uint64_t position_information;
5858 if (total_data < 8) {
5859 return NT_STATUS_INVALID_PARAMETER;
5863 /* Ignore on pathname based set. */
5864 return NT_STATUS_OK;
5867 position_information = (uint64_t)IVAL(pdata,0);
5868 #ifdef LARGE_SMB_OFF_T
5869 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5870 #else /* LARGE_SMB_OFF_T */
5871 if (IVAL(pdata,4) != 0) {
5872 /* more than 32 bits? */
5873 return NT_STATUS_INVALID_PARAMETER;
5875 #endif /* LARGE_SMB_OFF_T */
5877 DEBUG(10,("smb_file_position_information: Set file position "
5878 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5879 (double)position_information));
5880 fsp->fh->position_information = position_information;
5881 return NT_STATUS_OK;
5884 /****************************************************************************
5885 Deal with SMB_FILE_MODE_INFORMATION.
5886 ****************************************************************************/
5888 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5894 if (total_data < 4) {
5895 return NT_STATUS_INVALID_PARAMETER;
5897 mode = IVAL(pdata,0);
5898 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5899 return NT_STATUS_INVALID_PARAMETER;
5901 return NT_STATUS_OK;
5904 /****************************************************************************
5905 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5906 ****************************************************************************/
5908 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5909 struct smb_request *req,
5912 const struct smb_filename *smb_fname)
5914 char *link_target = NULL;
5915 const char *newname = smb_fname->base_name;
5916 TALLOC_CTX *ctx = talloc_tos();
5918 /* Set a symbolic link. */
5919 /* Don't allow this if follow links is false. */
5921 if (total_data == 0) {
5922 return NT_STATUS_INVALID_PARAMETER;
5925 if (!lp_symlinks(SNUM(conn))) {
5926 return NT_STATUS_ACCESS_DENIED;
5929 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5930 total_data, STR_TERMINATE);
5933 return NT_STATUS_INVALID_PARAMETER;
5936 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5937 newname, link_target ));
5939 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5940 return map_nt_error_from_unix(errno);
5943 return NT_STATUS_OK;
5946 /****************************************************************************
5947 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5948 ****************************************************************************/
5950 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5951 struct smb_request *req,
5952 const char *pdata, int total_data,
5953 struct smb_filename *smb_fname_new)
5955 char *oldname = NULL;
5956 struct smb_filename *smb_fname_old = NULL;
5957 TALLOC_CTX *ctx = talloc_tos();
5958 NTSTATUS status = NT_STATUS_OK;
5960 /* Set a hard link. */
5961 if (total_data == 0) {
5962 return NT_STATUS_INVALID_PARAMETER;
5965 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5966 total_data, STR_TERMINATE, &status);
5967 if (!NT_STATUS_IS_OK(status)) {
5971 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5972 smb_fname_str_dbg(smb_fname_new), oldname));
5974 status = filename_convert(ctx,
5976 req->flags2 & FLAGS2_DFS_PATHNAMES,
5981 if (!NT_STATUS_IS_OK(status)) {
5985 return hardlink_internals(ctx, conn, req, false,
5986 smb_fname_old, smb_fname_new);
5989 /****************************************************************************
5990 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5991 ****************************************************************************/
5993 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5994 struct smb_request *req,
5998 struct smb_filename *smb_fname_src)
6002 char *newname = NULL;
6003 struct smb_filename *smb_fname_dst = NULL;
6004 NTSTATUS status = NT_STATUS_OK;
6005 TALLOC_CTX *ctx = talloc_tos();
6008 return NT_STATUS_INVALID_HANDLE;
6011 if (total_data < 20) {
6012 return NT_STATUS_INVALID_PARAMETER;
6015 overwrite = (CVAL(pdata,0) ? True : False);
6016 len = IVAL(pdata,16);
6018 if (len > (total_data - 20) || (len == 0)) {
6019 return NT_STATUS_INVALID_PARAMETER;
6022 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6023 &pdata[20], len, STR_TERMINATE,
6025 if (!NT_STATUS_IS_OK(status)) {
6029 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6032 status = filename_convert(ctx,
6034 req->flags2 & FLAGS2_DFS_PATHNAMES,
6039 if (!NT_STATUS_IS_OK(status)) {
6043 if (fsp->base_fsp) {
6044 /* newname must be a stream name. */
6045 if (newname[0] != ':') {
6046 return NT_STATUS_NOT_SUPPORTED;
6049 /* Create an smb_fname to call rename_internals_fsp() with. */
6050 status = create_synthetic_smb_fname(talloc_tos(),
6051 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6053 if (!NT_STATUS_IS_OK(status)) {
6058 * Set the original last component, since
6059 * rename_internals_fsp() requires it.
6061 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6063 if (smb_fname_dst->original_lcomp == NULL) {
6064 status = NT_STATUS_NO_MEMORY;
6070 DEBUG(10,("smb2_file_rename_information: "
6071 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6072 fsp->fnum, fsp_str_dbg(fsp),
6073 smb_fname_str_dbg(smb_fname_dst)));
6074 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6078 TALLOC_FREE(smb_fname_dst);
6082 static NTSTATUS smb_file_link_information(connection_struct *conn,
6083 struct smb_request *req,
6087 struct smb_filename *smb_fname_src)
6091 char *newname = NULL;
6092 struct smb_filename *smb_fname_dst = NULL;
6093 NTSTATUS status = NT_STATUS_OK;
6094 TALLOC_CTX *ctx = talloc_tos();
6097 return NT_STATUS_INVALID_HANDLE;
6100 if (total_data < 20) {
6101 return NT_STATUS_INVALID_PARAMETER;
6104 overwrite = (CVAL(pdata,0) ? true : false);
6105 len = IVAL(pdata,16);
6107 if (len > (total_data - 20) || (len == 0)) {
6108 return NT_STATUS_INVALID_PARAMETER;
6111 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6112 &pdata[20], len, STR_TERMINATE,
6114 if (!NT_STATUS_IS_OK(status)) {
6118 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6121 status = filename_convert(ctx,
6123 req->flags2 & FLAGS2_DFS_PATHNAMES,
6128 if (!NT_STATUS_IS_OK(status)) {
6132 if (fsp->base_fsp) {
6133 /* No stream names. */
6134 return NT_STATUS_NOT_SUPPORTED;
6137 DEBUG(10,("smb_file_link_information: "
6138 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6139 fsp->fnum, fsp_str_dbg(fsp),
6140 smb_fname_str_dbg(smb_fname_dst)));
6141 status = hardlink_internals(ctx,
6148 TALLOC_FREE(smb_fname_dst);
6152 /****************************************************************************
6153 Deal with SMB_FILE_RENAME_INFORMATION.
6154 ****************************************************************************/
6156 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6157 struct smb_request *req,
6161 struct smb_filename *smb_fname_src)
6166 char *newname = NULL;
6167 struct smb_filename *smb_fname_dst = NULL;
6168 bool dest_has_wcard = False;
6169 NTSTATUS status = NT_STATUS_OK;
6171 TALLOC_CTX *ctx = talloc_tos();
6173 if (total_data < 13) {
6174 return NT_STATUS_INVALID_PARAMETER;
6177 overwrite = (CVAL(pdata,0) ? True : False);
6178 root_fid = IVAL(pdata,4);
6179 len = IVAL(pdata,8);
6181 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6182 return NT_STATUS_INVALID_PARAMETER;
6185 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6188 if (!NT_STATUS_IS_OK(status)) {
6192 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6195 status = resolve_dfspath_wcard(ctx, conn,
6196 req->flags2 & FLAGS2_DFS_PATHNAMES,
6201 if (!NT_STATUS_IS_OK(status)) {
6205 /* Check the new name has no '/' characters. */
6206 if (strchr_m(newname, '/')) {
6207 return NT_STATUS_NOT_SUPPORTED;
6210 if (fsp && fsp->base_fsp) {
6211 /* newname must be a stream name. */
6212 if (newname[0] != ':') {
6213 return NT_STATUS_NOT_SUPPORTED;
6216 /* Create an smb_fname to call rename_internals_fsp() with. */
6217 status = create_synthetic_smb_fname(talloc_tos(),
6218 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6220 if (!NT_STATUS_IS_OK(status)) {
6225 * Set the original last component, since
6226 * rename_internals_fsp() requires it.
6228 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6230 if (smb_fname_dst->original_lcomp == NULL) {
6231 status = NT_STATUS_NO_MEMORY;
6237 * Build up an smb_fname_dst based on the filename passed in.
6238 * We basically just strip off the last component, and put on
6239 * the newname instead.
6241 char *base_name = NULL;
6243 /* newname must *not* be a stream name. */
6244 if (newname[0] == ':') {
6245 return NT_STATUS_NOT_SUPPORTED;
6249 * Strip off the last component (filename) of the path passed
6252 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6254 return NT_STATUS_NO_MEMORY;
6256 p = strrchr_m(base_name, '/');
6260 base_name = talloc_strdup(ctx, "");
6262 return NT_STATUS_NO_MEMORY;
6265 /* Append the new name. */
6266 base_name = talloc_asprintf_append(base_name,
6270 return NT_STATUS_NO_MEMORY;
6273 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6276 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6279 /* If an error we expect this to be
6280 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6282 if (!NT_STATUS_IS_OK(status)) {
6283 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6287 /* Create an smb_fname to call rename_internals_fsp() */
6288 status = create_synthetic_smb_fname(ctx,
6292 if (!NT_STATUS_IS_OK(status)) {
6299 DEBUG(10,("smb_file_rename_information: "
6300 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6301 fsp->fnum, fsp_str_dbg(fsp),
6302 smb_fname_str_dbg(smb_fname_dst)));
6303 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6306 DEBUG(10,("smb_file_rename_information: "
6307 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6308 smb_fname_str_dbg(smb_fname_src),
6309 smb_fname_str_dbg(smb_fname_dst)));
6310 status = rename_internals(ctx, conn, req, smb_fname_src,
6311 smb_fname_dst, 0, overwrite, false,
6313 FILE_WRITE_ATTRIBUTES);
6316 TALLOC_FREE(smb_fname_dst);
6320 /****************************************************************************
6321 Deal with SMB_SET_POSIX_ACL.
6322 ****************************************************************************/
6324 #if defined(HAVE_POSIX_ACLS)
6325 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6329 const struct smb_filename *smb_fname)
6331 uint16 posix_acl_version;
6332 uint16 num_file_acls;
6333 uint16 num_def_acls;
6334 bool valid_file_acls = True;
6335 bool valid_def_acls = True;
6337 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6338 return NT_STATUS_INVALID_PARAMETER;
6340 posix_acl_version = SVAL(pdata,0);
6341 num_file_acls = SVAL(pdata,2);
6342 num_def_acls = SVAL(pdata,4);
6344 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6345 valid_file_acls = False;
6349 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6350 valid_def_acls = False;
6354 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6355 return NT_STATUS_INVALID_PARAMETER;
6358 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6359 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6360 return NT_STATUS_INVALID_PARAMETER;
6363 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6364 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6365 (unsigned int)num_file_acls,
6366 (unsigned int)num_def_acls));
6368 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6369 smb_fname->base_name, num_file_acls,
6370 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6371 return map_nt_error_from_unix(errno);
6374 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6375 smb_fname->base_name, &smb_fname->st, num_def_acls,
6376 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6377 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6378 return map_nt_error_from_unix(errno);
6380 return NT_STATUS_OK;
6384 /****************************************************************************
6385 Deal with SMB_SET_POSIX_LOCK.
6386 ****************************************************************************/
6388 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6389 struct smb_request *req,
6397 bool blocking_lock = False;
6398 enum brl_type lock_type;
6400 NTSTATUS status = NT_STATUS_OK;
6402 if (fsp == NULL || fsp->fh->fd == -1) {
6403 return NT_STATUS_INVALID_HANDLE;
6406 if (total_data != POSIX_LOCK_DATA_SIZE) {
6407 return NT_STATUS_INVALID_PARAMETER;
6410 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6411 case POSIX_LOCK_TYPE_READ:
6412 lock_type = READ_LOCK;
6414 case POSIX_LOCK_TYPE_WRITE:
6415 /* Return the right POSIX-mappable error code for files opened read-only. */
6416 if (!fsp->can_write) {
6417 return NT_STATUS_INVALID_HANDLE;
6419 lock_type = WRITE_LOCK;
6421 case POSIX_LOCK_TYPE_UNLOCK:
6422 lock_type = UNLOCK_LOCK;
6425 return NT_STATUS_INVALID_PARAMETER;
6428 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6429 blocking_lock = False;
6430 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6431 blocking_lock = True;
6433 return NT_STATUS_INVALID_PARAMETER;
6436 if (!lp_blocking_locks(SNUM(conn))) {
6437 blocking_lock = False;
6440 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6441 #if defined(HAVE_LONGLONG)
6442 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6443 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6444 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6445 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6446 #else /* HAVE_LONGLONG */
6447 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6448 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6449 #endif /* HAVE_LONGLONG */
6451 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6452 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6454 (unsigned int)lock_type,
6455 (unsigned long long)smblctx,
6459 if (lock_type == UNLOCK_LOCK) {
6460 status = do_unlock(req->sconn->msg_ctx,
6467 uint64_t block_smblctx;
6469 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6481 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6483 * A blocking lock was requested. Package up
6484 * this smb into a queued request and push it
6485 * onto the blocking lock queue.
6487 if(push_blocking_lock_request(br_lck,
6490 -1, /* infinite timeout. */
6498 TALLOC_FREE(br_lck);
6502 TALLOC_FREE(br_lck);
6508 /****************************************************************************
6509 Deal with SMB_SET_FILE_BASIC_INFO.
6510 ****************************************************************************/
6512 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6516 const struct smb_filename *smb_fname)
6518 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6519 struct smb_file_time ft;
6521 NTSTATUS status = NT_STATUS_OK;
6525 if (total_data < 36) {
6526 return NT_STATUS_INVALID_PARAMETER;
6529 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6530 return NT_STATUS_ACCESS_DENIED;
6533 /* Set the attributes */
6534 dosmode = IVAL(pdata,32);
6535 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6536 if (!NT_STATUS_IS_OK(status)) {
6541 ft.create_time = interpret_long_date(pdata);
6544 ft.atime = interpret_long_date(pdata+8);
6547 ft.mtime = interpret_long_date(pdata+16);
6550 ft.ctime = interpret_long_date(pdata+24);
6552 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6553 smb_fname_str_dbg(smb_fname)));
6555 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6559 /****************************************************************************
6560 Deal with SMB_INFO_STANDARD.
6561 ****************************************************************************/
6563 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6567 const struct smb_filename *smb_fname)
6569 struct smb_file_time ft;
6573 if (total_data < 12) {
6574 return NT_STATUS_INVALID_PARAMETER;
6577 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6578 return NT_STATUS_ACCESS_DENIED;
6582 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6584 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6586 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6588 DEBUG(10,("smb_set_info_standard: file %s\n",
6589 smb_fname_str_dbg(smb_fname)));
6591 return smb_set_file_time(conn,
6598 /****************************************************************************
6599 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6600 ****************************************************************************/
6602 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6603 struct smb_request *req,
6607 struct smb_filename *smb_fname)
6609 uint64_t allocation_size = 0;
6610 NTSTATUS status = NT_STATUS_OK;
6611 files_struct *new_fsp = NULL;
6613 if (!VALID_STAT(smb_fname->st)) {
6614 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6617 if (total_data < 8) {
6618 return NT_STATUS_INVALID_PARAMETER;
6621 allocation_size = (uint64_t)IVAL(pdata,0);
6622 #ifdef LARGE_SMB_OFF_T
6623 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6624 #else /* LARGE_SMB_OFF_T */
6625 if (IVAL(pdata,4) != 0) {
6626 /* more than 32 bits? */
6627 return NT_STATUS_INVALID_PARAMETER;
6629 #endif /* LARGE_SMB_OFF_T */
6631 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6632 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6633 (double)allocation_size));
6635 if (allocation_size) {
6636 allocation_size = smb_roundup(conn, allocation_size);
6639 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6640 return NT_STATUS_ACCESS_DENIED;
6643 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6644 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6645 (double)allocation_size));
6647 if (fsp && fsp->fh->fd != -1) {
6648 /* Open file handle. */
6649 /* Only change if needed. */
6650 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6651 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6652 return map_nt_error_from_unix(errno);
6655 /* But always update the time. */
6657 * This is equivalent to a write. Ensure it's seen immediately
6658 * if there are no pending writes.
6660 trigger_write_time_update_immediate(fsp);
6661 return NT_STATUS_OK;
6664 /* Pathname or stat or directory file. */
6665 status = SMB_VFS_CREATE_FILE(
6668 0, /* root_dir_fid */
6669 smb_fname, /* fname */
6670 FILE_WRITE_DATA, /* access_mask */
6671 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6673 FILE_OPEN, /* create_disposition*/
6674 0, /* create_options */
6675 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6676 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6677 0, /* allocation_size */
6678 0, /* private_flags */
6681 &new_fsp, /* result */
6684 if (!NT_STATUS_IS_OK(status)) {
6685 /* NB. We check for open_was_deferred in the caller. */
6689 /* Only change if needed. */
6690 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6691 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6692 status = map_nt_error_from_unix(errno);
6693 close_file(req, new_fsp, NORMAL_CLOSE);
6698 /* Changing the allocation size should set the last mod time. */
6700 * This is equivalent to a write. Ensure it's seen immediately
6701 * if there are no pending writes.
6703 trigger_write_time_update_immediate(new_fsp);
6705 close_file(req, new_fsp, NORMAL_CLOSE);
6706 return NT_STATUS_OK;
6709 /****************************************************************************
6710 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6711 ****************************************************************************/
6713 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6714 struct smb_request *req,
6718 const struct smb_filename *smb_fname,
6719 bool fail_after_createfile)
6723 if (total_data < 8) {
6724 return NT_STATUS_INVALID_PARAMETER;
6727 size = IVAL(pdata,0);
6728 #ifdef LARGE_SMB_OFF_T
6729 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6730 #else /* LARGE_SMB_OFF_T */
6731 if (IVAL(pdata,4) != 0) {
6732 /* more than 32 bits? */
6733 return NT_STATUS_INVALID_PARAMETER;
6735 #endif /* LARGE_SMB_OFF_T */
6736 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6737 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6740 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6741 return NT_STATUS_ACCESS_DENIED;
6744 return smb_set_file_size(conn, req,
6749 fail_after_createfile);
6752 /****************************************************************************
6753 Allow a UNIX info mknod.
6754 ****************************************************************************/
6756 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6759 const struct smb_filename *smb_fname)
6761 uint32 file_type = IVAL(pdata,56);
6762 #if defined(HAVE_MAKEDEV)
6763 uint32 dev_major = IVAL(pdata,60);
6764 uint32 dev_minor = IVAL(pdata,68);
6766 SMB_DEV_T dev = (SMB_DEV_T)0;
6767 uint32 raw_unixmode = IVAL(pdata,84);
6771 if (total_data < 100) {
6772 return NT_STATUS_INVALID_PARAMETER;
6775 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6776 PERM_NEW_FILE, &unixmode);
6777 if (!NT_STATUS_IS_OK(status)) {
6781 #if defined(HAVE_MAKEDEV)
6782 dev = makedev(dev_major, dev_minor);
6785 switch (file_type) {
6786 #if defined(S_IFIFO)
6787 case UNIX_TYPE_FIFO:
6788 unixmode |= S_IFIFO;
6791 #if defined(S_IFSOCK)
6792 case UNIX_TYPE_SOCKET:
6793 unixmode |= S_IFSOCK;
6796 #if defined(S_IFCHR)
6797 case UNIX_TYPE_CHARDEV:
6798 unixmode |= S_IFCHR;
6801 #if defined(S_IFBLK)
6802 case UNIX_TYPE_BLKDEV:
6803 unixmode |= S_IFBLK;
6807 return NT_STATUS_INVALID_PARAMETER;
6810 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6811 "%.0f mode 0%o for file %s\n", (double)dev,
6812 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6814 /* Ok - do the mknod. */
6815 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6816 return map_nt_error_from_unix(errno);
6819 /* If any of the other "set" calls fail we
6820 * don't want to end up with a half-constructed mknod.
6823 if (lp_inherit_perms(SNUM(conn))) {
6825 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6827 return NT_STATUS_NO_MEMORY;
6829 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6831 TALLOC_FREE(parent);
6834 return NT_STATUS_OK;
6837 /****************************************************************************
6838 Deal with SMB_SET_FILE_UNIX_BASIC.
6839 ****************************************************************************/
6841 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6842 struct smb_request *req,
6846 const struct smb_filename *smb_fname)
6848 struct smb_file_time ft;
6849 uint32 raw_unixmode;
6852 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6853 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6854 NTSTATUS status = NT_STATUS_OK;
6855 bool delete_on_fail = False;
6856 enum perm_type ptype;
6857 files_struct *all_fsps = NULL;
6858 bool modify_mtime = true;
6860 struct smb_filename *smb_fname_tmp = NULL;
6861 SMB_STRUCT_STAT sbuf;
6865 if (total_data < 100) {
6866 return NT_STATUS_INVALID_PARAMETER;
6869 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6870 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6871 size=IVAL(pdata,0); /* first 8 Bytes are size */
6872 #ifdef LARGE_SMB_OFF_T
6873 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6874 #else /* LARGE_SMB_OFF_T */
6875 if (IVAL(pdata,4) != 0) {
6876 /* more than 32 bits? */
6877 return NT_STATUS_INVALID_PARAMETER;
6879 #endif /* LARGE_SMB_OFF_T */
6882 ft.atime = interpret_long_date(pdata+24); /* access_time */
6883 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6884 set_owner = (uid_t)IVAL(pdata,40);
6885 set_grp = (gid_t)IVAL(pdata,48);
6886 raw_unixmode = IVAL(pdata,84);
6888 if (VALID_STAT(smb_fname->st)) {
6889 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6890 ptype = PERM_EXISTING_DIR;
6892 ptype = PERM_EXISTING_FILE;
6895 ptype = PERM_NEW_FILE;
6898 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6900 if (!NT_STATUS_IS_OK(status)) {
6904 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6905 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6906 smb_fname_str_dbg(smb_fname), (double)size,
6907 (unsigned int)set_owner, (unsigned int)set_grp,
6908 (int)raw_unixmode));
6910 sbuf = smb_fname->st;
6912 if (!VALID_STAT(sbuf)) {
6914 * The only valid use of this is to create character and block
6915 * devices, and named pipes. This is deprecated (IMHO) and
6916 * a new info level should be used for mknod. JRA.
6919 status = smb_unix_mknod(conn,
6923 if (!NT_STATUS_IS_OK(status)) {
6927 status = copy_smb_filename(talloc_tos(), smb_fname,
6929 if (!NT_STATUS_IS_OK(status)) {
6933 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6934 status = map_nt_error_from_unix(errno);
6935 TALLOC_FREE(smb_fname_tmp);
6936 SMB_VFS_UNLINK(conn, smb_fname);
6940 sbuf = smb_fname_tmp->st;
6941 smb_fname = smb_fname_tmp;
6943 /* Ensure we don't try and change anything else. */
6944 raw_unixmode = SMB_MODE_NO_CHANGE;
6945 size = get_file_size_stat(&sbuf);
6946 ft.atime = sbuf.st_ex_atime;
6947 ft.mtime = sbuf.st_ex_mtime;
6949 * We continue here as we might want to change the
6952 delete_on_fail = True;
6956 /* Horrible backwards compatibility hack as an old server bug
6957 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6961 size = get_file_size_stat(&sbuf);
6966 * Deal with the UNIX specific mode set.
6969 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6970 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6971 "setting mode 0%o for file %s\n",
6972 (unsigned int)unixmode,
6973 smb_fname_str_dbg(smb_fname)));
6974 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6975 return map_nt_error_from_unix(errno);
6980 * Deal with the UNIX specific uid set.
6983 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6984 (sbuf.st_ex_uid != set_owner)) {
6987 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6988 "changing owner %u for path %s\n",
6989 (unsigned int)set_owner,
6990 smb_fname_str_dbg(smb_fname)));
6992 if (S_ISLNK(sbuf.st_ex_mode)) {
6993 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6994 set_owner, (gid_t)-1);
6996 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6997 set_owner, (gid_t)-1);
7001 status = map_nt_error_from_unix(errno);
7002 if (delete_on_fail) {
7003 SMB_VFS_UNLINK(conn, smb_fname);
7010 * Deal with the UNIX specific gid set.
7013 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7014 (sbuf.st_ex_gid != set_grp)) {
7015 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7016 "changing group %u for file %s\n",
7017 (unsigned int)set_owner,
7018 smb_fname_str_dbg(smb_fname)));
7019 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7021 status = map_nt_error_from_unix(errno);
7022 if (delete_on_fail) {
7023 SMB_VFS_UNLINK(conn, smb_fname);
7029 /* Deal with any size changes. */
7031 status = smb_set_file_size(conn, req,
7037 if (!NT_STATUS_IS_OK(status)) {
7041 /* Deal with any time changes. */
7042 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7043 /* No change, don't cancel anything. */
7047 id = vfs_file_id_from_sbuf(conn, &sbuf);
7048 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7049 all_fsps = file_find_di_next(all_fsps)) {
7051 * We're setting the time explicitly for UNIX.
7052 * Cancel any pending changes over all handles.
7054 all_fsps->update_write_time_on_close = false;
7055 TALLOC_FREE(all_fsps->update_write_time_event);
7059 * Override the "setting_write_time"
7060 * parameter here as it almost does what
7061 * we need. Just remember if we modified
7062 * mtime and send the notify ourselves.
7064 if (null_timespec(ft.mtime)) {
7065 modify_mtime = false;
7068 status = smb_set_file_time(conn,
7074 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7075 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7080 /****************************************************************************
7081 Deal with SMB_SET_FILE_UNIX_INFO2.
7082 ****************************************************************************/
7084 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7085 struct smb_request *req,
7089 const struct smb_filename *smb_fname)
7095 if (total_data < 116) {
7096 return NT_STATUS_INVALID_PARAMETER;
7099 /* Start by setting all the fields that are common between UNIX_BASIC
7102 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7104 if (!NT_STATUS_IS_OK(status)) {
7108 smb_fflags = IVAL(pdata, 108);
7109 smb_fmask = IVAL(pdata, 112);
7111 /* NB: We should only attempt to alter the file flags if the client
7112 * sends a non-zero mask.
7114 if (smb_fmask != 0) {
7115 int stat_fflags = 0;
7117 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7118 smb_fmask, &stat_fflags)) {
7119 /* Client asked to alter a flag we don't understand. */
7120 return NT_STATUS_INVALID_PARAMETER;
7123 if (fsp && fsp->fh->fd != -1) {
7124 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7125 return NT_STATUS_NOT_SUPPORTED;
7127 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7128 stat_fflags) != 0) {
7129 return map_nt_error_from_unix(errno);
7134 /* XXX: need to add support for changing the create_time here. You
7135 * can do this for paths on Darwin with setattrlist(2). The right way
7136 * to hook this up is probably by extending the VFS utimes interface.
7139 return NT_STATUS_OK;
7142 /****************************************************************************
7143 Create a directory with POSIX semantics.
7144 ****************************************************************************/
7146 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7147 struct smb_request *req,
7150 struct smb_filename *smb_fname,
7151 int *pdata_return_size)
7153 NTSTATUS status = NT_STATUS_OK;
7154 uint32 raw_unixmode = 0;
7155 uint32 mod_unixmode = 0;
7156 mode_t unixmode = (mode_t)0;
7157 files_struct *fsp = NULL;
7158 uint16 info_level_return = 0;
7160 char *pdata = *ppdata;
7162 if (total_data < 18) {
7163 return NT_STATUS_INVALID_PARAMETER;
7166 raw_unixmode = IVAL(pdata,8);
7167 /* Next 4 bytes are not yet defined. */
7169 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7170 PERM_NEW_DIR, &unixmode);
7171 if (!NT_STATUS_IS_OK(status)) {
7175 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7177 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7178 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7180 status = SMB_VFS_CREATE_FILE(
7183 0, /* root_dir_fid */
7184 smb_fname, /* fname */
7185 FILE_READ_ATTRIBUTES, /* access_mask */
7186 FILE_SHARE_NONE, /* share_access */
7187 FILE_CREATE, /* create_disposition*/
7188 FILE_DIRECTORY_FILE, /* create_options */
7189 mod_unixmode, /* file_attributes */
7190 0, /* oplock_request */
7191 0, /* allocation_size */
7192 0, /* private_flags */
7198 if (NT_STATUS_IS_OK(status)) {
7199 close_file(req, fsp, NORMAL_CLOSE);
7202 info_level_return = SVAL(pdata,16);
7204 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7205 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7206 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7207 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7209 *pdata_return_size = 12;
7212 /* Realloc the data size */
7213 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7214 if (*ppdata == NULL) {
7215 *pdata_return_size = 0;
7216 return NT_STATUS_NO_MEMORY;
7220 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7221 SSVAL(pdata,2,0); /* No fnum. */
7222 SIVAL(pdata,4,info); /* Was directory created. */
7224 switch (info_level_return) {
7225 case SMB_QUERY_FILE_UNIX_BASIC:
7226 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7227 SSVAL(pdata,10,0); /* Padding. */
7228 store_file_unix_basic(conn, pdata + 12, fsp,
7231 case SMB_QUERY_FILE_UNIX_INFO2:
7232 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7233 SSVAL(pdata,10,0); /* Padding. */
7234 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7238 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7239 SSVAL(pdata,10,0); /* Padding. */
7246 /****************************************************************************
7247 Open/Create a file with POSIX semantics.
7248 ****************************************************************************/
7250 static NTSTATUS smb_posix_open(connection_struct *conn,
7251 struct smb_request *req,
7254 struct smb_filename *smb_fname,
7255 int *pdata_return_size)
7257 bool extended_oplock_granted = False;
7258 char *pdata = *ppdata;
7260 uint32 wire_open_mode = 0;
7261 uint32 raw_unixmode = 0;
7262 uint32 mod_unixmode = 0;
7263 uint32 create_disp = 0;
7264 uint32 access_mask = 0;
7265 uint32 create_options = 0;
7266 NTSTATUS status = NT_STATUS_OK;
7267 mode_t unixmode = (mode_t)0;
7268 files_struct *fsp = NULL;
7269 int oplock_request = 0;
7271 uint16 info_level_return = 0;
7273 if (total_data < 18) {
7274 return NT_STATUS_INVALID_PARAMETER;
7277 flags = IVAL(pdata,0);
7278 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7279 if (oplock_request) {
7280 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7283 wire_open_mode = IVAL(pdata,4);
7285 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7286 return smb_posix_mkdir(conn, req,
7293 switch (wire_open_mode & SMB_ACCMODE) {
7295 access_mask = FILE_READ_DATA;
7298 access_mask = FILE_WRITE_DATA;
7301 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7304 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7305 (unsigned int)wire_open_mode ));
7306 return NT_STATUS_INVALID_PARAMETER;
7309 wire_open_mode &= ~SMB_ACCMODE;
7311 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7312 create_disp = FILE_CREATE;
7313 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7314 create_disp = FILE_OVERWRITE_IF;
7315 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7316 create_disp = FILE_OPEN_IF;
7317 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7318 create_disp = FILE_OPEN;
7320 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7321 (unsigned int)wire_open_mode ));
7322 return NT_STATUS_INVALID_PARAMETER;
7325 raw_unixmode = IVAL(pdata,8);
7326 /* Next 4 bytes are not yet defined. */
7328 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7329 (VALID_STAT(smb_fname->st) ?
7330 PERM_EXISTING_FILE : PERM_NEW_FILE),
7333 if (!NT_STATUS_IS_OK(status)) {
7337 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7339 if (wire_open_mode & SMB_O_SYNC) {
7340 create_options |= FILE_WRITE_THROUGH;
7342 if (wire_open_mode & SMB_O_APPEND) {
7343 access_mask |= FILE_APPEND_DATA;
7345 if (wire_open_mode & SMB_O_DIRECT) {
7346 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7349 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7350 smb_fname_str_dbg(smb_fname),
7351 (unsigned int)wire_open_mode,
7352 (unsigned int)unixmode ));
7354 status = SMB_VFS_CREATE_FILE(
7357 0, /* root_dir_fid */
7358 smb_fname, /* fname */
7359 access_mask, /* access_mask */
7360 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7362 create_disp, /* create_disposition*/
7363 FILE_NON_DIRECTORY_FILE, /* create_options */
7364 mod_unixmode, /* file_attributes */
7365 oplock_request, /* oplock_request */
7366 0, /* allocation_size */
7367 0, /* private_flags */
7373 if (!NT_STATUS_IS_OK(status)) {
7377 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7378 extended_oplock_granted = True;
7381 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7382 extended_oplock_granted = True;
7385 info_level_return = SVAL(pdata,16);
7387 /* Allocate the correct return size. */
7389 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7390 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7391 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7392 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7394 *pdata_return_size = 12;
7397 /* Realloc the data size */
7398 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7399 if (*ppdata == NULL) {
7400 close_file(req, fsp, ERROR_CLOSE);
7401 *pdata_return_size = 0;
7402 return NT_STATUS_NO_MEMORY;
7406 if (extended_oplock_granted) {
7407 if (flags & REQUEST_BATCH_OPLOCK) {
7408 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7410 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7412 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7413 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7415 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7418 SSVAL(pdata,2,fsp->fnum);
7419 SIVAL(pdata,4,info); /* Was file created etc. */
7421 switch (info_level_return) {
7422 case SMB_QUERY_FILE_UNIX_BASIC:
7423 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7424 SSVAL(pdata,10,0); /* padding. */
7425 store_file_unix_basic(conn, pdata + 12, fsp,
7428 case SMB_QUERY_FILE_UNIX_INFO2:
7429 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7430 SSVAL(pdata,10,0); /* padding. */
7431 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7435 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7436 SSVAL(pdata,10,0); /* padding. */
7439 return NT_STATUS_OK;
7442 /****************************************************************************
7443 Delete a file with POSIX semantics.
7444 ****************************************************************************/
7446 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7447 struct smb_request *req,
7450 struct smb_filename *smb_fname)
7452 NTSTATUS status = NT_STATUS_OK;
7453 files_struct *fsp = NULL;
7457 int create_options = 0;
7459 struct share_mode_lock *lck = NULL;
7461 if (total_data < 2) {
7462 return NT_STATUS_INVALID_PARAMETER;
7465 flags = SVAL(pdata,0);
7467 if (!VALID_STAT(smb_fname->st)) {
7468 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7471 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7472 !VALID_STAT_OF_DIR(smb_fname->st)) {
7473 return NT_STATUS_NOT_A_DIRECTORY;
7476 DEBUG(10,("smb_posix_unlink: %s %s\n",
7477 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7478 smb_fname_str_dbg(smb_fname)));
7480 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7481 create_options |= FILE_DIRECTORY_FILE;
7484 status = SMB_VFS_CREATE_FILE(
7487 0, /* root_dir_fid */
7488 smb_fname, /* fname */
7489 DELETE_ACCESS, /* access_mask */
7490 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7492 FILE_OPEN, /* create_disposition*/
7493 create_options, /* create_options */
7494 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7495 0, /* oplock_request */
7496 0, /* allocation_size */
7497 0, /* private_flags */
7503 if (!NT_STATUS_IS_OK(status)) {
7508 * Don't lie to client. If we can't really delete due to
7509 * non-POSIX opens return SHARING_VIOLATION.
7512 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7515 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7516 "lock for file %s\n", fsp_str_dbg(fsp)));
7517 close_file(req, fsp, NORMAL_CLOSE);
7518 return NT_STATUS_INVALID_PARAMETER;
7522 * See if others still have the file open. If this is the case, then
7523 * don't delete. If all opens are POSIX delete we can set the delete
7524 * on close disposition.
7526 for (i=0; i<lck->num_share_modes; i++) {
7527 struct share_mode_entry *e = &lck->share_modes[i];
7528 if (is_valid_share_mode_entry(e)) {
7529 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7532 /* Fail with sharing violation. */
7533 close_file(req, fsp, NORMAL_CLOSE);
7535 return NT_STATUS_SHARING_VIOLATION;
7540 * Set the delete on close.
7542 status = smb_set_file_disposition_info(conn,
7548 if (!NT_STATUS_IS_OK(status)) {
7549 close_file(req, fsp, NORMAL_CLOSE);
7554 return close_file(req, fsp, NORMAL_CLOSE);
7557 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7558 struct smb_request *req,
7559 TALLOC_CTX *mem_ctx,
7560 uint16_t info_level,
7562 struct smb_filename *smb_fname,
7563 char **ppdata, int total_data,
7566 char *pdata = *ppdata;
7567 NTSTATUS status = NT_STATUS_OK;
7568 int data_return_size = 0;
7572 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7573 return NT_STATUS_INVALID_LEVEL;
7576 if (!CAN_WRITE(conn)) {
7577 /* Allow POSIX opens. The open path will deny
7578 * any non-readonly opens. */
7579 if (info_level != SMB_POSIX_PATH_OPEN) {
7580 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7584 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7585 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7586 fsp ? fsp->fnum : -1, info_level, total_data));
7588 switch (info_level) {
7590 case SMB_INFO_STANDARD:
7592 status = smb_set_info_standard(conn,
7600 case SMB_INFO_SET_EA:
7602 status = smb_info_set_ea(conn,
7610 case SMB_SET_FILE_BASIC_INFO:
7611 case SMB_FILE_BASIC_INFORMATION:
7613 status = smb_set_file_basic_info(conn,
7621 case SMB_FILE_ALLOCATION_INFORMATION:
7622 case SMB_SET_FILE_ALLOCATION_INFO:
7624 status = smb_set_file_allocation_info(conn, req,
7632 case SMB_FILE_END_OF_FILE_INFORMATION:
7633 case SMB_SET_FILE_END_OF_FILE_INFO:
7636 * XP/Win7 both fail after the createfile with
7637 * SMB_SET_FILE_END_OF_FILE_INFO but not
7638 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7639 * The level is known here, so pass it down
7643 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7645 status = smb_set_file_end_of_file_info(conn, req,
7654 case SMB_FILE_DISPOSITION_INFORMATION:
7655 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7658 /* JRA - We used to just ignore this on a path ?
7659 * Shouldn't this be invalid level on a pathname
7662 if (tran_call != TRANSACT2_SETFILEINFO) {
7663 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7666 status = smb_set_file_disposition_info(conn,
7674 case SMB_FILE_POSITION_INFORMATION:
7676 status = smb_file_position_information(conn,
7683 case SMB_FILE_FULL_EA_INFORMATION:
7685 status = smb_set_file_full_ea_info(conn,
7692 /* From tridge Samba4 :
7693 * MODE_INFORMATION in setfileinfo (I have no
7694 * idea what "mode information" on a file is - it takes a value of 0,
7695 * 2, 4 or 6. What could it be?).
7698 case SMB_FILE_MODE_INFORMATION:
7700 status = smb_file_mode_information(conn,
7707 * CIFS UNIX extensions.
7710 case SMB_SET_FILE_UNIX_BASIC:
7712 status = smb_set_file_unix_basic(conn, req,
7720 case SMB_SET_FILE_UNIX_INFO2:
7722 status = smb_set_file_unix_info2(conn, req,
7730 case SMB_SET_FILE_UNIX_LINK:
7733 /* We must have a pathname for this. */
7734 return NT_STATUS_INVALID_LEVEL;
7736 status = smb_set_file_unix_link(conn, req, pdata,
7737 total_data, smb_fname);
7741 case SMB_SET_FILE_UNIX_HLINK:
7744 /* We must have a pathname for this. */
7745 return NT_STATUS_INVALID_LEVEL;
7747 status = smb_set_file_unix_hlink(conn, req,
7753 case SMB_FILE_RENAME_INFORMATION:
7755 status = smb_file_rename_information(conn, req,
7761 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7763 /* SMB2 rename information. */
7764 status = smb2_file_rename_information(conn, req,
7770 case SMB_FILE_LINK_INFORMATION:
7772 status = smb_file_link_information(conn, req,
7778 #if defined(HAVE_POSIX_ACLS)
7779 case SMB_SET_POSIX_ACL:
7781 status = smb_set_posix_acl(conn,
7790 case SMB_SET_POSIX_LOCK:
7793 return NT_STATUS_INVALID_LEVEL;
7795 status = smb_set_posix_lock(conn, req,
7796 pdata, total_data, fsp);
7800 case SMB_POSIX_PATH_OPEN:
7803 /* We must have a pathname for this. */
7804 return NT_STATUS_INVALID_LEVEL;
7807 status = smb_posix_open(conn, req,
7815 case SMB_POSIX_PATH_UNLINK:
7818 /* We must have a pathname for this. */
7819 return NT_STATUS_INVALID_LEVEL;
7822 status = smb_posix_unlink(conn, req,
7830 return NT_STATUS_INVALID_LEVEL;
7833 if (!NT_STATUS_IS_OK(status)) {
7837 *ret_data_size = data_return_size;
7838 return NT_STATUS_OK;
7841 /****************************************************************************
7842 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7843 ****************************************************************************/
7845 static void call_trans2setfilepathinfo(connection_struct *conn,
7846 struct smb_request *req,
7847 unsigned int tran_call,
7848 char **pparams, int total_params,
7849 char **ppdata, int total_data,
7850 unsigned int max_data_bytes)
7852 char *params = *pparams;
7853 char *pdata = *ppdata;
7855 struct smb_filename *smb_fname = NULL;
7856 files_struct *fsp = NULL;
7857 NTSTATUS status = NT_STATUS_OK;
7858 int data_return_size = 0;
7861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7865 if (tran_call == TRANSACT2_SETFILEINFO) {
7866 if (total_params < 4) {
7867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7871 fsp = file_fsp(req, SVAL(params,0));
7872 /* Basic check for non-null fsp. */
7873 if (!check_fsp_open(conn, req, fsp)) {
7876 info_level = SVAL(params,2);
7878 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7880 if (!NT_STATUS_IS_OK(status)) {
7881 reply_nterror(req, status);
7885 if(fsp->fh->fd == -1) {
7887 * This is actually a SETFILEINFO on a directory
7888 * handle (returned from an NT SMB). NT5.0 seems
7889 * to do this call. JRA.
7891 if (INFO_LEVEL_IS_UNIX(info_level)) {
7892 /* Always do lstat for UNIX calls. */
7893 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7894 DEBUG(3,("call_trans2setfilepathinfo: "
7895 "SMB_VFS_LSTAT of %s failed "
7897 smb_fname_str_dbg(smb_fname),
7899 reply_nterror(req, map_nt_error_from_unix(errno));
7903 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7904 DEBUG(3,("call_trans2setfilepathinfo: "
7905 "fileinfo of %s failed (%s)\n",
7906 smb_fname_str_dbg(smb_fname),
7908 reply_nterror(req, map_nt_error_from_unix(errno));
7912 } else if (fsp->print_file) {
7914 * Doing a DELETE_ON_CLOSE should cancel a print job.
7916 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7917 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7919 DEBUG(3,("call_trans2setfilepathinfo: "
7920 "Cancelling print job (%s)\n",
7924 send_trans2_replies(conn, req, params, 2,
7930 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7935 * Original code - this is an open file.
7937 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7938 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7939 "of fnum %d failed (%s)\n", fsp->fnum,
7941 reply_nterror(req, map_nt_error_from_unix(errno));
7949 if (total_params < 7) {
7950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7954 info_level = SVAL(params,0);
7955 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7956 total_params - 6, STR_TERMINATE,
7958 if (!NT_STATUS_IS_OK(status)) {
7959 reply_nterror(req, status);
7963 status = filename_convert(req, conn,
7964 req->flags2 & FLAGS2_DFS_PATHNAMES,
7969 if (!NT_STATUS_IS_OK(status)) {
7970 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7971 reply_botherror(req,
7972 NT_STATUS_PATH_NOT_COVERED,
7973 ERRSRV, ERRbadpath);
7976 reply_nterror(req, status);
7980 if (INFO_LEVEL_IS_UNIX(info_level)) {
7982 * For CIFS UNIX extensions the target name may not exist.
7985 /* Always do lstat for UNIX calls. */
7986 SMB_VFS_LSTAT(conn, smb_fname);
7988 } else if (!VALID_STAT(smb_fname->st) &&
7989 SMB_VFS_STAT(conn, smb_fname)) {
7990 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7992 smb_fname_str_dbg(smb_fname),
7994 reply_nterror(req, map_nt_error_from_unix(errno));
7999 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8000 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8001 fsp ? fsp->fnum : -1, info_level,total_data));
8003 /* Realloc the parameter size */
8004 *pparams = (char *)SMB_REALLOC(*pparams,2);
8005 if (*pparams == NULL) {
8006 reply_nterror(req, NT_STATUS_NO_MEMORY);
8013 status = smbd_do_setfilepathinfo(conn, req, req,
8019 if (!NT_STATUS_IS_OK(status)) {
8020 if (open_was_deferred(req->mid)) {
8021 /* We have re-scheduled this call. */
8024 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8025 /* We have re-scheduled this call. */
8028 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8029 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8030 ERRSRV, ERRbadpath);
8033 if (info_level == SMB_POSIX_PATH_OPEN) {
8034 reply_openerror(req, status);
8038 reply_nterror(req, status);
8042 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8048 /****************************************************************************
8049 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8050 ****************************************************************************/
8052 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8053 char **pparams, int total_params,
8054 char **ppdata, int total_data,
8055 unsigned int max_data_bytes)
8057 struct smb_filename *smb_dname = NULL;
8058 char *params = *pparams;
8059 char *pdata = *ppdata;
8060 char *directory = NULL;
8061 NTSTATUS status = NT_STATUS_OK;
8062 struct ea_list *ea_list = NULL;
8063 TALLOC_CTX *ctx = talloc_tos();
8065 if (!CAN_WRITE(conn)) {
8066 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8070 if (total_params < 5) {
8071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8075 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8076 total_params - 4, STR_TERMINATE,
8078 if (!NT_STATUS_IS_OK(status)) {
8079 reply_nterror(req, status);
8083 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8085 status = filename_convert(ctx,
8087 req->flags2 & FLAGS2_DFS_PATHNAMES,
8093 if (!NT_STATUS_IS_OK(status)) {
8094 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8095 reply_botherror(req,
8096 NT_STATUS_PATH_NOT_COVERED,
8097 ERRSRV, ERRbadpath);
8100 reply_nterror(req, status);
8105 * OS/2 workplace shell seems to send SET_EA requests of "null"
8106 * length (4 bytes containing IVAL 4).
8107 * They seem to have no effect. Bug #3212. JRA.
8110 if (total_data && (total_data != 4)) {
8111 /* Any data in this call is an EA list. */
8112 if (total_data < 10) {
8113 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8117 if (IVAL(pdata,0) > total_data) {
8118 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8119 IVAL(pdata,0), (unsigned int)total_data));
8120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8124 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8131 if (!lp_ea_support(SNUM(conn))) {
8132 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8136 /* If total_data == 4 Windows doesn't care what values
8137 * are placed in that field, it just ignores them.
8138 * The System i QNTC IBM SMB client puts bad values here,
8139 * so ignore them. */
8141 status = create_directory(conn, req, smb_dname);
8143 if (!NT_STATUS_IS_OK(status)) {
8144 reply_nterror(req, status);
8148 /* Try and set any given EA. */
8150 status = set_ea(conn, NULL, smb_dname, ea_list);
8151 if (!NT_STATUS_IS_OK(status)) {
8152 reply_nterror(req, status);
8157 /* Realloc the parameter and data sizes */
8158 *pparams = (char *)SMB_REALLOC(*pparams,2);
8159 if(*pparams == NULL) {
8160 reply_nterror(req, NT_STATUS_NO_MEMORY);
8167 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8170 TALLOC_FREE(smb_dname);
8174 /****************************************************************************
8175 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8176 We don't actually do this - we just send a null response.
8177 ****************************************************************************/
8179 static void call_trans2findnotifyfirst(connection_struct *conn,
8180 struct smb_request *req,
8181 char **pparams, int total_params,
8182 char **ppdata, int total_data,
8183 unsigned int max_data_bytes)
8185 char *params = *pparams;
8188 if (total_params < 6) {
8189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8193 info_level = SVAL(params,4);
8194 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8196 switch (info_level) {
8201 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8205 /* Realloc the parameter and data sizes */
8206 *pparams = (char *)SMB_REALLOC(*pparams,6);
8207 if (*pparams == NULL) {
8208 reply_nterror(req, NT_STATUS_NO_MEMORY);
8213 SSVAL(params,0,fnf_handle);
8214 SSVAL(params,2,0); /* No changes */
8215 SSVAL(params,4,0); /* No EA errors */
8222 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8227 /****************************************************************************
8228 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8229 changes). Currently this does nothing.
8230 ****************************************************************************/
8232 static void call_trans2findnotifynext(connection_struct *conn,
8233 struct smb_request *req,
8234 char **pparams, int total_params,
8235 char **ppdata, int total_data,
8236 unsigned int max_data_bytes)
8238 char *params = *pparams;
8240 DEBUG(3,("call_trans2findnotifynext\n"));
8242 /* Realloc the parameter and data sizes */
8243 *pparams = (char *)SMB_REALLOC(*pparams,4);
8244 if (*pparams == NULL) {
8245 reply_nterror(req, NT_STATUS_NO_MEMORY);
8250 SSVAL(params,0,0); /* No changes */
8251 SSVAL(params,2,0); /* No EA errors */
8253 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8258 /****************************************************************************
8259 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8260 ****************************************************************************/
8262 static void call_trans2getdfsreferral(connection_struct *conn,
8263 struct smb_request *req,
8264 char **pparams, int total_params,
8265 char **ppdata, int total_data,
8266 unsigned int max_data_bytes)
8268 char *params = *pparams;
8269 char *pathname = NULL;
8271 int max_referral_level;
8272 NTSTATUS status = NT_STATUS_OK;
8273 TALLOC_CTX *ctx = talloc_tos();
8275 DEBUG(10,("call_trans2getdfsreferral\n"));
8277 if (total_params < 3) {
8278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8282 max_referral_level = SVAL(params,0);
8284 if(!lp_host_msdfs()) {
8285 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8289 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8290 total_params - 2, STR_TERMINATE);
8292 reply_nterror(req, NT_STATUS_NOT_FOUND);
8295 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8296 ppdata,&status)) < 0) {
8297 reply_nterror(req, status);
8301 SSVAL(req->inbuf, smb_flg2,
8302 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8303 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8308 #define LMCAT_SPL 0x53
8309 #define LMFUNC_GETJOBID 0x60
8311 /****************************************************************************
8312 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8313 ****************************************************************************/
8315 static void call_trans2ioctl(connection_struct *conn,
8316 struct smb_request *req,
8317 char **pparams, int total_params,
8318 char **ppdata, int total_data,
8319 unsigned int max_data_bytes)
8321 char *pdata = *ppdata;
8322 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8324 /* check for an invalid fid before proceeding */
8327 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8331 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8332 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8333 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8334 if (*ppdata == NULL) {
8335 reply_nterror(req, NT_STATUS_NO_MEMORY);
8340 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8341 CAN ACCEPT THIS IN UNICODE. JRA. */
8344 if (fsp->print_file) {
8345 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8349 srvstr_push(pdata, req->flags2, pdata + 2,
8350 global_myname(), 15,
8351 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8352 srvstr_push(pdata, req->flags2, pdata+18,
8353 lp_servicename(SNUM(conn)), 13,
8354 STR_ASCII|STR_TERMINATE); /* Service name */
8355 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8360 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8361 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8364 /****************************************************************************
8365 Reply to a SMBfindclose (stop trans2 directory search).
8366 ****************************************************************************/
8368 void reply_findclose(struct smb_request *req)
8371 struct smbd_server_connection *sconn = req->sconn;
8373 START_PROFILE(SMBfindclose);
8376 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8377 END_PROFILE(SMBfindclose);
8381 dptr_num = SVALS(req->vwv+0, 0);
8383 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8385 dptr_close(sconn, &dptr_num);
8387 reply_outbuf(req, 0, 0);
8389 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8391 END_PROFILE(SMBfindclose);
8395 /****************************************************************************
8396 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8397 ****************************************************************************/
8399 void reply_findnclose(struct smb_request *req)
8403 START_PROFILE(SMBfindnclose);
8406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8407 END_PROFILE(SMBfindnclose);
8411 dptr_num = SVAL(req->vwv+0, 0);
8413 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8415 /* We never give out valid handles for a
8416 findnotifyfirst - so any dptr_num is ok here.
8419 reply_outbuf(req, 0, 0);
8421 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8423 END_PROFILE(SMBfindnclose);
8427 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8428 struct trans_state *state)
8430 if (get_Protocol() >= PROTOCOL_NT1) {
8431 req->flags2 |= 0x40; /* IS_LONG_NAME */
8432 SSVAL(req->inbuf,smb_flg2,req->flags2);
8435 if (conn->encrypt_level == Required && !req->encrypted) {
8436 if (state->call != TRANSACT2_QFSINFO &&
8437 state->call != TRANSACT2_SETFSINFO) {
8438 DEBUG(0,("handle_trans2: encryption required "
8440 (unsigned int)state->call));
8441 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8446 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8448 /* Now we must call the relevant TRANS2 function */
8449 switch(state->call) {
8450 case TRANSACT2_OPEN:
8452 START_PROFILE(Trans2_open);
8453 call_trans2open(conn, req,
8454 &state->param, state->total_param,
8455 &state->data, state->total_data,
8456 state->max_data_return);
8457 END_PROFILE(Trans2_open);
8461 case TRANSACT2_FINDFIRST:
8463 START_PROFILE(Trans2_findfirst);
8464 call_trans2findfirst(conn, req,
8465 &state->param, state->total_param,
8466 &state->data, state->total_data,
8467 state->max_data_return);
8468 END_PROFILE(Trans2_findfirst);
8472 case TRANSACT2_FINDNEXT:
8474 START_PROFILE(Trans2_findnext);
8475 call_trans2findnext(conn, req,
8476 &state->param, state->total_param,
8477 &state->data, state->total_data,
8478 state->max_data_return);
8479 END_PROFILE(Trans2_findnext);
8483 case TRANSACT2_QFSINFO:
8485 START_PROFILE(Trans2_qfsinfo);
8486 call_trans2qfsinfo(conn, req,
8487 &state->param, state->total_param,
8488 &state->data, state->total_data,
8489 state->max_data_return);
8490 END_PROFILE(Trans2_qfsinfo);
8494 case TRANSACT2_SETFSINFO:
8496 START_PROFILE(Trans2_setfsinfo);
8497 call_trans2setfsinfo(conn, req,
8498 &state->param, state->total_param,
8499 &state->data, state->total_data,
8500 state->max_data_return);
8501 END_PROFILE(Trans2_setfsinfo);
8505 case TRANSACT2_QPATHINFO:
8506 case TRANSACT2_QFILEINFO:
8508 START_PROFILE(Trans2_qpathinfo);
8509 call_trans2qfilepathinfo(conn, req, state->call,
8510 &state->param, state->total_param,
8511 &state->data, state->total_data,
8512 state->max_data_return);
8513 END_PROFILE(Trans2_qpathinfo);
8517 case TRANSACT2_SETPATHINFO:
8518 case TRANSACT2_SETFILEINFO:
8520 START_PROFILE(Trans2_setpathinfo);
8521 call_trans2setfilepathinfo(conn, req, state->call,
8522 &state->param, state->total_param,
8523 &state->data, state->total_data,
8524 state->max_data_return);
8525 END_PROFILE(Trans2_setpathinfo);
8529 case TRANSACT2_FINDNOTIFYFIRST:
8531 START_PROFILE(Trans2_findnotifyfirst);
8532 call_trans2findnotifyfirst(conn, req,
8533 &state->param, state->total_param,
8534 &state->data, state->total_data,
8535 state->max_data_return);
8536 END_PROFILE(Trans2_findnotifyfirst);
8540 case TRANSACT2_FINDNOTIFYNEXT:
8542 START_PROFILE(Trans2_findnotifynext);
8543 call_trans2findnotifynext(conn, req,
8544 &state->param, state->total_param,
8545 &state->data, state->total_data,
8546 state->max_data_return);
8547 END_PROFILE(Trans2_findnotifynext);
8551 case TRANSACT2_MKDIR:
8553 START_PROFILE(Trans2_mkdir);
8554 call_trans2mkdir(conn, req,
8555 &state->param, state->total_param,
8556 &state->data, state->total_data,
8557 state->max_data_return);
8558 END_PROFILE(Trans2_mkdir);
8562 case TRANSACT2_GET_DFS_REFERRAL:
8564 START_PROFILE(Trans2_get_dfs_referral);
8565 call_trans2getdfsreferral(conn, req,
8566 &state->param, state->total_param,
8567 &state->data, state->total_data,
8568 state->max_data_return);
8569 END_PROFILE(Trans2_get_dfs_referral);
8573 case TRANSACT2_IOCTL:
8575 START_PROFILE(Trans2_ioctl);
8576 call_trans2ioctl(conn, req,
8577 &state->param, state->total_param,
8578 &state->data, state->total_data,
8579 state->max_data_return);
8580 END_PROFILE(Trans2_ioctl);
8585 /* Error in request */
8586 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8587 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8591 /****************************************************************************
8592 Reply to a SMBtrans2.
8593 ****************************************************************************/
8595 void reply_trans2(struct smb_request *req)
8597 connection_struct *conn = req->conn;
8602 unsigned int tran_call;
8603 struct trans_state *state;
8606 START_PROFILE(SMBtrans2);
8608 if (req->wct < 14) {
8609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8610 END_PROFILE(SMBtrans2);
8614 dsoff = SVAL(req->vwv+12, 0);
8615 dscnt = SVAL(req->vwv+11, 0);
8616 psoff = SVAL(req->vwv+10, 0);
8617 pscnt = SVAL(req->vwv+9, 0);
8618 tran_call = SVAL(req->vwv+14, 0);
8620 result = allow_new_trans(conn->pending_trans, req->mid);
8621 if (!NT_STATUS_IS_OK(result)) {
8622 DEBUG(2, ("Got invalid trans2 request: %s\n",
8623 nt_errstr(result)));
8624 reply_nterror(req, result);
8625 END_PROFILE(SMBtrans2);
8630 switch (tran_call) {
8631 /* List the allowed trans2 calls on IPC$ */
8632 case TRANSACT2_OPEN:
8633 case TRANSACT2_GET_DFS_REFERRAL:
8634 case TRANSACT2_QFILEINFO:
8635 case TRANSACT2_QFSINFO:
8636 case TRANSACT2_SETFSINFO:
8639 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8640 END_PROFILE(SMBtrans2);
8645 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8646 DEBUG(0, ("talloc failed\n"));
8647 reply_nterror(req, NT_STATUS_NO_MEMORY);
8648 END_PROFILE(SMBtrans2);
8652 state->cmd = SMBtrans2;
8654 state->mid = req->mid;
8655 state->vuid = req->vuid;
8656 state->setup_count = SVAL(req->vwv+13, 0);
8657 state->setup = NULL;
8658 state->total_param = SVAL(req->vwv+0, 0);
8659 state->param = NULL;
8660 state->total_data = SVAL(req->vwv+1, 0);
8662 state->max_param_return = SVAL(req->vwv+2, 0);
8663 state->max_data_return = SVAL(req->vwv+3, 0);
8664 state->max_setup_return = SVAL(req->vwv+4, 0);
8665 state->close_on_completion = BITSETW(req->vwv+5, 0);
8666 state->one_way = BITSETW(req->vwv+5, 1);
8668 state->call = tran_call;
8670 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8671 is so as a sanity check */
8672 if (state->setup_count != 1) {
8674 * Need to have rc=0 for ioctl to get job id for OS/2.
8675 * Network printing will fail if function is not successful.
8676 * Similar function in reply.c will be used if protocol
8677 * is LANMAN1.0 instead of LM1.2X002.
8678 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8679 * outbuf doesn't have to be set(only job id is used).
8681 if ( (state->setup_count == 4)
8682 && (tran_call == TRANSACT2_IOCTL)
8683 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8684 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8685 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8687 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8688 DEBUG(2,("Transaction is %d\n",tran_call));
8690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8691 END_PROFILE(SMBtrans2);
8696 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8699 if (state->total_data) {
8701 if (trans_oob(state->total_data, 0, dscnt)
8702 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8706 /* Can't use talloc here, the core routines do realloc on the
8707 * params and data. */
8708 state->data = (char *)SMB_MALLOC(state->total_data);
8709 if (state->data == NULL) {
8710 DEBUG(0,("reply_trans2: data malloc fail for %u "
8711 "bytes !\n", (unsigned int)state->total_data));
8713 reply_nterror(req, NT_STATUS_NO_MEMORY);
8714 END_PROFILE(SMBtrans2);
8718 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8721 if (state->total_param) {
8723 if (trans_oob(state->total_param, 0, pscnt)
8724 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8728 /* Can't use talloc here, the core routines do realloc on the
8729 * params and data. */
8730 state->param = (char *)SMB_MALLOC(state->total_param);
8731 if (state->param == NULL) {
8732 DEBUG(0,("reply_trans: param malloc fail for %u "
8733 "bytes !\n", (unsigned int)state->total_param));
8734 SAFE_FREE(state->data);
8736 reply_nterror(req, NT_STATUS_NO_MEMORY);
8737 END_PROFILE(SMBtrans2);
8741 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8744 state->received_data = dscnt;
8745 state->received_param = pscnt;
8747 if ((state->received_param == state->total_param) &&
8748 (state->received_data == state->total_data)) {
8750 handle_trans2(conn, req, state);
8752 SAFE_FREE(state->data);
8753 SAFE_FREE(state->param);
8755 END_PROFILE(SMBtrans2);
8759 DLIST_ADD(conn->pending_trans, state);
8761 /* We need to send an interim response then receive the rest
8762 of the parameter/data bytes */
8763 reply_outbuf(req, 0, 0);
8764 show_msg((char *)req->outbuf);
8765 END_PROFILE(SMBtrans2);
8770 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8771 SAFE_FREE(state->data);
8772 SAFE_FREE(state->param);
8774 END_PROFILE(SMBtrans2);
8775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8779 /****************************************************************************
8780 Reply to a SMBtranss2
8781 ****************************************************************************/
8783 void reply_transs2(struct smb_request *req)
8785 connection_struct *conn = req->conn;
8786 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8787 struct trans_state *state;
8789 START_PROFILE(SMBtranss2);
8791 show_msg((char *)req->inbuf);
8794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8795 END_PROFILE(SMBtranss2);
8799 for (state = conn->pending_trans; state != NULL;
8800 state = state->next) {
8801 if (state->mid == req->mid) {
8806 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8808 END_PROFILE(SMBtranss2);
8812 /* Revise state->total_param and state->total_data in case they have
8813 changed downwards */
8815 if (SVAL(req->vwv+0, 0) < state->total_param)
8816 state->total_param = SVAL(req->vwv+0, 0);
8817 if (SVAL(req->vwv+1, 0) < state->total_data)
8818 state->total_data = SVAL(req->vwv+1, 0);
8820 pcnt = SVAL(req->vwv+2, 0);
8821 poff = SVAL(req->vwv+3, 0);
8822 pdisp = SVAL(req->vwv+4, 0);
8824 dcnt = SVAL(req->vwv+5, 0);
8825 doff = SVAL(req->vwv+6, 0);
8826 ddisp = SVAL(req->vwv+7, 0);
8828 state->received_param += pcnt;
8829 state->received_data += dcnt;
8831 if ((state->received_data > state->total_data) ||
8832 (state->received_param > state->total_param))
8836 if (trans_oob(state->total_param, pdisp, pcnt)
8837 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8840 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8844 if (trans_oob(state->total_data, ddisp, dcnt)
8845 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8848 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8851 if ((state->received_param < state->total_param) ||
8852 (state->received_data < state->total_data)) {
8853 END_PROFILE(SMBtranss2);
8857 handle_trans2(conn, req, state);
8859 DLIST_REMOVE(conn->pending_trans, state);
8860 SAFE_FREE(state->data);
8861 SAFE_FREE(state->param);
8864 END_PROFILE(SMBtranss2);
8869 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8870 DLIST_REMOVE(conn->pending_trans, state);
8871 SAFE_FREE(state->data);
8872 SAFE_FREE(state->param);
8874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8875 END_PROFILE(SMBtranss2);