2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "libcli/security/security.h"
38 #define DIR_ENTRY_SAFETY_MARGIN 4096
40 static char *store_file_unix_basic(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 static char *store_file_unix_basic_info2(connection_struct *conn,
48 const SMB_STRUCT_STAT *psbuf);
50 /********************************************************************
51 Roundup a value to the nearest allocation roundup size boundary.
52 Only do this for Windows clients.
53 ********************************************************************/
55 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
57 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
59 /* Only roundup for Windows clients. */
60 enum remote_arch_types ra_type = get_remote_arch();
61 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
62 val = SMB_ROUNDUP(val,rval);
67 /********************************************************************
68 Create a 64 bit FileIndex. If the file is on the same device as
69 the root of the share, just return the 64-bit inode. If it isn't,
70 mangle as we used to do.
71 ********************************************************************/
73 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
76 if (conn->base_share_dev == psbuf->st_ex_dev) {
77 return (uint64_t)psbuf->st_ex_ino;
79 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
80 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
84 /****************************************************************************
85 Utility functions for dealing with extended attributes.
86 ****************************************************************************/
88 /****************************************************************************
89 Refuse to allow clients to overwrite our private xattrs.
90 ****************************************************************************/
92 static bool samba_private_attr_name(const char *unix_ea_name)
94 static const char * const prohibited_ea_names[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME,
96 SAMBA_XATTR_DOS_ATTRIB,
104 for (i = 0; prohibited_ea_names[i]; i++) {
105 if (strequal( prohibited_ea_names[i], unix_ea_name))
108 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
109 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
120 files_struct *fsp, const char *fname,
121 const char *ea_name, struct ea_struct *pea)
123 /* Get the value of this xattr. Max size is 64k. */
124 size_t attr_size = 256;
130 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
132 return NT_STATUS_NO_MEMORY;
135 if (fsp && fsp->fh->fd != -1) {
136 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
138 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
141 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
147 return map_nt_error_from_unix(errno);
150 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
151 dump_data(10, (uint8 *)val, sizeret);
154 if (strnequal(ea_name, "user.", 5)) {
155 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
157 pea->name = talloc_strdup(mem_ctx, ea_name);
159 if (pea->name == NULL) {
161 return NT_STATUS_NO_MEMORY;
163 pea->value.data = (unsigned char *)val;
164 pea->value.length = (size_t)sizeret;
168 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
169 files_struct *fsp, const char *fname,
170 char ***pnames, size_t *pnum_names)
172 /* Get a list of all xattrs. Max namesize is 64k. */
173 size_t ea_namelist_size = 1024;
174 char *ea_namelist = NULL;
179 ssize_t sizeret = -1;
181 if (!lp_ea_support(SNUM(conn))) {
190 * TALLOC the result early to get the talloc hierarchy right.
193 names = TALLOC_ARRAY(mem_ctx, char *, 1);
195 DEBUG(0, ("talloc failed\n"));
196 return NT_STATUS_NO_MEMORY;
199 while (ea_namelist_size <= 65536) {
201 ea_namelist = TALLOC_REALLOC_ARRAY(
202 names, ea_namelist, char, ea_namelist_size);
203 if (ea_namelist == NULL) {
204 DEBUG(0, ("talloc failed\n"));
206 return NT_STATUS_NO_MEMORY;
209 if (fsp && fsp->fh->fd != -1) {
210 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
213 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
217 if ((sizeret == -1) && (errno == ERANGE)) {
218 ea_namelist_size *= 2;
227 return map_nt_error_from_unix(errno);
230 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
231 (unsigned int)sizeret));
243 * Ensure the result is 0-terminated
246 if (ea_namelist[sizeret-1] != '\0') {
248 return NT_STATUS_INTERNAL_ERROR;
256 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
260 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
262 DEBUG(0, ("talloc failed\n"));
264 return NT_STATUS_NO_MEMORY;
270 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
271 names[num_names++] = p;
279 *pnum_names = num_names;
283 /****************************************************************************
284 Return a linked list of the total EA's. Plus the total size
285 ****************************************************************************/
287 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
288 const char *fname, size_t *pea_total_len)
290 /* Get a list of all xattrs. Max namesize is 64k. */
293 struct ea_list *ea_list_head = NULL;
298 if (!lp_ea_support(SNUM(conn))) {
302 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
305 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
309 for (i=0; i<num_names; i++) {
310 struct ea_list *listp;
313 if (strnequal(names[i], "system.", 7)
314 || samba_private_attr_name(names[i]))
317 listp = TALLOC_P(mem_ctx, struct ea_list);
322 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
328 push_ascii_fstring(dos_ea_name, listp->ea.name);
331 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
333 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
334 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
335 (unsigned int)listp->ea.value.length));
337 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
341 /* Add on 4 for total length. */
342 if (*pea_total_len) {
346 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
347 (unsigned int)*pea_total_len));
352 /****************************************************************************
353 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
355 ****************************************************************************/
357 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
358 connection_struct *conn, struct ea_list *ea_list)
360 unsigned int ret_data_size = 4;
363 SMB_ASSERT(total_data_size >= 4);
365 if (!lp_ea_support(SNUM(conn))) {
370 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
373 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
374 dos_namelen = strlen(dos_ea_name);
375 if (dos_namelen > 255 || dos_namelen == 0) {
378 if (ea_list->ea.value.length > 65535) {
381 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
385 /* We know we have room. */
386 SCVAL(p,0,ea_list->ea.flags);
387 SCVAL(p,1,dos_namelen);
388 SSVAL(p,2,ea_list->ea.value.length);
389 fstrcpy(p+4, dos_ea_name);
390 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
392 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
393 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
396 ret_data_size = PTR_DIFF(p, pdata);
397 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
398 SIVAL(pdata,0,ret_data_size);
399 return ret_data_size;
402 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
404 unsigned int total_data_size,
405 unsigned int *ret_data_size,
406 connection_struct *conn,
407 struct ea_list *ea_list)
409 uint8_t *p = (uint8_t *)pdata;
410 uint8_t *last_start = NULL;
414 if (!lp_ea_support(SNUM(conn))) {
415 return NT_STATUS_NO_EAS_ON_FILE;
418 for (; ea_list; ea_list = ea_list->next) {
424 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
428 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
429 dos_namelen = strlen(dos_ea_name);
430 if (dos_namelen > 255 || dos_namelen == 0) {
431 return NT_STATUS_INTERNAL_ERROR;
433 if (ea_list->ea.value.length > 65535) {
434 return NT_STATUS_INTERNAL_ERROR;
437 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
440 size_t pad = 4 - (this_size % 4);
444 if (this_size > total_data_size) {
445 return NT_STATUS_INFO_LENGTH_MISMATCH;
448 /* We know we have room. */
449 SIVAL(p, 0x00, 0); /* next offset */
450 SCVAL(p, 0x04, ea_list->ea.flags);
451 SCVAL(p, 0x05, dos_namelen);
452 SSVAL(p, 0x06, ea_list->ea.value.length);
453 fstrcpy((char *)(p+0x08), dos_ea_name);
454 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
456 total_data_size -= this_size;
460 *ret_data_size = PTR_DIFF(p, pdata);
461 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
465 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
467 size_t total_ea_len = 0;
468 TALLOC_CTX *mem_ctx = NULL;
470 if (!lp_ea_support(SNUM(conn))) {
473 mem_ctx = talloc_tos();
474 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
478 /****************************************************************************
479 Ensure the EA name is case insensitive by matching any existing EA name.
480 ****************************************************************************/
482 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
485 TALLOC_CTX *mem_ctx = talloc_tos();
486 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
488 for (; ea_list; ea_list = ea_list->next) {
489 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
490 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
491 &unix_ea_name[5], ea_list->ea.name));
492 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
498 /****************************************************************************
499 Set or delete an extended attribute.
500 ****************************************************************************/
502 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
503 const struct smb_filename *smb_fname, struct ea_list *ea_list)
507 if (!lp_ea_support(SNUM(conn))) {
508 return NT_STATUS_EAS_NOT_SUPPORTED;
511 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
512 return NT_STATUS_ACCESS_DENIED;
515 /* For now setting EAs on streams isn't supported. */
516 fname = smb_fname->base_name;
518 for (;ea_list; ea_list = ea_list->next) {
520 fstring unix_ea_name;
522 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
523 fstrcat(unix_ea_name, ea_list->ea.name);
525 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
527 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
529 if (samba_private_attr_name(unix_ea_name)) {
530 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
531 return NT_STATUS_ACCESS_DENIED;
534 if (ea_list->ea.value.length == 0) {
535 /* Remove the attribute. */
536 if (fsp && (fsp->fh->fd != -1)) {
537 DEBUG(10,("set_ea: deleting ea name %s on "
538 "file %s by file descriptor.\n",
539 unix_ea_name, fsp_str_dbg(fsp)));
540 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
542 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
543 unix_ea_name, fname));
544 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
547 /* Removing a non existent attribute always succeeds. */
548 if (ret == -1 && errno == ENOATTR) {
549 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
555 if (fsp && (fsp->fh->fd != -1)) {
556 DEBUG(10,("set_ea: setting ea name %s on file "
557 "%s by file descriptor.\n",
558 unix_ea_name, fsp_str_dbg(fsp)));
559 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
560 ea_list->ea.value.data, ea_list->ea.value.length, 0);
562 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
563 unix_ea_name, fname));
564 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
565 ea_list->ea.value.data, ea_list->ea.value.length, 0);
571 if (errno == ENOTSUP) {
572 return NT_STATUS_EAS_NOT_SUPPORTED;
575 return map_nt_error_from_unix(errno);
581 /****************************************************************************
582 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
583 ****************************************************************************/
585 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
587 struct ea_list *ea_list_head = NULL;
588 size_t converted_size, offset = 0;
590 while (offset + 2 < data_size) {
591 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
592 unsigned int namelen = CVAL(pdata,offset);
594 offset++; /* Go past the namelen byte. */
596 /* integer wrap paranioa. */
597 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
598 (offset > data_size) || (namelen > data_size) ||
599 (offset + namelen >= data_size)) {
602 /* Ensure the name is null terminated. */
603 if (pdata[offset + namelen] != '\0') {
606 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
608 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
609 "failed: %s", strerror(errno)));
615 offset += (namelen + 1); /* Go past the name + terminating zero. */
616 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
617 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
623 /****************************************************************************
624 Read one EA list entry from the buffer.
625 ****************************************************************************/
627 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
629 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
631 unsigned int namelen;
632 size_t converted_size;
642 eal->ea.flags = CVAL(pdata,0);
643 namelen = CVAL(pdata,1);
644 val_len = SVAL(pdata,2);
646 if (4 + namelen + 1 + val_len > data_size) {
650 /* Ensure the name is null terminated. */
651 if (pdata[namelen + 4] != '\0') {
654 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
655 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
662 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
663 if (!eal->ea.value.data) {
667 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
669 /* Ensure we're null terminated just in case we print the value. */
670 eal->ea.value.data[val_len] = '\0';
671 /* But don't count the null. */
672 eal->ea.value.length--;
675 *pbytes_used = 4 + namelen + 1 + val_len;
678 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
679 dump_data(10, eal->ea.value.data, eal->ea.value.length);
684 /****************************************************************************
685 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
686 ****************************************************************************/
688 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
690 struct ea_list *ea_list_head = NULL;
692 size_t bytes_used = 0;
694 while (offset < data_size) {
695 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
701 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
702 offset += bytes_used;
708 /****************************************************************************
709 Count the total EA size needed.
710 ****************************************************************************/
712 static size_t ea_list_size(struct ea_list *ealist)
715 struct ea_list *listp;
718 for (listp = ealist; listp; listp = listp->next) {
719 push_ascii_fstring(dos_ea_name, listp->ea.name);
720 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
722 /* Add on 4 for total length. */
730 /****************************************************************************
731 Return a union of EA's from a file list and a list of names.
732 The TALLOC context for the two lists *MUST* be identical as we steal
733 memory from one list to add to another. JRA.
734 ****************************************************************************/
736 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
738 struct ea_list *nlistp, *flistp;
740 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
741 for (flistp = file_list; flistp; flistp = flistp->next) {
742 if (strequal(nlistp->ea.name, flistp->ea.name)) {
748 /* Copy the data from this entry. */
749 nlistp->ea.flags = flistp->ea.flags;
750 nlistp->ea.value = flistp->ea.value;
753 nlistp->ea.flags = 0;
754 ZERO_STRUCT(nlistp->ea.value);
758 *total_ea_len = ea_list_size(name_list);
762 /****************************************************************************
763 Send the required number of replies back.
764 We assume all fields other than the data fields are
765 set correctly for the type of call.
766 HACK ! Always assumes smb_setup field is zero.
767 ****************************************************************************/
769 void send_trans2_replies(connection_struct *conn,
770 struct smb_request *req,
777 /* As we are using a protocol > LANMAN1 then the max_send
778 variable must have been set in the sessetupX call.
779 This takes precedence over the max_xmit field in the
780 global struct. These different max_xmit variables should
781 be merged as this is now too confusing */
783 int data_to_send = datasize;
784 int params_to_send = paramsize;
786 const char *pp = params;
787 const char *pd = pdata;
788 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
789 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
790 int data_alignment_offset = 0;
791 bool overflow = False;
792 struct smbd_server_connection *sconn = req->sconn;
793 int max_send = sconn->smb1.sessions.max_send;
795 /* Modify the data_to_send and datasize and set the error if
796 we're trying to send more than max_data_bytes. We still send
797 the part of the packet(s) that fit. Strange, but needed
800 if (max_data_bytes > 0 && datasize > max_data_bytes) {
801 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
802 max_data_bytes, datasize ));
803 datasize = data_to_send = max_data_bytes;
807 /* If there genuinely are no parameters or data to send just send the empty packet */
809 if(params_to_send == 0 && data_to_send == 0) {
810 reply_outbuf(req, 10, 0);
811 show_msg((char *)req->outbuf);
812 if (!srv_send_smb(sconn,
815 IS_CONN_ENCRYPTED(conn),
817 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
819 TALLOC_FREE(req->outbuf);
823 /* When sending params and data ensure that both are nicely aligned */
824 /* Only do this alignment when there is also data to send - else
825 can cause NT redirector problems. */
827 if (((params_to_send % 4) != 0) && (data_to_send != 0))
828 data_alignment_offset = 4 - (params_to_send % 4);
830 /* Space is bufsize minus Netbios over TCP header minus SMB header */
831 /* The alignment_offset is to align the param bytes on an even byte
832 boundary. NT 4.0 Beta needs this to work correctly. */
834 useable_space = max_send - (smb_size
837 + data_alignment_offset);
839 if (useable_space < 0) {
840 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
841 "= %d!!!", useable_space));
842 exit_server_cleanly("send_trans2_replies: Not enough space");
845 while (params_to_send || data_to_send) {
846 /* Calculate whether we will totally or partially fill this packet */
848 total_sent_thistime = params_to_send + data_to_send;
850 /* We can never send more than useable_space */
852 * Note that 'useable_space' does not include the alignment offsets,
853 * but we must include the alignment offsets in the calculation of
854 * the length of the data we send over the wire, as the alignment offsets
855 * are sent here. Fix from Marc_Jacobsen@hp.com.
858 total_sent_thistime = MIN(total_sent_thistime, useable_space);
860 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
861 + data_alignment_offset);
864 * We might have SMBtrans2s in req which was transferred to
865 * the outbuf, fix that.
867 SCVAL(req->outbuf, smb_com, SMBtrans2);
869 /* Set total params and data to be sent */
870 SSVAL(req->outbuf,smb_tprcnt,paramsize);
871 SSVAL(req->outbuf,smb_tdrcnt,datasize);
873 /* Calculate how many parameters and data we can fit into
874 * this packet. Parameters get precedence
877 params_sent_thistime = MIN(params_to_send,useable_space);
878 data_sent_thistime = useable_space - params_sent_thistime;
879 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
881 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
883 /* smb_proff is the offset from the start of the SMB header to the
884 parameter bytes, however the first 4 bytes of outbuf are
885 the Netbios over TCP header. Thus use smb_base() to subtract
886 them from the calculation */
888 SSVAL(req->outbuf,smb_proff,
889 ((smb_buf(req->outbuf)+alignment_offset)
890 - smb_base(req->outbuf)));
892 if(params_sent_thistime == 0)
893 SSVAL(req->outbuf,smb_prdisp,0);
895 /* Absolute displacement of param bytes sent in this packet */
896 SSVAL(req->outbuf,smb_prdisp,pp - params);
898 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
899 if(data_sent_thistime == 0) {
900 SSVAL(req->outbuf,smb_droff,0);
901 SSVAL(req->outbuf,smb_drdisp, 0);
903 /* The offset of the data bytes is the offset of the
904 parameter bytes plus the number of parameters being sent this time */
905 SSVAL(req->outbuf, smb_droff,
906 ((smb_buf(req->outbuf)+alignment_offset)
907 - smb_base(req->outbuf))
908 + params_sent_thistime + data_alignment_offset);
909 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
912 /* Initialize the padding for alignment */
914 if (alignment_offset != 0) {
915 memset(smb_buf(req->outbuf), 0, alignment_offset);
918 /* Copy the param bytes into the packet */
920 if(params_sent_thistime) {
921 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
922 params_sent_thistime);
925 /* Copy in the data bytes */
926 if(data_sent_thistime) {
927 if (data_alignment_offset != 0) {
928 memset((smb_buf(req->outbuf)+alignment_offset+
929 params_sent_thistime), 0,
930 data_alignment_offset);
932 memcpy(smb_buf(req->outbuf)+alignment_offset
933 +params_sent_thistime+data_alignment_offset,
934 pd,data_sent_thistime);
937 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
938 params_sent_thistime, data_sent_thistime, useable_space));
939 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
940 params_to_send, data_to_send, paramsize, datasize));
943 error_packet_set((char *)req->outbuf,
944 ERRDOS,ERRbufferoverflow,
945 STATUS_BUFFER_OVERFLOW,
949 /* Send the packet */
950 show_msg((char *)req->outbuf);
951 if (!srv_send_smb(sconn,
954 IS_CONN_ENCRYPTED(conn),
956 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
958 TALLOC_FREE(req->outbuf);
960 pp += params_sent_thistime;
961 pd += data_sent_thistime;
963 params_to_send -= params_sent_thistime;
964 data_to_send -= data_sent_thistime;
967 if(params_to_send < 0 || data_to_send < 0) {
968 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
969 params_to_send, data_to_send));
977 /****************************************************************************
978 Reply to a TRANSACT2_OPEN.
979 ****************************************************************************/
981 static void call_trans2open(connection_struct *conn,
982 struct smb_request *req,
983 char **pparams, int total_params,
984 char **ppdata, int total_data,
985 unsigned int max_data_bytes)
987 struct smb_filename *smb_fname = NULL;
988 char *params = *pparams;
989 char *pdata = *ppdata;
994 bool return_additional_info;
1003 int fattr=0,mtime=0;
1004 SMB_INO_T inode = 0;
1007 struct ea_list *ea_list = NULL;
1012 uint32 create_disposition;
1013 uint32 create_options = 0;
1014 uint32_t private_flags = 0;
1015 TALLOC_CTX *ctx = talloc_tos();
1018 * Ensure we have enough parameters to perform the operation.
1021 if (total_params < 29) {
1022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1026 flags = SVAL(params, 0);
1027 deny_mode = SVAL(params, 2);
1028 open_attr = SVAL(params,6);
1029 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1030 if (oplock_request) {
1031 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1035 return_additional_info = BITSETW(params,0);
1036 open_sattr = SVAL(params, 4);
1037 open_time = make_unix_date3(params+8);
1039 open_ofun = SVAL(params,12);
1040 open_size = IVAL(params,14);
1041 pname = ¶ms[28];
1044 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1048 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1049 total_params - 28, STR_TERMINATE,
1051 if (!NT_STATUS_IS_OK(status)) {
1052 reply_nterror(req, status);
1056 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1057 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1058 (unsigned int)open_ofun, open_size));
1060 status = filename_convert(ctx,
1062 req->flags2 & FLAGS2_DFS_PATHNAMES,
1067 if (!NT_STATUS_IS_OK(status)) {
1068 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1069 reply_botherror(req,
1070 NT_STATUS_PATH_NOT_COVERED,
1071 ERRSRV, ERRbadpath);
1074 reply_nterror(req, status);
1078 if (open_ofun == 0) {
1079 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1083 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1084 &access_mask, &share_mode,
1085 &create_disposition,
1088 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1092 /* Any data in this call is an EA list. */
1093 if (total_data && (total_data != 4)) {
1094 if (total_data < 10) {
1095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1099 if (IVAL(pdata,0) > total_data) {
1100 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1101 IVAL(pdata,0), (unsigned int)total_data));
1102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1106 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1113 if (!lp_ea_support(SNUM(conn))) {
1114 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1119 status = SMB_VFS_CREATE_FILE(
1122 0, /* root_dir_fid */
1123 smb_fname, /* fname */
1124 access_mask, /* access_mask */
1125 share_mode, /* share_access */
1126 create_disposition, /* create_disposition*/
1127 create_options, /* create_options */
1128 open_attr, /* file_attributes */
1129 oplock_request, /* oplock_request */
1130 open_size, /* allocation_size */
1133 ea_list, /* ea_list */
1135 &smb_action); /* psbuf */
1137 if (!NT_STATUS_IS_OK(status)) {
1138 if (open_was_deferred(req->mid)) {
1139 /* We have re-scheduled this call. */
1142 reply_openerror(req, status);
1146 size = get_file_size_stat(&smb_fname->st);
1147 fattr = dos_mode(conn, smb_fname);
1148 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1149 inode = smb_fname->st.st_ex_ino;
1151 close_file(req, fsp, ERROR_CLOSE);
1152 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1156 /* Realloc the size of parameters and data we will return */
1157 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1158 if(*pparams == NULL ) {
1159 reply_nterror(req, NT_STATUS_NO_MEMORY);
1164 SSVAL(params,0,fsp->fnum);
1165 SSVAL(params,2,fattr);
1166 srv_put_dos_date2(params,4, mtime);
1167 SIVAL(params,8, (uint32)size);
1168 SSVAL(params,12,deny_mode);
1169 SSVAL(params,14,0); /* open_type - file or directory. */
1170 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1172 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1173 smb_action |= EXTENDED_OPLOCK_GRANTED;
1176 SSVAL(params,18,smb_action);
1179 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1181 SIVAL(params,20,inode);
1182 SSVAL(params,24,0); /* Padding. */
1184 uint32 ea_size = estimate_ea_size(conn, fsp,
1185 fsp->fsp_name->base_name);
1186 SIVAL(params, 26, ea_size);
1188 SIVAL(params, 26, 0);
1191 /* Send the required number of replies */
1192 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1194 TALLOC_FREE(smb_fname);
1197 /*********************************************************
1198 Routine to check if a given string matches exactly.
1199 as a special case a mask of "." does NOT match. That
1200 is required for correct wildcard semantics
1201 Case can be significant or not.
1202 **********************************************************/
1204 static bool exact_match(bool has_wild,
1205 bool case_sensitive,
1209 if (mask[0] == '.' && mask[1] == 0) {
1217 if (case_sensitive) {
1218 return strcmp(str,mask)==0;
1220 return StrCaseCmp(str,mask) == 0;
1224 /****************************************************************************
1225 Return the filetype for UNIX extensions.
1226 ****************************************************************************/
1228 static uint32 unix_filetype(mode_t mode)
1231 return UNIX_TYPE_FILE;
1232 else if(S_ISDIR(mode))
1233 return UNIX_TYPE_DIR;
1235 else if(S_ISLNK(mode))
1236 return UNIX_TYPE_SYMLINK;
1239 else if(S_ISCHR(mode))
1240 return UNIX_TYPE_CHARDEV;
1243 else if(S_ISBLK(mode))
1244 return UNIX_TYPE_BLKDEV;
1247 else if(S_ISFIFO(mode))
1248 return UNIX_TYPE_FIFO;
1251 else if(S_ISSOCK(mode))
1252 return UNIX_TYPE_SOCKET;
1255 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1256 return UNIX_TYPE_UNKNOWN;
1259 /****************************************************************************
1260 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1261 ****************************************************************************/
1263 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1265 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1266 const SMB_STRUCT_STAT *psbuf,
1268 enum perm_type ptype,
1273 if (perms == SMB_MODE_NO_CHANGE) {
1274 if (!VALID_STAT(*psbuf)) {
1275 return NT_STATUS_INVALID_PARAMETER;
1277 *ret_perms = psbuf->st_ex_mode;
1278 return NT_STATUS_OK;
1282 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1283 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1284 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1285 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1286 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1287 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1288 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1289 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1290 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1292 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1295 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1298 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1303 /* Apply mode mask */
1304 ret &= lp_create_mask(SNUM(conn));
1305 /* Add in force bits */
1306 ret |= lp_force_create_mode(SNUM(conn));
1309 ret &= lp_dir_mask(SNUM(conn));
1310 /* Add in force bits */
1311 ret |= lp_force_dir_mode(SNUM(conn));
1313 case PERM_EXISTING_FILE:
1314 /* Apply mode mask */
1315 ret &= lp_security_mask(SNUM(conn));
1316 /* Add in force bits */
1317 ret |= lp_force_security_mode(SNUM(conn));
1319 case PERM_EXISTING_DIR:
1320 /* Apply mode mask */
1321 ret &= lp_dir_security_mask(SNUM(conn));
1322 /* Add in force bits */
1323 ret |= lp_force_dir_security_mode(SNUM(conn));
1328 return NT_STATUS_OK;
1331 /****************************************************************************
1332 Needed to show the msdfs symlinks as directories. Modifies psbuf
1333 to be a directory if it's a msdfs link.
1334 ****************************************************************************/
1336 static bool check_msdfs_link(connection_struct *conn,
1337 const char *pathname,
1338 SMB_STRUCT_STAT *psbuf)
1340 int saved_errno = errno;
1341 if(lp_host_msdfs() &&
1342 lp_msdfs_root(SNUM(conn)) &&
1343 is_msdfs_link(conn, pathname, psbuf)) {
1345 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1348 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1349 errno = saved_errno;
1352 errno = saved_errno;
1357 /****************************************************************************
1358 Get a level dependent lanman2 dir entry.
1359 ****************************************************************************/
1361 struct smbd_dirptr_lanman2_state {
1362 connection_struct *conn;
1363 uint32_t info_level;
1364 bool check_mangled_names;
1366 bool got_exact_match;
1369 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1375 struct smbd_dirptr_lanman2_state *state =
1376 (struct smbd_dirptr_lanman2_state *)private_data;
1378 char mangled_name[13]; /* mangled 8.3 name. */
1382 /* Mangle fname if it's an illegal name. */
1383 if (mangle_must_mangle(dname, state->conn->params)) {
1384 ok = name_to_8_3(dname, mangled_name,
1385 true, state->conn->params);
1389 fname = mangled_name;
1394 got_match = exact_match(state->has_wild,
1395 state->conn->case_sensitive,
1397 state->got_exact_match = got_match;
1399 got_match = mask_match(fname, mask,
1400 state->conn->case_sensitive);
1403 if(!got_match && state->check_mangled_names &&
1404 !mangle_is_8_3(fname, false, state->conn->params)) {
1406 * It turns out that NT matches wildcards against
1407 * both long *and* short names. This may explain some
1408 * of the wildcard wierdness from old DOS clients
1409 * that some people have been seeing.... JRA.
1411 /* Force the mangling into 8.3. */
1412 ok = name_to_8_3(fname, mangled_name,
1413 false, state->conn->params);
1418 got_match = exact_match(state->has_wild,
1419 state->conn->case_sensitive,
1420 mangled_name, mask);
1421 state->got_exact_match = got_match;
1423 got_match = mask_match(mangled_name, mask,
1424 state->conn->case_sensitive);
1432 *_fname = talloc_strdup(ctx, fname);
1433 if (*_fname == NULL) {
1440 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1442 struct smb_filename *smb_fname,
1445 struct smbd_dirptr_lanman2_state *state =
1446 (struct smbd_dirptr_lanman2_state *)private_data;
1447 bool ms_dfs_link = false;
1450 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1451 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1452 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1453 "Couldn't lstat [%s] (%s)\n",
1454 smb_fname_str_dbg(smb_fname),
1458 } else if (!VALID_STAT(smb_fname->st) &&
1459 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1460 /* Needed to show the msdfs symlinks as
1463 ms_dfs_link = check_msdfs_link(state->conn,
1464 smb_fname->base_name,
1467 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1468 "Couldn't stat [%s] (%s)\n",
1469 smb_fname_str_dbg(smb_fname),
1476 mode = dos_mode_msdfs(state->conn, smb_fname);
1478 mode = dos_mode(state->conn, smb_fname);
1485 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1486 connection_struct *conn,
1488 uint32_t info_level,
1489 struct ea_list *name_list,
1490 bool check_mangled_names,
1491 bool requires_resume_key,
1494 const struct smb_filename *smb_fname,
1495 int space_remaining,
1502 uint64_t *last_entry_off)
1504 char *p, *q, *pdata = *ppdata;
1506 uint64_t file_size = 0;
1507 uint64_t allocation_size = 0;
1508 uint64_t file_index = 0;
1510 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1511 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1512 time_t c_date = (time_t)0;
1514 char *last_entry_ptr;
1519 *out_of_space = false;
1521 ZERO_STRUCT(mdate_ts);
1522 ZERO_STRUCT(adate_ts);
1523 ZERO_STRUCT(create_date_ts);
1524 ZERO_STRUCT(cdate_ts);
1526 if (!(mode & aDIR)) {
1527 file_size = get_file_size_stat(&smb_fname->st);
1529 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1531 file_index = get_FileIndex(conn, &smb_fname->st);
1533 mdate_ts = smb_fname->st.st_ex_mtime;
1534 adate_ts = smb_fname->st.st_ex_atime;
1535 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1536 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1538 if (lp_dos_filetime_resolution(SNUM(conn))) {
1539 dos_filetime_timespec(&create_date_ts);
1540 dos_filetime_timespec(&mdate_ts);
1541 dos_filetime_timespec(&adate_ts);
1542 dos_filetime_timespec(&cdate_ts);
1545 create_date = convert_timespec_to_time_t(create_date_ts);
1546 mdate = convert_timespec_to_time_t(mdate_ts);
1547 adate = convert_timespec_to_time_t(adate_ts);
1548 c_date = convert_timespec_to_time_t(cdate_ts);
1550 /* align the record */
1551 SMB_ASSERT(align >= 1);
1553 off = (int)PTR_DIFF(pdata, base_data);
1554 pad = (off + (align-1)) & ~(align-1);
1557 if (pad && pad > space_remaining) {
1558 *out_of_space = true;
1559 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1560 "for padding (wanted %u, had %d)\n",
1563 return false; /* Not finished - just out of space */
1567 /* initialize padding to 0 */
1569 memset(pdata, 0, pad);
1571 space_remaining -= pad;
1573 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1583 switch (info_level) {
1584 case SMB_FIND_INFO_STANDARD:
1585 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1586 if(requires_resume_key) {
1590 srv_put_dos_date2(p,0,create_date);
1591 srv_put_dos_date2(p,4,adate);
1592 srv_put_dos_date2(p,8,mdate);
1593 SIVAL(p,12,(uint32)file_size);
1594 SIVAL(p,16,(uint32)allocation_size);
1598 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1599 p += ucs2_align(base_data, p, 0);
1601 len = srvstr_push(base_data, flags2, p,
1602 fname, PTR_DIFF(end_data, p),
1604 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1606 SCVAL(nameptr, -1, len - 2);
1608 SCVAL(nameptr, -1, 0);
1612 SCVAL(nameptr, -1, len - 1);
1614 SCVAL(nameptr, -1, 0);
1620 case SMB_FIND_EA_SIZE:
1621 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1622 if (requires_resume_key) {
1626 srv_put_dos_date2(p,0,create_date);
1627 srv_put_dos_date2(p,4,adate);
1628 srv_put_dos_date2(p,8,mdate);
1629 SIVAL(p,12,(uint32)file_size);
1630 SIVAL(p,16,(uint32)allocation_size);
1633 unsigned int ea_size = estimate_ea_size(conn, NULL,
1634 smb_fname->base_name);
1635 SIVAL(p,22,ea_size); /* Extended attributes */
1639 len = srvstr_push(base_data, flags2,
1640 p, fname, PTR_DIFF(end_data, p),
1641 STR_TERMINATE | STR_NOALIGN);
1642 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1655 SCVAL(nameptr,0,len);
1657 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1660 case SMB_FIND_EA_LIST:
1662 struct ea_list *file_list = NULL;
1665 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1669 if (requires_resume_key) {
1673 srv_put_dos_date2(p,0,create_date);
1674 srv_put_dos_date2(p,4,adate);
1675 srv_put_dos_date2(p,8,mdate);
1676 SIVAL(p,12,(uint32)file_size);
1677 SIVAL(p,16,(uint32)allocation_size);
1679 p += 22; /* p now points to the EA area. */
1681 file_list = get_ea_list_from_file(ctx, conn, NULL,
1682 smb_fname->base_name,
1684 name_list = ea_list_union(name_list, file_list, &ea_len);
1686 /* We need to determine if this entry will fit in the space available. */
1687 /* Max string size is 255 bytes. */
1688 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1689 *out_of_space = true;
1690 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1691 "(wanted %u, had %d)\n",
1692 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1694 return False; /* Not finished - just out of space */
1697 /* Push the ea_data followed by the name. */
1698 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1700 len = srvstr_push(base_data, flags2,
1701 p + 1, fname, PTR_DIFF(end_data, p+1),
1702 STR_TERMINATE | STR_NOALIGN);
1703 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1716 SCVAL(nameptr,0,len);
1718 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1722 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1723 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1724 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1726 SIVAL(p,0,reskey); p += 4;
1727 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1728 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1729 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1730 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1731 SOFF_T(p,0,file_size); p += 8;
1732 SOFF_T(p,0,allocation_size); p += 8;
1733 SIVAL(p,0,mode); p += 4;
1734 q = p; p += 4; /* q is placeholder for name length. */
1736 unsigned int ea_size = estimate_ea_size(conn, NULL,
1737 smb_fname->base_name);
1738 SIVAL(p,0,ea_size); /* Extended attributes */
1741 /* Clear the short name buffer. This is
1742 * IMPORTANT as not doing so will trigger
1743 * a Win2k client bug. JRA.
1745 if (!was_8_3 && check_mangled_names) {
1746 char mangled_name[13]; /* mangled 8.3 name. */
1747 if (!name_to_8_3(fname,mangled_name,True,
1749 /* Error - mangle failed ! */
1750 memset(mangled_name,'\0',12);
1752 mangled_name[12] = 0;
1753 len = srvstr_push(base_data, flags2,
1754 p+2, mangled_name, 24,
1755 STR_UPPER|STR_UNICODE);
1757 memset(p + 2 + len,'\0',24 - len);
1764 len = srvstr_push(base_data, flags2, p,
1765 fname, PTR_DIFF(end_data, p),
1766 STR_TERMINATE_ASCII);
1770 len = PTR_DIFF(p, pdata);
1771 pad = (len + (align-1)) & ~(align-1);
1773 * offset to the next entry, the caller
1774 * will overwrite it for the last entry
1775 * that's why we always include the padding
1779 * set padding to zero
1782 memset(p, 0, pad - len);
1789 case SMB_FIND_FILE_DIRECTORY_INFO:
1790 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1792 SIVAL(p,0,reskey); p += 4;
1793 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1794 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1795 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1796 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1797 SOFF_T(p,0,file_size); p += 8;
1798 SOFF_T(p,0,allocation_size); p += 8;
1799 SIVAL(p,0,mode); p += 4;
1800 len = srvstr_push(base_data, flags2,
1801 p + 4, fname, PTR_DIFF(end_data, p+4),
1802 STR_TERMINATE_ASCII);
1806 len = PTR_DIFF(p, pdata);
1807 pad = (len + (align-1)) & ~(align-1);
1809 * offset to the next entry, the caller
1810 * will overwrite it for the last entry
1811 * that's why we always include the padding
1815 * set padding to zero
1818 memset(p, 0, pad - len);
1825 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1826 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1828 SIVAL(p,0,reskey); p += 4;
1829 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1830 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1831 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1832 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1833 SOFF_T(p,0,file_size); p += 8;
1834 SOFF_T(p,0,allocation_size); p += 8;
1835 SIVAL(p,0,mode); p += 4;
1836 q = p; p += 4; /* q is placeholder for name length. */
1838 unsigned int ea_size = estimate_ea_size(conn, NULL,
1839 smb_fname->base_name);
1840 SIVAL(p,0,ea_size); /* Extended attributes */
1843 len = srvstr_push(base_data, flags2, p,
1844 fname, PTR_DIFF(end_data, p),
1845 STR_TERMINATE_ASCII);
1849 len = PTR_DIFF(p, pdata);
1850 pad = (len + (align-1)) & ~(align-1);
1852 * offset to the next entry, the caller
1853 * will overwrite it for the last entry
1854 * that's why we always include the padding
1858 * set padding to zero
1861 memset(p, 0, pad - len);
1868 case SMB_FIND_FILE_NAMES_INFO:
1869 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1871 SIVAL(p,0,reskey); p += 4;
1873 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1874 acl on a dir (tridge) */
1875 len = srvstr_push(base_data, flags2, p,
1876 fname, PTR_DIFF(end_data, p),
1877 STR_TERMINATE_ASCII);
1881 len = PTR_DIFF(p, pdata);
1882 pad = (len + (align-1)) & ~(align-1);
1884 * offset to the next entry, the caller
1885 * will overwrite it for the last entry
1886 * that's why we always include the padding
1890 * set padding to zero
1893 memset(p, 0, pad - len);
1900 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1901 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1903 SIVAL(p,0,reskey); p += 4;
1904 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1905 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1906 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1907 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1908 SOFF_T(p,0,file_size); p += 8;
1909 SOFF_T(p,0,allocation_size); p += 8;
1910 SIVAL(p,0,mode); p += 4;
1911 q = p; p += 4; /* q is placeholder for name length. */
1913 unsigned int ea_size = estimate_ea_size(conn, NULL,
1914 smb_fname->base_name);
1915 SIVAL(p,0,ea_size); /* Extended attributes */
1918 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1919 SBVAL(p,0,file_index); p += 8;
1920 len = srvstr_push(base_data, flags2, p,
1921 fname, PTR_DIFF(end_data, p),
1922 STR_TERMINATE_ASCII);
1926 len = PTR_DIFF(p, pdata);
1927 pad = (len + (align-1)) & ~(align-1);
1929 * offset to the next entry, the caller
1930 * will overwrite it for the last entry
1931 * that's why we always include the padding
1935 * set padding to zero
1938 memset(p, 0, pad - len);
1945 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1946 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1947 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1949 SIVAL(p,0,reskey); p += 4;
1950 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1951 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1952 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1953 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1954 SOFF_T(p,0,file_size); p += 8;
1955 SOFF_T(p,0,allocation_size); p += 8;
1956 SIVAL(p,0,mode); p += 4;
1957 q = p; p += 4; /* q is placeholder for name length */
1959 unsigned int ea_size = estimate_ea_size(conn, NULL,
1960 smb_fname->base_name);
1961 SIVAL(p,0,ea_size); /* Extended attributes */
1964 /* Clear the short name buffer. This is
1965 * IMPORTANT as not doing so will trigger
1966 * a Win2k client bug. JRA.
1968 if (!was_8_3 && check_mangled_names) {
1969 char mangled_name[13]; /* mangled 8.3 name. */
1970 if (!name_to_8_3(fname,mangled_name,True,
1972 /* Error - mangle failed ! */
1973 memset(mangled_name,'\0',12);
1975 mangled_name[12] = 0;
1976 len = srvstr_push(base_data, flags2,
1977 p+2, mangled_name, 24,
1978 STR_UPPER|STR_UNICODE);
1981 memset(p + 2 + len,'\0',24 - len);
1988 SSVAL(p,0,0); p += 2; /* Reserved ? */
1989 SBVAL(p,0,file_index); p += 8;
1990 len = srvstr_push(base_data, flags2, p,
1991 fname, PTR_DIFF(end_data, p),
1992 STR_TERMINATE_ASCII);
1996 len = PTR_DIFF(p, pdata);
1997 pad = (len + (align-1)) & ~(align-1);
1999 * offset to the next entry, the caller
2000 * will overwrite it for the last entry
2001 * that's why we always include the padding
2005 * set padding to zero
2008 memset(p, 0, pad - len);
2015 /* CIFS UNIX Extension. */
2017 case SMB_FIND_FILE_UNIX:
2018 case SMB_FIND_FILE_UNIX_INFO2:
2020 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2022 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2024 if (info_level == SMB_FIND_FILE_UNIX) {
2025 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2026 p = store_file_unix_basic(conn, p,
2027 NULL, &smb_fname->st);
2028 len = srvstr_push(base_data, flags2, p,
2029 fname, PTR_DIFF(end_data, p),
2032 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2033 p = store_file_unix_basic_info2(conn, p,
2034 NULL, &smb_fname->st);
2037 len = srvstr_push(base_data, flags2, p, fname,
2038 PTR_DIFF(end_data, p), 0);
2039 SIVAL(nameptr, 0, len);
2044 len = PTR_DIFF(p, pdata);
2045 pad = (len + (align-1)) & ~(align-1);
2047 * offset to the next entry, the caller
2048 * will overwrite it for the last entry
2049 * that's why we always include the padding
2053 * set padding to zero
2056 memset(p, 0, pad - len);
2061 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2069 if (PTR_DIFF(p,pdata) > space_remaining) {
2070 *out_of_space = true;
2071 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2072 "(wanted %u, had %d)\n",
2073 (unsigned int)PTR_DIFF(p,pdata),
2075 return false; /* Not finished - just out of space */
2078 /* Setup the last entry pointer, as an offset from base_data */
2079 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2080 /* Advance the data pointer to the next slot */
2086 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2087 connection_struct *conn,
2088 struct dptr_struct *dirptr,
2090 const char *path_mask,
2093 int requires_resume_key,
2101 int space_remaining,
2103 bool *got_exact_match,
2104 int *_last_entry_off,
2105 struct ea_list *name_list)
2108 const char *mask = NULL;
2109 long prev_dirpos = 0;
2112 struct smb_filename *smb_fname = NULL;
2113 struct smbd_dirptr_lanman2_state state;
2115 uint64_t last_entry_off = 0;
2119 state.info_level = info_level;
2120 state.check_mangled_names = lp_manglednames(conn->params);
2121 state.has_wild = dptr_has_wild(dirptr);
2122 state.got_exact_match = false;
2124 *out_of_space = false;
2125 *got_exact_match = false;
2127 p = strrchr_m(path_mask,'/');
2138 ok = smbd_dirptr_get_entry(ctx,
2144 smbd_dirptr_lanman2_match_fn,
2145 smbd_dirptr_lanman2_mode_fn,
2155 *got_exact_match = state.got_exact_match;
2157 ok = smbd_marshall_dir_entry(ctx,
2162 state.check_mangled_names,
2163 requires_resume_key,
2176 TALLOC_FREE(smb_fname);
2177 if (*out_of_space) {
2178 dptr_SeekDir(dirptr, prev_dirpos);
2185 *_last_entry_off = last_entry_off;
2189 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2190 connection_struct *conn,
2191 struct dptr_struct *dirptr,
2193 const char *path_mask,
2196 bool requires_resume_key,
2202 int space_remaining,
2204 bool *got_exact_match,
2205 int *last_entry_off,
2206 struct ea_list *name_list)
2209 const bool do_pad = true;
2211 if (info_level >= 1 && info_level <= 3) {
2212 /* No alignment on earlier info levels. */
2216 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2217 path_mask, dirtype, info_level,
2218 requires_resume_key, dont_descend, ask_sharemode,
2220 ppdata, base_data, end_data,
2222 out_of_space, got_exact_match,
2223 last_entry_off, name_list);
2226 /****************************************************************************
2227 Reply to a TRANS2_FINDFIRST.
2228 ****************************************************************************/
2230 static void call_trans2findfirst(connection_struct *conn,
2231 struct smb_request *req,
2232 char **pparams, int total_params,
2233 char **ppdata, int total_data,
2234 unsigned int max_data_bytes)
2236 /* We must be careful here that we don't return more than the
2237 allowed number of data bytes. If this means returning fewer than
2238 maxentries then so be it. We assume that the redirector has
2239 enough room for the fixed number of parameter bytes it has
2241 struct smb_filename *smb_dname = NULL;
2242 char *params = *pparams;
2243 char *pdata = *ppdata;
2247 uint16 findfirst_flags;
2248 bool close_after_first;
2250 bool requires_resume_key;
2252 char *directory = NULL;
2255 int last_entry_off=0;
2259 bool finished = False;
2260 bool dont_descend = False;
2261 bool out_of_space = False;
2262 int space_remaining;
2263 bool mask_contains_wcard = False;
2264 struct ea_list *ea_list = NULL;
2265 NTSTATUS ntstatus = NT_STATUS_OK;
2266 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2267 TALLOC_CTX *ctx = talloc_tos();
2268 struct dptr_struct *dirptr = NULL;
2269 struct smbd_server_connection *sconn = req->sconn;
2271 if (total_params < 13) {
2272 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2276 dirtype = SVAL(params,0);
2277 maxentries = SVAL(params,2);
2278 findfirst_flags = SVAL(params,4);
2279 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2280 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2281 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2282 info_level = SVAL(params,6);
2284 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2285 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2286 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2287 info_level, max_data_bytes));
2290 /* W2K3 seems to treat zero as 1. */
2294 switch (info_level) {
2295 case SMB_FIND_INFO_STANDARD:
2296 case SMB_FIND_EA_SIZE:
2297 case SMB_FIND_EA_LIST:
2298 case SMB_FIND_FILE_DIRECTORY_INFO:
2299 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2300 case SMB_FIND_FILE_NAMES_INFO:
2301 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2302 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2305 case SMB_FIND_FILE_UNIX:
2306 case SMB_FIND_FILE_UNIX_INFO2:
2307 /* Always use filesystem for UNIX mtime query. */
2308 ask_sharemode = false;
2309 if (!lp_unix_extensions()) {
2310 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2315 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2319 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2320 params+12, total_params - 12,
2321 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2322 if (!NT_STATUS_IS_OK(ntstatus)) {
2323 reply_nterror(req, ntstatus);
2327 ntstatus = filename_convert(ctx, conn,
2328 req->flags2 & FLAGS2_DFS_PATHNAMES,
2331 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2332 &mask_contains_wcard,
2334 if (!NT_STATUS_IS_OK(ntstatus)) {
2335 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2336 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2337 ERRSRV, ERRbadpath);
2340 reply_nterror(req, ntstatus);
2344 mask = smb_dname->original_lcomp;
2346 directory = smb_dname->base_name;
2348 p = strrchr_m(directory,'/');
2350 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2351 if((directory[0] == '.') && (directory[1] == '\0')) {
2352 mask = talloc_strdup(ctx,"*");
2354 reply_nterror(req, NT_STATUS_NO_MEMORY);
2357 mask_contains_wcard = True;
2363 if (p == NULL || p == directory) {
2364 /* Ensure we don't have a directory name of "". */
2365 directory = talloc_strdup(talloc_tos(), ".");
2367 reply_nterror(req, NT_STATUS_NO_MEMORY);
2372 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2374 if (info_level == SMB_FIND_EA_LIST) {
2377 if (total_data < 4) {
2378 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2382 ea_size = IVAL(pdata,0);
2383 if (ea_size != total_data) {
2384 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2385 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2390 if (!lp_ea_support(SNUM(conn))) {
2391 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2395 /* Pull out the list of names. */
2396 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2398 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2403 *ppdata = (char *)SMB_REALLOC(
2404 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2405 if(*ppdata == NULL ) {
2406 reply_nterror(req, NT_STATUS_NO_MEMORY);
2410 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2412 /* Realloc the params space */
2413 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2414 if (*pparams == NULL) {
2415 reply_nterror(req, NT_STATUS_NO_MEMORY);
2420 /* Save the wildcard match and attribs we are using on this directory -
2421 needed as lanman2 assumes these are being saved between calls */
2423 ntstatus = dptr_create(conn,
2430 mask_contains_wcard,
2434 if (!NT_STATUS_IS_OK(ntstatus)) {
2435 reply_nterror(req, ntstatus);
2439 dptr_num = dptr_dnum(dirptr);
2440 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2442 /* Initialize per TRANS2_FIND_FIRST operation data */
2443 dptr_init_search_op(dirptr);
2445 /* We don't need to check for VOL here as this is returned by
2446 a different TRANS2 call. */
2448 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2449 directory,lp_dontdescend(SNUM(conn))));
2450 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2451 dont_descend = True;
2454 space_remaining = max_data_bytes;
2455 out_of_space = False;
2457 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2458 bool got_exact_match = False;
2460 /* this is a heuristic to avoid seeking the dirptr except when
2461 absolutely necessary. It allows for a filename of about 40 chars */
2462 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2463 out_of_space = True;
2466 finished = !get_lanman2_dir_entry(ctx,
2470 mask,dirtype,info_level,
2471 requires_resume_key,dont_descend,
2474 space_remaining, &out_of_space,
2476 &last_entry_off, ea_list);
2479 if (finished && out_of_space)
2482 if (!finished && !out_of_space)
2486 * As an optimisation if we know we aren't looking
2487 * for a wildcard name (ie. the name matches the wildcard exactly)
2488 * then we can finish on any (first) match.
2489 * This speeds up large directory searches. JRA.
2495 /* Ensure space_remaining never goes -ve. */
2496 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2497 space_remaining = 0;
2498 out_of_space = true;
2500 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2504 /* Check if we can close the dirptr */
2505 if(close_after_first || (finished && close_if_end)) {
2506 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2507 dptr_close(sconn, &dptr_num);
2511 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2512 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2513 * the protocol level is less than NT1. Tested with smbclient. JRA.
2514 * This should fix the OS/2 client bug #2335.
2517 if(numentries == 0) {
2518 dptr_close(sconn, &dptr_num);
2519 if (get_Protocol() < PROTOCOL_NT1) {
2520 reply_force_doserror(req, ERRDOS, ERRnofiles);
2523 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2524 ERRDOS, ERRbadfile);
2529 /* At this point pdata points to numentries directory entries. */
2531 /* Set up the return parameter block */
2532 SSVAL(params,0,dptr_num);
2533 SSVAL(params,2,numentries);
2534 SSVAL(params,4,finished);
2535 SSVAL(params,6,0); /* Never an EA error */
2536 SSVAL(params,8,last_entry_off);
2538 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2541 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2542 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2544 reply_nterror(req, NT_STATUS_NO_MEMORY);
2548 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2549 smb_fn_name(req->cmd),
2550 mask, directory, dirtype, numentries ) );
2553 * Force a name mangle here to ensure that the
2554 * mask as an 8.3 name is top of the mangled cache.
2555 * The reasons for this are subtle. Don't remove
2556 * this code unless you know what you are doing
2557 * (see PR#13758). JRA.
2560 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2561 char mangled_name[13];
2562 name_to_8_3(mask, mangled_name, True, conn->params);
2565 TALLOC_FREE(smb_dname);
2569 /****************************************************************************
2570 Reply to a TRANS2_FINDNEXT.
2571 ****************************************************************************/
2573 static void call_trans2findnext(connection_struct *conn,
2574 struct smb_request *req,
2575 char **pparams, int total_params,
2576 char **ppdata, int total_data,
2577 unsigned int max_data_bytes)
2579 /* We must be careful here that we don't return more than the
2580 allowed number of data bytes. If this means returning fewer than
2581 maxentries then so be it. We assume that the redirector has
2582 enough room for the fixed number of parameter bytes it has
2584 char *params = *pparams;
2585 char *pdata = *ppdata;
2591 uint16 findnext_flags;
2592 bool close_after_request;
2594 bool requires_resume_key;
2596 bool mask_contains_wcard = False;
2597 char *resume_name = NULL;
2598 const char *mask = NULL;
2599 const char *directory = NULL;
2603 int i, last_entry_off=0;
2604 bool finished = False;
2605 bool dont_descend = False;
2606 bool out_of_space = False;
2607 int space_remaining;
2608 struct ea_list *ea_list = NULL;
2609 NTSTATUS ntstatus = NT_STATUS_OK;
2610 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2611 TALLOC_CTX *ctx = talloc_tos();
2612 struct dptr_struct *dirptr;
2613 struct smbd_server_connection *sconn = req->sconn;
2615 if (total_params < 13) {
2616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2620 dptr_num = SVAL(params,0);
2621 maxentries = SVAL(params,2);
2622 info_level = SVAL(params,4);
2623 resume_key = IVAL(params,6);
2624 findnext_flags = SVAL(params,10);
2625 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2626 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2627 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2628 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2630 if (!continue_bit) {
2631 /* We only need resume_name if continue_bit is zero. */
2632 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2634 total_params - 12, STR_TERMINATE, &ntstatus,
2635 &mask_contains_wcard);
2636 if (!NT_STATUS_IS_OK(ntstatus)) {
2637 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2638 complain (it thinks we're asking for the directory above the shared
2639 path or an invalid name). Catch this as the resume name is only compared, never used in
2640 a file access. JRA. */
2641 srvstr_pull_talloc(ctx, params, req->flags2,
2642 &resume_name, params+12,
2646 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2647 reply_nterror(req, ntstatus);
2653 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2654 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2655 resume_key = %d resume name = %s continue=%d level = %d\n",
2656 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2657 requires_resume_key, resume_key,
2658 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2661 /* W2K3 seems to treat zero as 1. */
2665 switch (info_level) {
2666 case SMB_FIND_INFO_STANDARD:
2667 case SMB_FIND_EA_SIZE:
2668 case SMB_FIND_EA_LIST:
2669 case SMB_FIND_FILE_DIRECTORY_INFO:
2670 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2671 case SMB_FIND_FILE_NAMES_INFO:
2672 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2673 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2674 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2676 case SMB_FIND_FILE_UNIX:
2677 case SMB_FIND_FILE_UNIX_INFO2:
2678 /* Always use filesystem for UNIX mtime query. */
2679 ask_sharemode = false;
2680 if (!lp_unix_extensions()) {
2681 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2686 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2690 if (info_level == SMB_FIND_EA_LIST) {
2693 if (total_data < 4) {
2694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2698 ea_size = IVAL(pdata,0);
2699 if (ea_size != total_data) {
2700 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2701 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2706 if (!lp_ea_support(SNUM(conn))) {
2707 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2711 /* Pull out the list of names. */
2712 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2719 *ppdata = (char *)SMB_REALLOC(
2720 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2721 if(*ppdata == NULL) {
2722 reply_nterror(req, NT_STATUS_NO_MEMORY);
2727 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2729 /* Realloc the params space */
2730 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2731 if(*pparams == NULL ) {
2732 reply_nterror(req, NT_STATUS_NO_MEMORY);
2738 /* Check that the dptr is valid */
2739 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2740 reply_nterror(req, STATUS_NO_MORE_FILES);
2744 directory = dptr_path(sconn, dptr_num);
2746 /* Get the wildcard mask from the dptr */
2747 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2748 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2749 reply_nterror(req, STATUS_NO_MORE_FILES);
2755 /* Get the attr mask from the dptr */
2756 dirtype = dptr_attr(sconn, dptr_num);
2758 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2759 dptr_num, mask, dirtype,
2761 dptr_TellDir(dirptr)));
2763 /* Initialize per TRANS2_FIND_NEXT operation data */
2764 dptr_init_search_op(dirptr);
2766 /* We don't need to check for VOL here as this is returned by
2767 a different TRANS2 call. */
2769 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2770 directory,lp_dontdescend(SNUM(conn))));
2771 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2772 dont_descend = True;
2775 space_remaining = max_data_bytes;
2776 out_of_space = False;
2779 * Seek to the correct position. We no longer use the resume key but
2780 * depend on the last file name instead.
2783 if(!continue_bit && resume_name && *resume_name) {
2786 long current_pos = 0;
2788 * Remember, name_to_8_3 is called by
2789 * get_lanman2_dir_entry(), so the resume name
2790 * could be mangled. Ensure we check the unmangled name.
2793 if (mangle_is_mangled(resume_name, conn->params)) {
2794 char *new_resume_name = NULL;
2795 mangle_lookup_name_from_8_3(ctx,
2799 if (new_resume_name) {
2800 resume_name = new_resume_name;
2805 * Fix for NT redirector problem triggered by resume key indexes
2806 * changing between directory scans. We now return a resume key of 0
2807 * and instead look for the filename to continue from (also given
2808 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2809 * findfirst/findnext (as is usual) then the directory pointer
2810 * should already be at the correct place.
2813 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2814 } /* end if resume_name && !continue_bit */
2816 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2817 bool got_exact_match = False;
2819 /* this is a heuristic to avoid seeking the dirptr except when
2820 absolutely necessary. It allows for a filename of about 40 chars */
2821 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2822 out_of_space = True;
2825 finished = !get_lanman2_dir_entry(ctx,
2829 mask,dirtype,info_level,
2830 requires_resume_key,dont_descend,
2833 space_remaining, &out_of_space,
2835 &last_entry_off, ea_list);
2838 if (finished && out_of_space)
2841 if (!finished && !out_of_space)
2845 * As an optimisation if we know we aren't looking
2846 * for a wildcard name (ie. the name matches the wildcard exactly)
2847 * then we can finish on any (first) match.
2848 * This speeds up large directory searches. JRA.
2854 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2857 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2858 smb_fn_name(req->cmd),
2859 mask, directory, dirtype, numentries ) );
2861 /* Check if we can close the dirptr */
2862 if(close_after_request || (finished && close_if_end)) {
2863 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2864 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2867 /* Set up the return parameter block */
2868 SSVAL(params,0,numentries);
2869 SSVAL(params,2,finished);
2870 SSVAL(params,4,0); /* Never an EA error */
2871 SSVAL(params,6,last_entry_off);
2873 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2879 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2881 E_md4hash(lp_servicename(SNUM(conn)),objid);
2885 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2887 SMB_ASSERT(extended_info != NULL);
2889 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2890 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2891 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2892 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2893 #ifdef SAMBA_VERSION_REVISION
2894 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2896 extended_info->samba_subversion = 0;
2897 #ifdef SAMBA_VERSION_RC_RELEASE
2898 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2900 #ifdef SAMBA_VERSION_PRE_RELEASE
2901 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2904 #ifdef SAMBA_VERSION_VENDOR_PATCH
2905 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2907 extended_info->samba_gitcommitdate = 0;
2908 #ifdef SAMBA_VERSION_COMMIT_TIME
2909 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2912 memset(extended_info->samba_version_string, 0,
2913 sizeof(extended_info->samba_version_string));
2915 snprintf (extended_info->samba_version_string,
2916 sizeof(extended_info->samba_version_string),
2917 "%s", samba_version_string());
2920 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2921 TALLOC_CTX *mem_ctx,
2922 uint16_t info_level,
2924 unsigned int max_data_bytes,
2928 char *pdata, *end_data;
2929 int data_len = 0, len;
2930 const char *vname = volume_label(SNUM(conn));
2931 int snum = SNUM(conn);
2932 char *fstype = lp_fstype(SNUM(conn));
2933 uint32 additional_flags = 0;
2934 struct smb_filename smb_fname_dot;
2938 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2939 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2940 "info level (0x%x) on IPC$.\n",
2941 (unsigned int)info_level));
2942 return NT_STATUS_ACCESS_DENIED;
2946 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2948 ZERO_STRUCT(smb_fname_dot);
2949 smb_fname_dot.base_name = discard_const_p(char, ".");
2951 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2952 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2953 return map_nt_error_from_unix(errno);
2956 st = smb_fname_dot.st;
2958 *ppdata = (char *)SMB_REALLOC(
2959 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2960 if (*ppdata == NULL) {
2961 return NT_STATUS_NO_MEMORY;
2965 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2966 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2968 switch (info_level) {
2969 case SMB_INFO_ALLOCATION:
2971 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2973 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2974 return map_nt_error_from_unix(errno);
2977 block_size = lp_block_size(snum);
2978 if (bsize < block_size) {
2979 uint64_t factor = block_size/bsize;
2984 if (bsize > block_size) {
2985 uint64_t factor = bsize/block_size;
2990 bytes_per_sector = 512;
2991 sectors_per_unit = bsize/bytes_per_sector;
2993 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2994 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2995 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2997 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2998 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2999 SIVAL(pdata,l1_cUnit,dsize);
3000 SIVAL(pdata,l1_cUnitAvail,dfree);
3001 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3005 case SMB_INFO_VOLUME:
3006 /* Return volume name */
3008 * Add volume serial number - hash of a combination of
3009 * the called hostname and the service name.
3011 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3013 * Win2k3 and previous mess this up by sending a name length
3014 * one byte short. I believe only older clients (OS/2 Win9x) use
3015 * this call so try fixing this by adding a terminating null to
3016 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3020 pdata+l2_vol_szVolLabel, vname,
3021 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3022 STR_NOALIGN|STR_TERMINATE);
3023 SCVAL(pdata,l2_vol_cch,len);
3024 data_len = l2_vol_szVolLabel + len;
3025 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3026 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3030 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3031 case SMB_FS_ATTRIBUTE_INFORMATION:
3033 additional_flags = 0;
3034 #if defined(HAVE_SYS_QUOTAS)
3035 additional_flags |= FILE_VOLUME_QUOTAS;
3038 if(lp_nt_acl_support(SNUM(conn))) {
3039 additional_flags |= FILE_PERSISTENT_ACLS;
3042 /* Capabilities are filled in at connection time through STATVFS call */
3043 additional_flags |= conn->fs_capabilities;
3044 additional_flags |= lp_parm_int(conn->params->service,
3045 "share", "fake_fscaps",
3048 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3049 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3050 additional_flags); /* FS ATTRIBUTES */
3052 SIVAL(pdata,4,255); /* Max filename component length */
3053 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3054 and will think we can't do long filenames */
3055 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3056 PTR_DIFF(end_data, pdata+12),
3059 data_len = 12 + len;
3062 case SMB_QUERY_FS_LABEL_INFO:
3063 case SMB_FS_LABEL_INFORMATION:
3064 len = srvstr_push(pdata, flags2, pdata+4, vname,
3065 PTR_DIFF(end_data, pdata+4), 0);
3070 case SMB_QUERY_FS_VOLUME_INFO:
3071 case SMB_FS_VOLUME_INFORMATION:
3074 * Add volume serial number - hash of a combination of
3075 * the called hostname and the service name.
3077 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3078 (str_checksum(get_local_machine_name())<<16));
3080 /* Max label len is 32 characters. */
3081 len = srvstr_push(pdata, flags2, pdata+18, vname,
3082 PTR_DIFF(end_data, pdata+18),
3084 SIVAL(pdata,12,len);
3087 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3088 (int)strlen(vname),vname, lp_servicename(snum)));
3091 case SMB_QUERY_FS_SIZE_INFO:
3092 case SMB_FS_SIZE_INFORMATION:
3094 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3096 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3097 return map_nt_error_from_unix(errno);
3099 block_size = lp_block_size(snum);
3100 if (bsize < block_size) {
3101 uint64_t factor = block_size/bsize;
3106 if (bsize > block_size) {
3107 uint64_t factor = bsize/block_size;
3112 bytes_per_sector = 512;
3113 sectors_per_unit = bsize/bytes_per_sector;
3114 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3115 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3116 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3117 SBIG_UINT(pdata,0,dsize);
3118 SBIG_UINT(pdata,8,dfree);
3119 SIVAL(pdata,16,sectors_per_unit);
3120 SIVAL(pdata,20,bytes_per_sector);
3124 case SMB_FS_FULL_SIZE_INFORMATION:
3126 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3128 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3129 return map_nt_error_from_unix(errno);
3131 block_size = lp_block_size(snum);
3132 if (bsize < block_size) {
3133 uint64_t factor = block_size/bsize;
3138 if (bsize > block_size) {
3139 uint64_t factor = bsize/block_size;
3144 bytes_per_sector = 512;
3145 sectors_per_unit = bsize/bytes_per_sector;
3146 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3147 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3148 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3149 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3150 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3151 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3152 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3153 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3157 case SMB_QUERY_FS_DEVICE_INFO:
3158 case SMB_FS_DEVICE_INFORMATION:
3160 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3162 if (!CAN_WRITE(conn)) {
3163 characteristics |= FILE_READ_ONLY_DEVICE;
3166 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3167 SIVAL(pdata,4,characteristics);
3171 #ifdef HAVE_SYS_QUOTAS
3172 case SMB_FS_QUOTA_INFORMATION:
3174 * what we have to send --metze:
3176 * Unknown1: 24 NULL bytes
3177 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3178 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3179 * Quota Flags: 2 byte :
3180 * Unknown3: 6 NULL bytes
3184 * details for Quota Flags:
3186 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3187 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3188 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3189 * 0x0001 Enable Quotas: enable quota for this fs
3193 /* we need to fake up a fsp here,
3194 * because its not send in this call
3197 SMB_NTQUOTA_STRUCT quotas;
3200 ZERO_STRUCT(quotas);
3206 if (get_current_uid(conn) != 0) {
3207 DEBUG(0,("set_user_quota: access_denied "
3208 "service [%s] user [%s]\n",
3209 lp_servicename(SNUM(conn)),
3210 conn->session_info->unix_name));
3211 return NT_STATUS_ACCESS_DENIED;
3214 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3215 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3216 return map_nt_error_from_unix(errno);
3221 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3222 lp_servicename(SNUM(conn))));
3224 /* Unknown1 24 NULL bytes*/
3225 SBIG_UINT(pdata,0,(uint64_t)0);
3226 SBIG_UINT(pdata,8,(uint64_t)0);
3227 SBIG_UINT(pdata,16,(uint64_t)0);
3229 /* Default Soft Quota 8 bytes */
3230 SBIG_UINT(pdata,24,quotas.softlim);
3232 /* Default Hard Quota 8 bytes */
3233 SBIG_UINT(pdata,32,quotas.hardlim);
3235 /* Quota flag 2 bytes */
3236 SSVAL(pdata,40,quotas.qflags);
3238 /* Unknown3 6 NULL bytes */
3244 #endif /* HAVE_SYS_QUOTAS */
3245 case SMB_FS_OBJECTID_INFORMATION:
3247 unsigned char objid[16];
3248 struct smb_extended_info extended_info;
3249 memcpy(pdata,create_volume_objectid(conn, objid),16);
3250 samba_extended_info_version (&extended_info);
3251 SIVAL(pdata,16,extended_info.samba_magic);
3252 SIVAL(pdata,20,extended_info.samba_version);
3253 SIVAL(pdata,24,extended_info.samba_subversion);
3254 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3255 memcpy(pdata+36,extended_info.samba_version_string,28);
3261 * Query the version and capabilities of the CIFS UNIX extensions
3265 case SMB_QUERY_CIFS_UNIX_INFO:
3267 bool large_write = lp_min_receive_file_size() &&
3268 !srv_is_signing_active(conn->sconn);
3269 bool large_read = !srv_is_signing_active(conn->sconn);
3270 int encrypt_caps = 0;
3272 if (!lp_unix_extensions()) {
3273 return NT_STATUS_INVALID_LEVEL;
3276 switch (conn->encrypt_level) {
3282 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3285 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3286 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3287 large_write = false;
3293 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3294 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3296 /* We have POSIX ACLs, pathname, encryption,
3297 * large read/write, and locking capability. */
3299 SBIG_UINT(pdata,4,((uint64_t)(
3300 CIFS_UNIX_POSIX_ACLS_CAP|
3301 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3302 CIFS_UNIX_FCNTL_LOCKS_CAP|
3303 CIFS_UNIX_EXTATTR_CAP|
3304 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3306 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3308 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3312 case SMB_QUERY_POSIX_FS_INFO:
3315 vfs_statvfs_struct svfs;
3317 if (!lp_unix_extensions()) {
3318 return NT_STATUS_INVALID_LEVEL;
3321 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3325 SIVAL(pdata,0,svfs.OptimalTransferSize);
3326 SIVAL(pdata,4,svfs.BlockSize);
3327 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3328 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3329 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3330 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3331 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3332 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3333 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3335 } else if (rc == EOPNOTSUPP) {
3336 return NT_STATUS_INVALID_LEVEL;
3337 #endif /* EOPNOTSUPP */
3339 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3340 return NT_STATUS_DOS(ERRSRV, ERRerror);
3345 case SMB_QUERY_POSIX_WHOAMI:
3351 if (!lp_unix_extensions()) {
3352 return NT_STATUS_INVALID_LEVEL;
3355 if (max_data_bytes < 40) {
3356 return NT_STATUS_BUFFER_TOO_SMALL;
3359 /* We ARE guest if global_sid_Builtin_Guests is
3360 * in our list of SIDs.
3362 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3363 conn->session_info->security_token)) {
3364 flags |= SMB_WHOAMI_GUEST;
3367 /* We are NOT guest if global_sid_Authenticated_Users
3368 * is in our list of SIDs.
3370 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3371 conn->session_info->security_token)) {
3372 flags &= ~SMB_WHOAMI_GUEST;
3375 /* NOTE: 8 bytes for UID/GID, irrespective of native
3376 * platform size. This matches
3377 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3379 data_len = 4 /* flags */
3386 + 4 /* pad/reserved */
3387 + (conn->session_info->utok.ngroups * 8)
3389 + (conn->session_info->security_token->num_sids *
3393 SIVAL(pdata, 0, flags);
3394 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3396 (uint64_t)conn->session_info->utok.uid);
3397 SBIG_UINT(pdata, 16,
3398 (uint64_t)conn->session_info->utok.gid);
3401 if (data_len >= max_data_bytes) {
3402 /* Potential overflow, skip the GIDs and SIDs. */
3404 SIVAL(pdata, 24, 0); /* num_groups */
3405 SIVAL(pdata, 28, 0); /* num_sids */
3406 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3407 SIVAL(pdata, 36, 0); /* reserved */
3413 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3414 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3416 /* We walk the SID list twice, but this call is fairly
3417 * infrequent, and I don't expect that it's performance
3418 * sensitive -- jpeach
3420 for (i = 0, sid_bytes = 0;
3421 i < conn->session_info->security_token->num_sids; ++i) {
3422 sid_bytes += ndr_size_dom_sid(
3423 &conn->session_info->security_token->sids[i],
3427 /* SID list byte count */
3428 SIVAL(pdata, 32, sid_bytes);
3430 /* 4 bytes pad/reserved - must be zero */
3431 SIVAL(pdata, 36, 0);
3435 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3436 SBIG_UINT(pdata, data_len,
3437 (uint64_t)conn->session_info->utok.groups[i]);
3443 i < conn->session_info->security_token->num_sids; ++i) {
3444 int sid_len = ndr_size_dom_sid(
3445 &conn->session_info->security_token->sids[i],
3448 sid_linearize(pdata + data_len, sid_len,
3449 &conn->session_info->security_token->sids[i]);
3450 data_len += sid_len;
3456 case SMB_MAC_QUERY_FS_INFO:
3458 * Thursby MAC extension... ONLY on NTFS filesystems
3459 * once we do streams then we don't need this
3461 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3463 SIVAL(pdata,84,0x100); /* Don't support mac... */
3468 return NT_STATUS_INVALID_LEVEL;
3471 *ret_data_len = data_len;
3472 return NT_STATUS_OK;
3475 /****************************************************************************
3476 Reply to a TRANS2_QFSINFO (query filesystem info).
3477 ****************************************************************************/
3479 static void call_trans2qfsinfo(connection_struct *conn,
3480 struct smb_request *req,
3481 char **pparams, int total_params,
3482 char **ppdata, int total_data,
3483 unsigned int max_data_bytes)
3485 char *params = *pparams;
3486 uint16_t info_level;
3490 if (total_params < 2) {
3491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3495 info_level = SVAL(params,0);
3497 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3498 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3499 DEBUG(0,("call_trans2qfsinfo: encryption required "
3500 "and info level 0x%x sent.\n",
3501 (unsigned int)info_level));
3502 exit_server_cleanly("encryption required "
3508 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3510 status = smbd_do_qfsinfo(conn, req,
3515 if (!NT_STATUS_IS_OK(status)) {
3516 reply_nterror(req, status);
3520 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3523 DEBUG( 4, ( "%s info_level = %d\n",
3524 smb_fn_name(req->cmd), info_level) );
3529 /****************************************************************************
3530 Reply to a TRANS2_SETFSINFO (set filesystem info).
3531 ****************************************************************************/
3533 static void call_trans2setfsinfo(connection_struct *conn,
3534 struct smb_request *req,
3535 char **pparams, int total_params,
3536 char **ppdata, int total_data,
3537 unsigned int max_data_bytes)
3539 char *pdata = *ppdata;
3540 char *params = *pparams;
3543 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3546 if (total_params < 4) {
3547 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3553 info_level = SVAL(params,2);
3556 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3557 info_level != SMB_SET_CIFS_UNIX_INFO) {
3558 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3559 "info level (0x%x) on IPC$.\n",
3560 (unsigned int)info_level));
3561 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3566 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3567 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3568 DEBUG(0,("call_trans2setfsinfo: encryption required "
3569 "and info level 0x%x sent.\n",
3570 (unsigned int)info_level));
3571 exit_server_cleanly("encryption required "
3577 switch(info_level) {
3578 case SMB_SET_CIFS_UNIX_INFO:
3580 uint16 client_unix_major;
3581 uint16 client_unix_minor;
3582 uint32 client_unix_cap_low;
3583 uint32 client_unix_cap_high;
3585 if (!lp_unix_extensions()) {
3587 NT_STATUS_INVALID_LEVEL);
3591 /* There should be 12 bytes of capabilities set. */
3592 if (total_data < 8) {
3595 NT_STATUS_INVALID_PARAMETER);
3598 client_unix_major = SVAL(pdata,0);
3599 client_unix_minor = SVAL(pdata,2);
3600 client_unix_cap_low = IVAL(pdata,4);
3601 client_unix_cap_high = IVAL(pdata,8);
3602 /* Just print these values for now. */
3603 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3604 cap_low = 0x%x, cap_high = 0x%x\n",
3605 (unsigned int)client_unix_major,
3606 (unsigned int)client_unix_minor,
3607 (unsigned int)client_unix_cap_low,
3608 (unsigned int)client_unix_cap_high ));
3610 /* Here is where we must switch to posix pathname processing... */
3611 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3612 lp_set_posix_pathnames();
3613 mangle_change_to_posix();
3616 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3617 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3618 /* Client that knows how to do posix locks,
3619 * but not posix open/mkdir operations. Set a
3620 * default type for read/write checks. */
3622 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3628 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3631 size_t param_len = 0;
3632 size_t data_len = total_data;
3634 if (!lp_unix_extensions()) {
3637 NT_STATUS_INVALID_LEVEL);
3641 if (lp_smb_encrypt(SNUM(conn)) == false) {
3644 NT_STATUS_NOT_SUPPORTED);
3648 if (req->sconn->smb1.echo_handler.trusted_fde) {
3649 DEBUG( 2,("call_trans2setfsinfo: "
3650 "request transport encryption disabled"
3651 "with 'fork echo handler = yes'\n"));
3654 NT_STATUS_NOT_SUPPORTED);
3658 DEBUG( 4,("call_trans2setfsinfo: "
3659 "request transport encryption.\n"));
3661 status = srv_request_encryption_setup(conn,
3662 (unsigned char **)ppdata,
3664 (unsigned char **)pparams,
3667 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3668 !NT_STATUS_IS_OK(status)) {
3669 reply_nterror(req, status);
3673 send_trans2_replies(conn, req,
3680 if (NT_STATUS_IS_OK(status)) {
3681 /* Server-side transport
3682 * encryption is now *on*. */
3683 status = srv_encryption_start(conn);
3684 if (!NT_STATUS_IS_OK(status)) {
3685 exit_server_cleanly(
3686 "Failure in setting "
3687 "up encrypted transport");
3693 case SMB_FS_QUOTA_INFORMATION:
3695 files_struct *fsp = NULL;
3696 SMB_NTQUOTA_STRUCT quotas;
3698 ZERO_STRUCT(quotas);
3701 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3702 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3703 lp_servicename(SNUM(conn)),
3704 conn->session_info->unix_name));
3705 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3709 /* note: normaly there're 48 bytes,
3710 * but we didn't use the last 6 bytes for now
3713 fsp = file_fsp(req, SVAL(params,0));
3715 if (!check_fsp_ntquota_handle(conn, req,
3717 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3719 req, NT_STATUS_INVALID_HANDLE);
3723 if (total_data < 42) {
3724 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3728 NT_STATUS_INVALID_PARAMETER);
3732 /* unknown_1 24 NULL bytes in pdata*/
3734 /* the soft quotas 8 bytes (uint64_t)*/
3735 quotas.softlim = (uint64_t)IVAL(pdata,24);
3736 #ifdef LARGE_SMB_OFF_T
3737 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3738 #else /* LARGE_SMB_OFF_T */
3739 if ((IVAL(pdata,28) != 0)&&
3740 ((quotas.softlim != 0xFFFFFFFF)||
3741 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3742 /* more than 32 bits? */
3745 NT_STATUS_INVALID_PARAMETER);
3748 #endif /* LARGE_SMB_OFF_T */
3750 /* the hard quotas 8 bytes (uint64_t)*/
3751 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3752 #ifdef LARGE_SMB_OFF_T
3753 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3754 #else /* LARGE_SMB_OFF_T */
3755 if ((IVAL(pdata,36) != 0)&&
3756 ((quotas.hardlim != 0xFFFFFFFF)||
3757 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3758 /* more than 32 bits? */
3761 NT_STATUS_INVALID_PARAMETER);
3764 #endif /* LARGE_SMB_OFF_T */
3766 /* quota_flags 2 bytes **/
3767 quotas.qflags = SVAL(pdata,40);
3769 /* unknown_2 6 NULL bytes follow*/
3771 /* now set the quotas */
3772 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3773 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3774 reply_nterror(req, map_nt_error_from_unix(errno));
3781 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3783 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3789 * sending this reply works fine,
3790 * but I'm not sure it's the same
3791 * like windows do...
3794 reply_outbuf(req, 10, 0);
3797 #if defined(HAVE_POSIX_ACLS)
3798 /****************************************************************************
3799 Utility function to count the number of entries in a POSIX acl.
3800 ****************************************************************************/
3802 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3804 unsigned int ace_count = 0;
3805 int entry_id = SMB_ACL_FIRST_ENTRY;
3806 SMB_ACL_ENTRY_T entry;
3808 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3810 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3811 entry_id = SMB_ACL_NEXT_ENTRY;
3818 /****************************************************************************
3819 Utility function to marshall a POSIX acl into wire format.
3820 ****************************************************************************/
3822 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3824 int entry_id = SMB_ACL_FIRST_ENTRY;
3825 SMB_ACL_ENTRY_T entry;
3827 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3828 SMB_ACL_TAG_T tagtype;
3829 SMB_ACL_PERMSET_T permset;
3830 unsigned char perms = 0;
3831 unsigned int own_grp;
3834 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3835 entry_id = SMB_ACL_NEXT_ENTRY;
3838 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3839 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3843 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3844 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3848 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3849 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3850 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3852 SCVAL(pdata,1,perms);
3855 case SMB_ACL_USER_OBJ:
3856 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3857 own_grp = (unsigned int)pst->st_ex_uid;
3858 SIVAL(pdata,2,own_grp);
3863 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3865 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3868 own_grp = (unsigned int)*puid;
3869 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3870 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3871 SIVAL(pdata,2,own_grp);
3875 case SMB_ACL_GROUP_OBJ:
3876 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3877 own_grp = (unsigned int)pst->st_ex_gid;
3878 SIVAL(pdata,2,own_grp);
3883 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3885 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3888 own_grp = (unsigned int)*pgid;
3889 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3890 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3891 SIVAL(pdata,2,own_grp);
3896 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3897 SIVAL(pdata,2,0xFFFFFFFF);
3898 SIVAL(pdata,6,0xFFFFFFFF);
3901 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3902 SIVAL(pdata,2,0xFFFFFFFF);
3903 SIVAL(pdata,6,0xFFFFFFFF);
3906 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3909 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3916 /****************************************************************************
3917 Store the FILE_UNIX_BASIC info.
3918 ****************************************************************************/
3920 static char *store_file_unix_basic(connection_struct *conn,
3923 const SMB_STRUCT_STAT *psbuf)
3925 uint64_t file_index = get_FileIndex(conn, psbuf);
3927 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3928 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3930 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3933 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3936 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3937 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3938 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3941 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3945 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3949 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3952 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3956 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3960 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3963 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3967 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3974 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3975 * the chflags(2) (or equivalent) flags.
3977 * XXX: this really should be behind the VFS interface. To do this, we would
3978 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3979 * Each VFS module could then implement its own mapping as appropriate for the
3980 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3982 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3986 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3990 { UF_IMMUTABLE, EXT_IMMUTABLE },
3994 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3998 { UF_HIDDEN, EXT_HIDDEN },
4001 /* Do not remove. We need to guarantee that this array has at least one
4002 * entry to build on HP-UX.
4008 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4009 uint32 *smb_fflags, uint32 *smb_fmask)
4013 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4014 *smb_fmask |= info2_flags_map[i].smb_fflag;
4015 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4016 *smb_fflags |= info2_flags_map[i].smb_fflag;
4021 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4022 const uint32 smb_fflags,
4023 const uint32 smb_fmask,
4026 uint32 max_fmask = 0;
4029 *stat_fflags = psbuf->st_ex_flags;
4031 /* For each flags requested in smb_fmask, check the state of the
4032 * corresponding flag in smb_fflags and set or clear the matching
4036 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4037 max_fmask |= info2_flags_map[i].smb_fflag;
4038 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4039 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4040 *stat_fflags |= info2_flags_map[i].stat_fflag;
4042 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4047 /* If smb_fmask is asking to set any bits that are not supported by
4048 * our flag mappings, we should fail.
4050 if ((smb_fmask & max_fmask) != smb_fmask) {
4058 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4059 * of file flags and birth (create) time.
4061 static char *store_file_unix_basic_info2(connection_struct *conn,
4064 const SMB_STRUCT_STAT *psbuf)
4066 uint32 file_flags = 0;
4067 uint32 flags_mask = 0;
4069 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4071 /* Create (birth) time 64 bit */
4072 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4075 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4076 SIVAL(pdata, 0, file_flags); /* flags */
4077 SIVAL(pdata, 4, flags_mask); /* mask */
4083 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4084 const struct stream_struct *streams,
4086 unsigned int max_data_bytes,
4087 unsigned int *data_size)
4090 unsigned int ofs = 0;
4092 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4093 unsigned int next_offset;
4095 smb_ucs2_t *namebuf;
4097 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4098 streams[i].name, &namelen) ||
4101 return NT_STATUS_INVALID_PARAMETER;
4105 * name_buf is now null-terminated, we need to marshall as not
4111 SIVAL(data, ofs+4, namelen);
4112 SOFF_T(data, ofs+8, streams[i].size);
4113 SOFF_T(data, ofs+16, streams[i].alloc_size);
4114 memcpy(data+ofs+24, namebuf, namelen);
4115 TALLOC_FREE(namebuf);
4117 next_offset = ofs + 24 + namelen;
4119 if (i == num_streams-1) {
4120 SIVAL(data, ofs, 0);
4123 unsigned int align = ndr_align_size(next_offset, 8);
4125 memset(data+next_offset, 0, align);
4126 next_offset += align;
4128 SIVAL(data, ofs, next_offset - ofs);
4137 return NT_STATUS_OK;
4140 /****************************************************************************
4141 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4142 ****************************************************************************/
4144 static void call_trans2qpipeinfo(connection_struct *conn,
4145 struct smb_request *req,
4146 unsigned int tran_call,
4147 char **pparams, int total_params,
4148 char **ppdata, int total_data,
4149 unsigned int max_data_bytes)
4151 char *params = *pparams;
4152 char *pdata = *ppdata;
4153 unsigned int data_size = 0;
4154 unsigned int param_size = 2;
4159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4163 if (total_params < 4) {
4164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4168 fsp = file_fsp(req, SVAL(params,0));
4169 if (!fsp_is_np(fsp)) {
4170 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4174 info_level = SVAL(params,2);
4176 *pparams = (char *)SMB_REALLOC(*pparams,2);
4177 if (*pparams == NULL) {
4178 reply_nterror(req, NT_STATUS_NO_MEMORY);
4183 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4184 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4185 if (*ppdata == NULL ) {
4186 reply_nterror(req, NT_STATUS_NO_MEMORY);
4191 switch (info_level) {
4192 case SMB_FILE_STANDARD_INFORMATION:
4194 SOFF_T(pdata,0,4096LL);
4201 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4205 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4211 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4212 TALLOC_CTX *mem_ctx,
4213 uint16_t info_level,
4215 struct smb_filename *smb_fname,
4216 bool delete_pending,
4217 struct timespec write_time_ts,
4218 struct ea_list *ea_list,
4219 int lock_data_count,
4222 unsigned int max_data_bytes,
4224 unsigned int *pdata_size)
4226 char *pdata = *ppdata;
4227 char *dstart, *dend;
4228 unsigned int data_size;
4229 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4230 time_t create_time, mtime, atime, c_time;
4231 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4238 uint64_t file_size = 0;
4240 uint64_t allocation_size = 0;
4241 uint64_t file_index = 0;
4242 uint32_t access_mask = 0;
4244 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4245 return NT_STATUS_INVALID_LEVEL;
4248 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4249 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4250 info_level, max_data_bytes));
4252 mode = dos_mode(conn, smb_fname);
4253 nlink = psbuf->st_ex_nlink;
4255 if (nlink && (mode&aDIR)) {
4259 if ((nlink > 0) && delete_pending) {
4263 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4264 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4265 if (*ppdata == NULL) {
4266 return NT_STATUS_NO_MEMORY;
4270 dend = dstart + data_size - 1;
4272 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4273 update_stat_ex_mtime(psbuf, write_time_ts);
4276 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4277 mtime_ts = psbuf->st_ex_mtime;
4278 atime_ts = psbuf->st_ex_atime;
4279 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4281 if (lp_dos_filetime_resolution(SNUM(conn))) {
4282 dos_filetime_timespec(&create_time_ts);
4283 dos_filetime_timespec(&mtime_ts);
4284 dos_filetime_timespec(&atime_ts);
4285 dos_filetime_timespec(&ctime_ts);
4288 create_time = convert_timespec_to_time_t(create_time_ts);
4289 mtime = convert_timespec_to_time_t(mtime_ts);
4290 atime = convert_timespec_to_time_t(atime_ts);
4291 c_time = convert_timespec_to_time_t(ctime_ts);
4293 p = strrchr_m(smb_fname->base_name,'/');
4295 base_name = smb_fname->base_name;
4299 /* NT expects the name to be in an exact form of the *full*
4300 filename. See the trans2 torture test */
4301 if (ISDOT(base_name)) {
4302 dos_fname = talloc_strdup(mem_ctx, "\\");
4304 return NT_STATUS_NO_MEMORY;
4307 dos_fname = talloc_asprintf(mem_ctx,
4309 smb_fname->base_name);
4311 return NT_STATUS_NO_MEMORY;
4313 if (is_ntfs_stream_smb_fname(smb_fname)) {
4314 dos_fname = talloc_asprintf(dos_fname, "%s",
4315 smb_fname->stream_name);
4317 return NT_STATUS_NO_MEMORY;
4321 string_replace(dos_fname, '/', '\\');
4324 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4327 /* Do we have this path open ? */
4329 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4330 fsp1 = file_find_di_first(conn->sconn, fileid);
4331 if (fsp1 && fsp1->initial_allocation_size) {
4332 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4336 if (!(mode & aDIR)) {
4337 file_size = get_file_size_stat(psbuf);
4341 pos = fsp->fh->position_information;
4345 access_mask = fsp->access_mask;
4347 /* GENERIC_EXECUTE mapping from Windows */
4348 access_mask = 0x12019F;
4351 /* This should be an index number - looks like
4354 I think this causes us to fail the IFSKIT
4355 BasicFileInformationTest. -tpot */
4356 file_index = get_FileIndex(conn, psbuf);
4358 switch (info_level) {
4359 case SMB_INFO_STANDARD:
4360 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4362 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4363 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4364 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4365 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4366 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4367 SSVAL(pdata,l1_attrFile,mode);
4370 case SMB_INFO_QUERY_EA_SIZE:
4372 unsigned int ea_size =
4373 estimate_ea_size(conn, fsp,
4374 smb_fname->base_name);
4375 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4377 srv_put_dos_date2(pdata,0,create_time);
4378 srv_put_dos_date2(pdata,4,atime);
4379 srv_put_dos_date2(pdata,8,mtime); /* write time */
4380 SIVAL(pdata,12,(uint32)file_size);
4381 SIVAL(pdata,16,(uint32)allocation_size);
4382 SSVAL(pdata,20,mode);
4383 SIVAL(pdata,22,ea_size);
4387 case SMB_INFO_IS_NAME_VALID:
4388 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4390 /* os/2 needs this ? really ?*/
4391 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4393 /* This is only reached for qpathinfo */
4397 case SMB_INFO_QUERY_EAS_FROM_LIST:
4399 size_t total_ea_len = 0;
4400 struct ea_list *ea_file_list = NULL;
4402 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4405 get_ea_list_from_file(mem_ctx, conn, fsp,
4406 smb_fname->base_name,
4408 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4410 if (!ea_list || (total_ea_len > data_size)) {
4412 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4416 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4420 case SMB_INFO_QUERY_ALL_EAS:
4422 /* We have data_size bytes to put EA's into. */
4423 size_t total_ea_len = 0;
4425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4427 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4428 smb_fname->base_name,
4430 if (!ea_list || (total_ea_len > data_size)) {
4432 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4436 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4440 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4442 /* This is FileFullEaInformation - 0xF which maps to
4443 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4445 /* We have data_size bytes to put EA's into. */
4446 size_t total_ea_len = 0;
4447 struct ea_list *ea_file_list = NULL;
4449 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4451 /*TODO: add filtering and index handling */
4454 get_ea_list_from_file(mem_ctx, conn, fsp,
4455 smb_fname->base_name,
4457 if (!ea_file_list) {
4458 return NT_STATUS_NO_EAS_ON_FILE;
4461 status = fill_ea_chained_buffer(mem_ctx,
4465 conn, ea_file_list);
4466 if (!NT_STATUS_IS_OK(status)) {
4472 case SMB_FILE_BASIC_INFORMATION:
4473 case SMB_QUERY_FILE_BASIC_INFO:
4475 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4477 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4479 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4483 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4484 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4485 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4486 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4487 SIVAL(pdata,32,mode);
4489 DEBUG(5,("SMB_QFBI - "));
4490 DEBUG(5,("create: %s ", ctime(&create_time)));
4491 DEBUG(5,("access: %s ", ctime(&atime)));
4492 DEBUG(5,("write: %s ", ctime(&mtime)));
4493 DEBUG(5,("change: %s ", ctime(&c_time)));
4494 DEBUG(5,("mode: %x\n", mode));
4497 case SMB_FILE_STANDARD_INFORMATION:
4498 case SMB_QUERY_FILE_STANDARD_INFO:
4500 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4502 SOFF_T(pdata,0,allocation_size);
4503 SOFF_T(pdata,8,file_size);
4504 SIVAL(pdata,16,nlink);
4505 SCVAL(pdata,20,delete_pending?1:0);
4506 SCVAL(pdata,21,(mode&aDIR)?1:0);
4507 SSVAL(pdata,22,0); /* Padding. */
4510 case SMB_FILE_EA_INFORMATION:
4511 case SMB_QUERY_FILE_EA_INFO:
4513 unsigned int ea_size =
4514 estimate_ea_size(conn, fsp, smb_fname->base_name);
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4517 SIVAL(pdata,0,ea_size);
4521 /* Get the 8.3 name - used if NT SMB was negotiated. */
4522 case SMB_QUERY_FILE_ALT_NAME_INFO:
4523 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4526 char mangled_name[13];
4527 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4528 if (!name_to_8_3(base_name,mangled_name,
4529 True,conn->params)) {
4530 return NT_STATUS_NO_MEMORY;
4532 len = srvstr_push(dstart, flags2,
4533 pdata+4, mangled_name,
4534 PTR_DIFF(dend, pdata+4),
4536 data_size = 4 + len;
4541 case SMB_QUERY_FILE_NAME_INFO:
4545 this must be *exactly* right for ACLs on mapped drives to work
4547 len = srvstr_push(dstart, flags2,
4549 PTR_DIFF(dend, pdata+4),
4551 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4552 data_size = 4 + len;
4557 case SMB_FILE_ALLOCATION_INFORMATION:
4558 case SMB_QUERY_FILE_ALLOCATION_INFO:
4559 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4561 SOFF_T(pdata,0,allocation_size);
4564 case SMB_FILE_END_OF_FILE_INFORMATION:
4565 case SMB_QUERY_FILE_END_OF_FILEINFO:
4566 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4568 SOFF_T(pdata,0,file_size);
4571 case SMB_QUERY_FILE_ALL_INFO:
4572 case SMB_FILE_ALL_INFORMATION:
4575 unsigned int ea_size =
4576 estimate_ea_size(conn, fsp, smb_fname->base_name);
4577 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4578 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4579 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4580 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4581 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4582 SIVAL(pdata,32,mode);
4583 SIVAL(pdata,36,0); /* padding. */
4585 SOFF_T(pdata,0,allocation_size);
4586 SOFF_T(pdata,8,file_size);
4587 SIVAL(pdata,16,nlink);
4588 SCVAL(pdata,20,delete_pending);
4589 SCVAL(pdata,21,(mode&aDIR)?1:0);
4592 SIVAL(pdata,0,ea_size);
4593 pdata += 4; /* EA info */
4594 len = srvstr_push(dstart, flags2,
4596 PTR_DIFF(dend, pdata+4),
4600 data_size = PTR_DIFF(pdata,(*ppdata));
4604 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4607 unsigned int ea_size =
4608 estimate_ea_size(conn, fsp, smb_fname->base_name);
4609 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4610 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4611 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4612 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4613 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4614 SIVAL(pdata, 0x20, mode);
4615 SIVAL(pdata, 0x24, 0); /* padding. */
4616 SBVAL(pdata, 0x28, allocation_size);
4617 SBVAL(pdata, 0x30, file_size);
4618 SIVAL(pdata, 0x38, nlink);
4619 SCVAL(pdata, 0x3C, delete_pending);
4620 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4621 SSVAL(pdata, 0x3E, 0); /* padding */
4622 SBVAL(pdata, 0x40, file_index);
4623 SIVAL(pdata, 0x48, ea_size);
4624 SIVAL(pdata, 0x4C, access_mask);
4625 SBVAL(pdata, 0x50, pos);
4626 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4627 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4631 len = srvstr_push(dstart, flags2,
4633 PTR_DIFF(dend, pdata+4),
4637 data_size = PTR_DIFF(pdata,(*ppdata));
4640 case SMB_FILE_INTERNAL_INFORMATION:
4642 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4643 SBVAL(pdata, 0, file_index);
4647 case SMB_FILE_ACCESS_INFORMATION:
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4649 SIVAL(pdata, 0, access_mask);
4653 case SMB_FILE_NAME_INFORMATION:
4654 /* Pathname with leading '\'. */
4657 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4658 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4659 SIVAL(pdata,0,byte_len);
4660 data_size = 4 + byte_len;
4664 case SMB_FILE_DISPOSITION_INFORMATION:
4665 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4667 SCVAL(pdata,0,delete_pending);
4670 case SMB_FILE_POSITION_INFORMATION:
4671 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4673 SOFF_T(pdata,0,pos);
4676 case SMB_FILE_MODE_INFORMATION:
4677 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4678 SIVAL(pdata,0,mode);
4682 case SMB_FILE_ALIGNMENT_INFORMATION:
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4684 SIVAL(pdata,0,0); /* No alignment needed. */
4689 * NT4 server just returns "invalid query" to this - if we try
4690 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4693 /* The first statement above is false - verified using Thursby
4694 * client against NT4 -- gcolley.
4696 case SMB_QUERY_FILE_STREAM_INFO:
4697 case SMB_FILE_STREAM_INFORMATION: {
4698 unsigned int num_streams;
4699 struct stream_struct *streams;
4701 DEBUG(10,("smbd_do_qfilepathinfo: "
4702 "SMB_FILE_STREAM_INFORMATION\n"));
4704 if (is_ntfs_stream_smb_fname(smb_fname)) {
4705 return NT_STATUS_INVALID_PARAMETER;
4708 status = SMB_VFS_STREAMINFO(
4709 conn, fsp, smb_fname->base_name, talloc_tos(),
4710 &num_streams, &streams);
4712 if (!NT_STATUS_IS_OK(status)) {
4713 DEBUG(10, ("could not get stream info: %s\n",
4714 nt_errstr(status)));
4718 status = marshall_stream_info(num_streams, streams,
4719 pdata, max_data_bytes,
4722 if (!NT_STATUS_IS_OK(status)) {
4723 DEBUG(10, ("marshall_stream_info failed: %s\n",
4724 nt_errstr(status)));
4728 TALLOC_FREE(streams);
4732 case SMB_QUERY_COMPRESSION_INFO:
4733 case SMB_FILE_COMPRESSION_INFORMATION:
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4735 SOFF_T(pdata,0,file_size);
4736 SIVAL(pdata,8,0); /* ??? */
4737 SIVAL(pdata,12,0); /* ??? */
4741 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4742 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4743 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4744 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4745 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4746 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4747 SOFF_T(pdata,32,allocation_size);
4748 SOFF_T(pdata,40,file_size);
4749 SIVAL(pdata,48,mode);
4750 SIVAL(pdata,52,0); /* ??? */
4754 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4756 SIVAL(pdata,0,mode);
4762 * CIFS UNIX Extensions.
4765 case SMB_QUERY_FILE_UNIX_BASIC:
4767 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4768 data_size = PTR_DIFF(pdata,(*ppdata));
4770 DEBUG(4,("smbd_do_qfilepathinfo: "
4771 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4772 dump_data(4, (uint8_t *)(*ppdata), data_size);
4776 case SMB_QUERY_FILE_UNIX_INFO2:
4778 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4779 data_size = PTR_DIFF(pdata,(*ppdata));
4783 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4785 for (i=0; i<100; i++)
4786 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4792 case SMB_QUERY_FILE_UNIX_LINK:
4795 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4798 return NT_STATUS_NO_MEMORY;
4801 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4803 if(!S_ISLNK(psbuf->st_ex_mode)) {
4804 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4807 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4809 len = SMB_VFS_READLINK(conn,
4810 smb_fname->base_name,
4813 return map_nt_error_from_unix(errno);
4816 len = srvstr_push(dstart, flags2,
4818 PTR_DIFF(dend, pdata),
4821 data_size = PTR_DIFF(pdata,(*ppdata));
4826 #if defined(HAVE_POSIX_ACLS)
4827 case SMB_QUERY_POSIX_ACL:
4829 SMB_ACL_T file_acl = NULL;
4830 SMB_ACL_T def_acl = NULL;
4831 uint16 num_file_acls = 0;
4832 uint16 num_def_acls = 0;
4834 if (fsp && fsp->fh->fd != -1) {
4835 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4838 SMB_VFS_SYS_ACL_GET_FILE(conn,
4839 smb_fname->base_name,
4840 SMB_ACL_TYPE_ACCESS);
4843 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4844 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4845 "not implemented on "
4846 "filesystem containing %s\n",
4847 smb_fname->base_name));
4848 return NT_STATUS_NOT_IMPLEMENTED;
4851 if (S_ISDIR(psbuf->st_ex_mode)) {
4852 if (fsp && fsp->is_directory) {
4854 SMB_VFS_SYS_ACL_GET_FILE(
4856 fsp->fsp_name->base_name,
4857 SMB_ACL_TYPE_DEFAULT);
4860 SMB_VFS_SYS_ACL_GET_FILE(
4862 smb_fname->base_name,
4863 SMB_ACL_TYPE_DEFAULT);
4865 def_acl = free_empty_sys_acl(conn, def_acl);
4868 num_file_acls = count_acl_entries(conn, file_acl);
4869 num_def_acls = count_acl_entries(conn, def_acl);
4871 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4872 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4874 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4875 SMB_POSIX_ACL_HEADER_SIZE) ));
4877 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4880 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4882 return NT_STATUS_BUFFER_TOO_SMALL;
4885 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4886 SSVAL(pdata,2,num_file_acls);
4887 SSVAL(pdata,4,num_def_acls);
4888 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4890 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4893 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4895 return NT_STATUS_INTERNAL_ERROR;
4897 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4899 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4902 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4904 return NT_STATUS_INTERNAL_ERROR;
4908 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4911 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4913 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4919 case SMB_QUERY_POSIX_LOCK:
4924 enum brl_type lock_type;
4926 /* We need an open file with a real fd for this. */
4927 if (!fsp || fsp->fh->fd == -1) {
4928 return NT_STATUS_INVALID_LEVEL;
4931 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4932 return NT_STATUS_INVALID_PARAMETER;
4935 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4936 case POSIX_LOCK_TYPE_READ:
4937 lock_type = READ_LOCK;
4939 case POSIX_LOCK_TYPE_WRITE:
4940 lock_type = WRITE_LOCK;
4942 case POSIX_LOCK_TYPE_UNLOCK:
4944 /* There's no point in asking for an unlock... */
4945 return NT_STATUS_INVALID_PARAMETER;
4948 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4949 #if defined(HAVE_LONGLONG)
4950 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4951 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4952 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4953 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4954 #else /* HAVE_LONGLONG */
4955 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4956 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4957 #endif /* HAVE_LONGLONG */
4959 status = query_lock(fsp,
4966 if (ERROR_WAS_LOCK_DENIED(status)) {
4967 /* Here we need to report who has it locked... */
4968 data_size = POSIX_LOCK_DATA_SIZE;
4970 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4971 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4972 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4973 #if defined(HAVE_LONGLONG)
4974 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4975 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4976 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4977 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4978 #else /* HAVE_LONGLONG */
4979 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4980 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4981 #endif /* HAVE_LONGLONG */
4983 } else if (NT_STATUS_IS_OK(status)) {
4984 /* For success we just return a copy of what we sent
4985 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4986 data_size = POSIX_LOCK_DATA_SIZE;
4987 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4988 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4996 return NT_STATUS_INVALID_LEVEL;
4999 *pdata_size = data_size;
5000 return NT_STATUS_OK;
5003 /****************************************************************************
5004 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5005 file name or file id).
5006 ****************************************************************************/
5008 static void call_trans2qfilepathinfo(connection_struct *conn,
5009 struct smb_request *req,
5010 unsigned int tran_call,
5011 char **pparams, int total_params,
5012 char **ppdata, int total_data,
5013 unsigned int max_data_bytes)
5015 char *params = *pparams;
5016 char *pdata = *ppdata;
5018 unsigned int data_size = 0;
5019 unsigned int param_size = 2;
5020 struct smb_filename *smb_fname = NULL;
5021 bool delete_pending = False;
5022 struct timespec write_time_ts;
5023 files_struct *fsp = NULL;
5024 struct file_id fileid;
5025 struct ea_list *ea_list = NULL;
5026 int lock_data_count = 0;
5027 char *lock_data = NULL;
5028 NTSTATUS status = NT_STATUS_OK;
5031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5035 ZERO_STRUCT(write_time_ts);
5037 if (tran_call == TRANSACT2_QFILEINFO) {
5038 if (total_params < 4) {
5039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5044 call_trans2qpipeinfo(conn, req, tran_call,
5045 pparams, total_params,
5051 fsp = file_fsp(req, SVAL(params,0));
5052 info_level = SVAL(params,2);
5054 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5056 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5057 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5061 /* Initial check for valid fsp ptr. */
5062 if (!check_fsp_open(conn, req, fsp)) {
5066 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5068 if (!NT_STATUS_IS_OK(status)) {
5069 reply_nterror(req, status);
5073 if(fsp->fake_file_handle) {
5075 * This is actually for the QUOTA_FAKE_FILE --metze
5078 /* We know this name is ok, it's already passed the checks. */
5080 } else if(fsp->fh->fd == -1) {
5082 * This is actually a QFILEINFO on a directory
5083 * handle (returned from an NT SMB). NT5.0 seems
5084 * to do this call. JRA.
5087 if (INFO_LEVEL_IS_UNIX(info_level)) {
5088 /* Always do lstat for UNIX calls. */
5089 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5090 DEBUG(3,("call_trans2qfilepathinfo: "
5091 "SMB_VFS_LSTAT of %s failed "
5093 smb_fname_str_dbg(smb_fname),
5096 map_nt_error_from_unix(errno));
5099 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5100 DEBUG(3,("call_trans2qfilepathinfo: "
5101 "SMB_VFS_STAT of %s failed (%s)\n",
5102 smb_fname_str_dbg(smb_fname),
5105 map_nt_error_from_unix(errno));
5109 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5110 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5113 * Original code - this is an open file.
5115 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5116 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5117 fsp->fnum, strerror(errno)));
5119 map_nt_error_from_unix(errno));
5122 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5123 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5131 if (total_params < 7) {
5132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5136 info_level = SVAL(params,0);
5138 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5140 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5141 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5145 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5147 STR_TERMINATE, &status);
5148 if (!NT_STATUS_IS_OK(status)) {
5149 reply_nterror(req, status);
5153 status = filename_convert(req,
5155 req->flags2 & FLAGS2_DFS_PATHNAMES,
5160 if (!NT_STATUS_IS_OK(status)) {
5161 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5162 reply_botherror(req,
5163 NT_STATUS_PATH_NOT_COVERED,
5164 ERRSRV, ERRbadpath);
5167 reply_nterror(req, status);
5171 /* If this is a stream, check if there is a delete_pending. */
5172 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5173 && is_ntfs_stream_smb_fname(smb_fname)) {
5174 struct smb_filename *smb_fname_base = NULL;
5176 /* Create an smb_filename with stream_name == NULL. */
5178 create_synthetic_smb_fname(talloc_tos(),
5179 smb_fname->base_name,
5182 if (!NT_STATUS_IS_OK(status)) {
5183 reply_nterror(req, status);
5187 if (INFO_LEVEL_IS_UNIX(info_level)) {
5188 /* Always do lstat for UNIX calls. */
5189 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5190 DEBUG(3,("call_trans2qfilepathinfo: "
5191 "SMB_VFS_LSTAT of %s failed "
5193 smb_fname_str_dbg(smb_fname_base),
5195 TALLOC_FREE(smb_fname_base);
5197 map_nt_error_from_unix(errno));
5201 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5202 DEBUG(3,("call_trans2qfilepathinfo: "
5203 "fileinfo of %s failed "
5205 smb_fname_str_dbg(smb_fname_base),
5207 TALLOC_FREE(smb_fname_base);
5209 map_nt_error_from_unix(errno));
5214 status = file_name_hash(conn,
5215 smb_fname_str_dbg(smb_fname_base),
5217 if (!NT_STATUS_IS_OK(status)) {
5218 TALLOC_FREE(smb_fname_base);
5219 reply_nterror(req, status);
5223 fileid = vfs_file_id_from_sbuf(conn,
5224 &smb_fname_base->st);
5225 TALLOC_FREE(smb_fname_base);
5226 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5227 if (delete_pending) {
5228 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5233 if (INFO_LEVEL_IS_UNIX(info_level)) {
5234 /* Always do lstat for UNIX calls. */
5235 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5236 DEBUG(3,("call_trans2qfilepathinfo: "
5237 "SMB_VFS_LSTAT of %s failed (%s)\n",
5238 smb_fname_str_dbg(smb_fname),
5241 map_nt_error_from_unix(errno));
5246 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5247 DEBUG(3,("call_trans2qfilepathinfo: "
5248 "SMB_VFS_STAT of %s failed (%s)\n",
5249 smb_fname_str_dbg(smb_fname),
5252 map_nt_error_from_unix(errno));
5257 status = file_name_hash(conn,
5258 smb_fname_str_dbg(smb_fname),
5260 if (!NT_STATUS_IS_OK(status)) {
5261 reply_nterror(req, status);
5265 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5266 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5267 if (delete_pending) {
5268 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5273 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5274 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5275 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5277 /* Pull out any data sent here before we realloc. */
5278 switch (info_level) {
5279 case SMB_INFO_QUERY_EAS_FROM_LIST:
5281 /* Pull any EA list from the data portion. */
5284 if (total_data < 4) {
5286 req, NT_STATUS_INVALID_PARAMETER);
5289 ea_size = IVAL(pdata,0);
5291 if (total_data > 0 && ea_size != total_data) {
5292 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5293 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5295 req, NT_STATUS_INVALID_PARAMETER);
5299 if (!lp_ea_support(SNUM(conn))) {
5300 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5304 /* Pull out the list of names. */
5305 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5308 req, NT_STATUS_INVALID_PARAMETER);
5314 case SMB_QUERY_POSIX_LOCK:
5316 if (fsp == NULL || fsp->fh->fd == -1) {
5317 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5321 if (total_data != POSIX_LOCK_DATA_SIZE) {
5323 req, NT_STATUS_INVALID_PARAMETER);
5327 /* Copy the lock range data. */
5328 lock_data = (char *)TALLOC_MEMDUP(
5329 req, pdata, total_data);
5331 reply_nterror(req, NT_STATUS_NO_MEMORY);
5334 lock_data_count = total_data;
5340 *pparams = (char *)SMB_REALLOC(*pparams,2);
5341 if (*pparams == NULL) {
5342 reply_nterror(req, NT_STATUS_NO_MEMORY);
5349 * draft-leach-cifs-v1-spec-02.txt
5350 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5353 * The requested information is placed in the Data portion of the
5354 * transaction response. For the information levels greater than 0x100,
5355 * the transaction response has 1 parameter word which should be
5356 * ignored by the client.
5358 * However Windows only follows this rule for the IS_NAME_VALID call.
5360 switch (info_level) {
5361 case SMB_INFO_IS_NAME_VALID:
5366 if ((info_level & 0xFF00) == 0xFF00) {
5368 * We use levels that start with 0xFF00
5369 * internally to represent SMB2 specific levels
5371 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5375 status = smbd_do_qfilepathinfo(conn, req, info_level,
5377 delete_pending, write_time_ts,
5379 lock_data_count, lock_data,
5380 req->flags2, max_data_bytes,
5381 ppdata, &data_size);
5382 if (!NT_STATUS_IS_OK(status)) {
5383 reply_nterror(req, status);
5387 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5393 /****************************************************************************
5394 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5396 ****************************************************************************/
5398 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5399 connection_struct *conn,
5400 struct smb_request *req,
5401 bool overwrite_if_exists,
5402 const struct smb_filename *smb_fname_old,
5403 struct smb_filename *smb_fname_new)
5405 NTSTATUS status = NT_STATUS_OK;
5407 /* source must already exist. */
5408 if (!VALID_STAT(smb_fname_old->st)) {
5409 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5412 if (VALID_STAT(smb_fname_new->st)) {
5413 if (overwrite_if_exists) {
5414 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5415 return NT_STATUS_FILE_IS_A_DIRECTORY;
5417 status = unlink_internals(conn,
5419 FILE_ATTRIBUTE_NORMAL,
5422 if (!NT_STATUS_IS_OK(status)) {
5426 /* Disallow if newname already exists. */
5427 return NT_STATUS_OBJECT_NAME_COLLISION;
5431 /* No links from a directory. */
5432 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5433 return NT_STATUS_FILE_IS_A_DIRECTORY;
5436 /* Setting a hardlink to/from a stream isn't currently supported. */
5437 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5438 is_ntfs_stream_smb_fname(smb_fname_new)) {
5439 return NT_STATUS_INVALID_PARAMETER;
5442 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5443 smb_fname_old->base_name, smb_fname_new->base_name));
5445 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5446 smb_fname_new->base_name) != 0) {
5447 status = map_nt_error_from_unix(errno);
5448 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5449 nt_errstr(status), smb_fname_old->base_name,
5450 smb_fname_new->base_name));
5455 /****************************************************************************
5456 Deal with setting the time from any of the setfilepathinfo functions.
5457 ****************************************************************************/
5459 NTSTATUS smb_set_file_time(connection_struct *conn,
5461 const struct smb_filename *smb_fname,
5462 struct smb_file_time *ft,
5463 bool setting_write_time)
5465 struct smb_filename smb_fname_base;
5467 FILE_NOTIFY_CHANGE_LAST_ACCESS
5468 |FILE_NOTIFY_CHANGE_LAST_WRITE
5469 |FILE_NOTIFY_CHANGE_CREATION;
5471 if (!VALID_STAT(smb_fname->st)) {
5472 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5475 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5476 return NT_STATUS_ACCESS_DENIED;
5479 /* get some defaults (no modifications) if any info is zero or -1. */
5480 if (null_timespec(ft->create_time)) {
5481 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5484 if (null_timespec(ft->atime)) {
5485 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5488 if (null_timespec(ft->mtime)) {
5489 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5492 if (!setting_write_time) {
5493 /* ft->mtime comes from change time, not write time. */
5494 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5497 /* Ensure the resolution is the correct for
5498 * what we can store on this filesystem. */
5500 round_timespec(conn->ts_res, &ft->create_time);
5501 round_timespec(conn->ts_res, &ft->ctime);
5502 round_timespec(conn->ts_res, &ft->atime);
5503 round_timespec(conn->ts_res, &ft->mtime);
5505 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5506 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5507 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5508 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5509 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5510 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5511 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5512 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5514 if (setting_write_time) {
5516 * This was a Windows setfileinfo on an open file.
5517 * NT does this a lot. We also need to
5518 * set the time here, as it can be read by
5519 * FindFirst/FindNext and with the patch for bug #2045
5520 * in smbd/fileio.c it ensures that this timestamp is
5521 * kept sticky even after a write. We save the request
5522 * away and will set it on file close and after a write. JRA.
5525 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5526 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5529 if (fsp->base_fsp) {
5530 set_sticky_write_time_fsp(fsp->base_fsp,
5533 set_sticky_write_time_fsp(fsp, ft->mtime);
5536 set_sticky_write_time_path(
5537 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5542 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5544 /* Always call ntimes on the base, even if a stream was passed in. */
5545 smb_fname_base = *smb_fname;
5546 smb_fname_base.stream_name = NULL;
5548 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5549 return map_nt_error_from_unix(errno);
5552 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5553 smb_fname->base_name);
5554 return NT_STATUS_OK;
5557 /****************************************************************************
5558 Deal with setting the dosmode from any of the setfilepathinfo functions.
5559 ****************************************************************************/
5561 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5562 const struct smb_filename *smb_fname,
5565 struct smb_filename *smb_fname_base = NULL;
5568 if (!VALID_STAT(smb_fname->st)) {
5569 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5572 /* Always operate on the base_name, even if a stream was passed in. */
5573 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5574 NULL, &smb_fname->st,
5576 if (!NT_STATUS_IS_OK(status)) {
5581 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5588 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5590 /* check the mode isn't different, before changing it */
5591 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5592 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5593 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5594 (unsigned int)dosmode));
5596 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5598 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5600 smb_fname_str_dbg(smb_fname_base),
5602 status = map_nt_error_from_unix(errno);
5606 status = NT_STATUS_OK;
5608 TALLOC_FREE(smb_fname_base);
5612 /****************************************************************************
5613 Deal with setting the size from any of the setfilepathinfo functions.
5614 ****************************************************************************/
5616 static NTSTATUS smb_set_file_size(connection_struct *conn,
5617 struct smb_request *req,
5619 const struct smb_filename *smb_fname,
5620 const SMB_STRUCT_STAT *psbuf,
5622 bool fail_after_createfile)
5624 NTSTATUS status = NT_STATUS_OK;
5625 struct smb_filename *smb_fname_tmp = NULL;
5626 files_struct *new_fsp = NULL;
5628 if (!VALID_STAT(*psbuf)) {
5629 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5632 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5633 return NT_STATUS_ACCESS_DENIED;
5636 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5638 if (size == get_file_size_stat(psbuf)) {
5639 return NT_STATUS_OK;
5642 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5643 smb_fname_str_dbg(smb_fname), (double)size));
5645 if (fsp && fsp->fh->fd != -1) {
5646 /* Handle based call. */
5647 if (vfs_set_filelen(fsp, size) == -1) {
5648 return map_nt_error_from_unix(errno);
5650 trigger_write_time_update_immediate(fsp);
5651 return NT_STATUS_OK;
5654 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5655 if (!NT_STATUS_IS_OK(status)) {
5659 smb_fname_tmp->st = *psbuf;
5661 status = SMB_VFS_CREATE_FILE(
5664 0, /* root_dir_fid */
5665 smb_fname_tmp, /* fname */
5666 FILE_WRITE_DATA, /* access_mask */
5667 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5669 FILE_OPEN, /* create_disposition*/
5670 0, /* create_options */
5671 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5672 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5673 0, /* allocation_size */
5674 0, /* private_flags */
5677 &new_fsp, /* result */
5680 TALLOC_FREE(smb_fname_tmp);
5682 if (!NT_STATUS_IS_OK(status)) {
5683 /* NB. We check for open_was_deferred in the caller. */
5687 /* See RAW-SFILEINFO-END-OF-FILE */
5688 if (fail_after_createfile) {
5689 close_file(req, new_fsp,NORMAL_CLOSE);
5690 return NT_STATUS_INVALID_LEVEL;
5693 if (vfs_set_filelen(new_fsp, size) == -1) {
5694 status = map_nt_error_from_unix(errno);
5695 close_file(req, new_fsp,NORMAL_CLOSE);
5699 trigger_write_time_update_immediate(new_fsp);
5700 close_file(req, new_fsp,NORMAL_CLOSE);
5701 return NT_STATUS_OK;
5704 /****************************************************************************
5705 Deal with SMB_INFO_SET_EA.
5706 ****************************************************************************/
5708 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5712 const struct smb_filename *smb_fname)
5714 struct ea_list *ea_list = NULL;
5715 TALLOC_CTX *ctx = NULL;
5716 NTSTATUS status = NT_STATUS_OK;
5718 if (total_data < 10) {
5720 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5721 length. They seem to have no effect. Bug #3212. JRA */
5723 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5724 /* We're done. We only get EA info in this call. */
5725 return NT_STATUS_OK;
5728 return NT_STATUS_INVALID_PARAMETER;
5731 if (IVAL(pdata,0) > total_data) {
5732 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5733 IVAL(pdata,0), (unsigned int)total_data));
5734 return NT_STATUS_INVALID_PARAMETER;
5738 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5740 return NT_STATUS_INVALID_PARAMETER;
5743 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5744 return NT_STATUS_ACCESS_DENIED;
5747 status = set_ea(conn, fsp, smb_fname, ea_list);
5752 /****************************************************************************
5753 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5754 ****************************************************************************/
5756 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5761 struct ea_list *ea_list = NULL;
5765 return NT_STATUS_INVALID_HANDLE;
5768 if (!lp_ea_support(SNUM(conn))) {
5769 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5770 "EA's not supported.\n",
5771 (unsigned int)total_data));
5772 return NT_STATUS_EAS_NOT_SUPPORTED;
5775 if (total_data < 10) {
5776 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5778 (unsigned int)total_data));
5779 return NT_STATUS_INVALID_PARAMETER;
5782 ea_list = read_nttrans_ea_list(talloc_tos(),
5787 return NT_STATUS_INVALID_PARAMETER;
5790 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5791 return NT_STATUS_ACCESS_DENIED;
5794 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5796 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5797 smb_fname_str_dbg(fsp->fsp_name),
5798 nt_errstr(status) ));
5804 /****************************************************************************
5805 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5806 ****************************************************************************/
5808 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5812 struct smb_filename *smb_fname)
5814 NTSTATUS status = NT_STATUS_OK;
5815 bool delete_on_close;
5818 if (total_data < 1) {
5819 return NT_STATUS_INVALID_PARAMETER;
5823 return NT_STATUS_INVALID_HANDLE;
5826 delete_on_close = (CVAL(pdata,0) ? True : False);
5827 dosmode = dos_mode(conn, smb_fname);
5829 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5830 "delete_on_close = %u\n",
5831 smb_fname_str_dbg(smb_fname),
5832 (unsigned int)dosmode,
5833 (unsigned int)delete_on_close ));
5835 if (delete_on_close) {
5836 status = can_set_delete_on_close(fsp, dosmode);
5837 if (!NT_STATUS_IS_OK(status)) {
5842 /* The set is across all open files on this dev/inode pair. */
5843 if (!set_delete_on_close(fsp, delete_on_close,
5844 &conn->session_info->utok)) {
5845 return NT_STATUS_ACCESS_DENIED;
5847 return NT_STATUS_OK;
5850 /****************************************************************************
5851 Deal with SMB_FILE_POSITION_INFORMATION.
5852 ****************************************************************************/
5854 static NTSTATUS smb_file_position_information(connection_struct *conn,
5859 uint64_t position_information;
5861 if (total_data < 8) {
5862 return NT_STATUS_INVALID_PARAMETER;
5866 /* Ignore on pathname based set. */
5867 return NT_STATUS_OK;
5870 position_information = (uint64_t)IVAL(pdata,0);
5871 #ifdef LARGE_SMB_OFF_T
5872 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5873 #else /* LARGE_SMB_OFF_T */
5874 if (IVAL(pdata,4) != 0) {
5875 /* more than 32 bits? */
5876 return NT_STATUS_INVALID_PARAMETER;
5878 #endif /* LARGE_SMB_OFF_T */
5880 DEBUG(10,("smb_file_position_information: Set file position "
5881 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5882 (double)position_information));
5883 fsp->fh->position_information = position_information;
5884 return NT_STATUS_OK;
5887 /****************************************************************************
5888 Deal with SMB_FILE_MODE_INFORMATION.
5889 ****************************************************************************/
5891 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5897 if (total_data < 4) {
5898 return NT_STATUS_INVALID_PARAMETER;
5900 mode = IVAL(pdata,0);
5901 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5902 return NT_STATUS_INVALID_PARAMETER;
5904 return NT_STATUS_OK;
5907 /****************************************************************************
5908 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5909 ****************************************************************************/
5911 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5912 struct smb_request *req,
5915 const struct smb_filename *smb_fname)
5917 char *link_target = NULL;
5918 const char *newname = smb_fname->base_name;
5919 TALLOC_CTX *ctx = talloc_tos();
5921 /* Set a symbolic link. */
5922 /* Don't allow this if follow links is false. */
5924 if (total_data == 0) {
5925 return NT_STATUS_INVALID_PARAMETER;
5928 if (!lp_symlinks(SNUM(conn))) {
5929 return NT_STATUS_ACCESS_DENIED;
5932 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5933 total_data, STR_TERMINATE);
5936 return NT_STATUS_INVALID_PARAMETER;
5939 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5940 newname, link_target ));
5942 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5943 return map_nt_error_from_unix(errno);
5946 return NT_STATUS_OK;
5949 /****************************************************************************
5950 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5951 ****************************************************************************/
5953 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5954 struct smb_request *req,
5955 const char *pdata, int total_data,
5956 struct smb_filename *smb_fname_new)
5958 char *oldname = NULL;
5959 struct smb_filename *smb_fname_old = NULL;
5960 TALLOC_CTX *ctx = talloc_tos();
5961 NTSTATUS status = NT_STATUS_OK;
5963 /* Set a hard link. */
5964 if (total_data == 0) {
5965 return NT_STATUS_INVALID_PARAMETER;
5968 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5969 total_data, STR_TERMINATE, &status);
5970 if (!NT_STATUS_IS_OK(status)) {
5974 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5975 smb_fname_str_dbg(smb_fname_new), oldname));
5977 status = filename_convert(ctx,
5979 req->flags2 & FLAGS2_DFS_PATHNAMES,
5984 if (!NT_STATUS_IS_OK(status)) {
5988 return hardlink_internals(ctx, conn, req, false,
5989 smb_fname_old, smb_fname_new);
5992 /****************************************************************************
5993 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5994 ****************************************************************************/
5996 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5997 struct smb_request *req,
6001 struct smb_filename *smb_fname_src)
6005 char *newname = NULL;
6006 struct smb_filename *smb_fname_dst = NULL;
6007 NTSTATUS status = NT_STATUS_OK;
6008 TALLOC_CTX *ctx = talloc_tos();
6011 return NT_STATUS_INVALID_HANDLE;
6014 if (total_data < 20) {
6015 return NT_STATUS_INVALID_PARAMETER;
6018 overwrite = (CVAL(pdata,0) ? True : False);
6019 len = IVAL(pdata,16);
6021 if (len > (total_data - 20) || (len == 0)) {
6022 return NT_STATUS_INVALID_PARAMETER;
6025 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6026 &pdata[20], len, STR_TERMINATE,
6028 if (!NT_STATUS_IS_OK(status)) {
6032 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6035 status = filename_convert(ctx,
6037 req->flags2 & FLAGS2_DFS_PATHNAMES,
6042 if (!NT_STATUS_IS_OK(status)) {
6046 if (fsp->base_fsp) {
6047 /* newname must be a stream name. */
6048 if (newname[0] != ':') {
6049 return NT_STATUS_NOT_SUPPORTED;
6052 /* Create an smb_fname to call rename_internals_fsp() with. */
6053 status = create_synthetic_smb_fname(talloc_tos(),
6054 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6056 if (!NT_STATUS_IS_OK(status)) {
6061 * Set the original last component, since
6062 * rename_internals_fsp() requires it.
6064 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6066 if (smb_fname_dst->original_lcomp == NULL) {
6067 status = NT_STATUS_NO_MEMORY;
6073 DEBUG(10,("smb2_file_rename_information: "
6074 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6075 fsp->fnum, fsp_str_dbg(fsp),
6076 smb_fname_str_dbg(smb_fname_dst)));
6077 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6081 TALLOC_FREE(smb_fname_dst);
6085 static NTSTATUS smb_file_link_information(connection_struct *conn,
6086 struct smb_request *req,
6090 struct smb_filename *smb_fname_src)
6094 char *newname = NULL;
6095 struct smb_filename *smb_fname_dst = NULL;
6096 NTSTATUS status = NT_STATUS_OK;
6097 TALLOC_CTX *ctx = talloc_tos();
6100 return NT_STATUS_INVALID_HANDLE;
6103 if (total_data < 20) {
6104 return NT_STATUS_INVALID_PARAMETER;
6107 overwrite = (CVAL(pdata,0) ? true : false);
6108 len = IVAL(pdata,16);
6110 if (len > (total_data - 20) || (len == 0)) {
6111 return NT_STATUS_INVALID_PARAMETER;
6114 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6115 &pdata[20], len, STR_TERMINATE,
6117 if (!NT_STATUS_IS_OK(status)) {
6121 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6124 status = filename_convert(ctx,
6126 req->flags2 & FLAGS2_DFS_PATHNAMES,
6131 if (!NT_STATUS_IS_OK(status)) {
6135 if (fsp->base_fsp) {
6136 /* No stream names. */
6137 return NT_STATUS_NOT_SUPPORTED;
6140 DEBUG(10,("smb_file_link_information: "
6141 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6142 fsp->fnum, fsp_str_dbg(fsp),
6143 smb_fname_str_dbg(smb_fname_dst)));
6144 status = hardlink_internals(ctx,
6151 TALLOC_FREE(smb_fname_dst);
6155 /****************************************************************************
6156 Deal with SMB_FILE_RENAME_INFORMATION.
6157 ****************************************************************************/
6159 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6160 struct smb_request *req,
6164 struct smb_filename *smb_fname_src)
6169 char *newname = NULL;
6170 struct smb_filename *smb_fname_dst = NULL;
6171 bool dest_has_wcard = False;
6172 NTSTATUS status = NT_STATUS_OK;
6174 TALLOC_CTX *ctx = talloc_tos();
6176 if (total_data < 13) {
6177 return NT_STATUS_INVALID_PARAMETER;
6180 overwrite = (CVAL(pdata,0) ? True : False);
6181 root_fid = IVAL(pdata,4);
6182 len = IVAL(pdata,8);
6184 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6185 return NT_STATUS_INVALID_PARAMETER;
6188 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6191 if (!NT_STATUS_IS_OK(status)) {
6195 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6198 status = resolve_dfspath_wcard(ctx, conn,
6199 req->flags2 & FLAGS2_DFS_PATHNAMES,
6204 if (!NT_STATUS_IS_OK(status)) {
6208 /* Check the new name has no '/' characters. */
6209 if (strchr_m(newname, '/')) {
6210 return NT_STATUS_NOT_SUPPORTED;
6213 if (fsp && fsp->base_fsp) {
6214 /* newname must be a stream name. */
6215 if (newname[0] != ':') {
6216 return NT_STATUS_NOT_SUPPORTED;
6219 /* Create an smb_fname to call rename_internals_fsp() with. */
6220 status = create_synthetic_smb_fname(talloc_tos(),
6221 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6223 if (!NT_STATUS_IS_OK(status)) {
6228 * Set the original last component, since
6229 * rename_internals_fsp() requires it.
6231 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6233 if (smb_fname_dst->original_lcomp == NULL) {
6234 status = NT_STATUS_NO_MEMORY;
6240 * Build up an smb_fname_dst based on the filename passed in.
6241 * We basically just strip off the last component, and put on
6242 * the newname instead.
6244 char *base_name = NULL;
6246 /* newname must *not* be a stream name. */
6247 if (newname[0] == ':') {
6248 return NT_STATUS_NOT_SUPPORTED;
6252 * Strip off the last component (filename) of the path passed
6255 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6257 return NT_STATUS_NO_MEMORY;
6259 p = strrchr_m(base_name, '/');
6263 base_name = talloc_strdup(ctx, "");
6265 return NT_STATUS_NO_MEMORY;
6268 /* Append the new name. */
6269 base_name = talloc_asprintf_append(base_name,
6273 return NT_STATUS_NO_MEMORY;
6276 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6279 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6282 /* If an error we expect this to be
6283 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6285 if (!NT_STATUS_IS_OK(status)) {
6286 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6290 /* Create an smb_fname to call rename_internals_fsp() */
6291 status = create_synthetic_smb_fname(ctx,
6295 if (!NT_STATUS_IS_OK(status)) {
6302 DEBUG(10,("smb_file_rename_information: "
6303 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6304 fsp->fnum, fsp_str_dbg(fsp),
6305 smb_fname_str_dbg(smb_fname_dst)));
6306 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6309 DEBUG(10,("smb_file_rename_information: "
6310 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6311 smb_fname_str_dbg(smb_fname_src),
6312 smb_fname_str_dbg(smb_fname_dst)));
6313 status = rename_internals(ctx, conn, req, smb_fname_src,
6314 smb_fname_dst, 0, overwrite, false,
6316 FILE_WRITE_ATTRIBUTES);
6319 TALLOC_FREE(smb_fname_dst);
6323 /****************************************************************************
6324 Deal with SMB_SET_POSIX_ACL.
6325 ****************************************************************************/
6327 #if defined(HAVE_POSIX_ACLS)
6328 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6332 const struct smb_filename *smb_fname)
6334 uint16 posix_acl_version;
6335 uint16 num_file_acls;
6336 uint16 num_def_acls;
6337 bool valid_file_acls = True;
6338 bool valid_def_acls = True;
6340 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6341 return NT_STATUS_INVALID_PARAMETER;
6343 posix_acl_version = SVAL(pdata,0);
6344 num_file_acls = SVAL(pdata,2);
6345 num_def_acls = SVAL(pdata,4);
6347 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6348 valid_file_acls = False;
6352 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6353 valid_def_acls = False;
6357 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6358 return NT_STATUS_INVALID_PARAMETER;
6361 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6362 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6363 return NT_STATUS_INVALID_PARAMETER;
6366 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6367 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6368 (unsigned int)num_file_acls,
6369 (unsigned int)num_def_acls));
6371 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6372 smb_fname->base_name, num_file_acls,
6373 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6374 return map_nt_error_from_unix(errno);
6377 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6378 smb_fname->base_name, &smb_fname->st, num_def_acls,
6379 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6380 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6381 return map_nt_error_from_unix(errno);
6383 return NT_STATUS_OK;
6387 /****************************************************************************
6388 Deal with SMB_SET_POSIX_LOCK.
6389 ****************************************************************************/
6391 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6392 struct smb_request *req,
6400 bool blocking_lock = False;
6401 enum brl_type lock_type;
6403 NTSTATUS status = NT_STATUS_OK;
6405 if (fsp == NULL || fsp->fh->fd == -1) {
6406 return NT_STATUS_INVALID_HANDLE;
6409 if (total_data != POSIX_LOCK_DATA_SIZE) {
6410 return NT_STATUS_INVALID_PARAMETER;
6413 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6414 case POSIX_LOCK_TYPE_READ:
6415 lock_type = READ_LOCK;
6417 case POSIX_LOCK_TYPE_WRITE:
6418 /* Return the right POSIX-mappable error code for files opened read-only. */
6419 if (!fsp->can_write) {
6420 return NT_STATUS_INVALID_HANDLE;
6422 lock_type = WRITE_LOCK;
6424 case POSIX_LOCK_TYPE_UNLOCK:
6425 lock_type = UNLOCK_LOCK;
6428 return NT_STATUS_INVALID_PARAMETER;
6431 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6432 blocking_lock = False;
6433 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6434 blocking_lock = True;
6436 return NT_STATUS_INVALID_PARAMETER;
6439 if (!lp_blocking_locks(SNUM(conn))) {
6440 blocking_lock = False;
6443 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6444 #if defined(HAVE_LONGLONG)
6445 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6446 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6447 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6448 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6449 #else /* HAVE_LONGLONG */
6450 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6451 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6452 #endif /* HAVE_LONGLONG */
6454 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6455 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6457 (unsigned int)lock_type,
6458 (unsigned long long)smblctx,
6462 if (lock_type == UNLOCK_LOCK) {
6463 status = do_unlock(req->sconn->msg_ctx,
6470 uint64_t block_smblctx;
6472 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6484 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6486 * A blocking lock was requested. Package up
6487 * this smb into a queued request and push it
6488 * onto the blocking lock queue.
6490 if(push_blocking_lock_request(br_lck,
6493 -1, /* infinite timeout. */
6501 TALLOC_FREE(br_lck);
6505 TALLOC_FREE(br_lck);
6511 /****************************************************************************
6512 Deal with SMB_SET_FILE_BASIC_INFO.
6513 ****************************************************************************/
6515 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6519 const struct smb_filename *smb_fname)
6521 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6522 struct smb_file_time ft;
6524 NTSTATUS status = NT_STATUS_OK;
6528 if (total_data < 36) {
6529 return NT_STATUS_INVALID_PARAMETER;
6532 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6533 return NT_STATUS_ACCESS_DENIED;
6536 /* Set the attributes */
6537 dosmode = IVAL(pdata,32);
6538 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6539 if (!NT_STATUS_IS_OK(status)) {
6544 ft.create_time = interpret_long_date(pdata);
6547 ft.atime = interpret_long_date(pdata+8);
6550 ft.mtime = interpret_long_date(pdata+16);
6553 ft.ctime = interpret_long_date(pdata+24);
6555 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6556 smb_fname_str_dbg(smb_fname)));
6558 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6562 /****************************************************************************
6563 Deal with SMB_INFO_STANDARD.
6564 ****************************************************************************/
6566 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6570 const struct smb_filename *smb_fname)
6572 struct smb_file_time ft;
6576 if (total_data < 12) {
6577 return NT_STATUS_INVALID_PARAMETER;
6580 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6581 return NT_STATUS_ACCESS_DENIED;
6585 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6587 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6589 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6591 DEBUG(10,("smb_set_info_standard: file %s\n",
6592 smb_fname_str_dbg(smb_fname)));
6594 return smb_set_file_time(conn,
6601 /****************************************************************************
6602 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6603 ****************************************************************************/
6605 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6606 struct smb_request *req,
6610 struct smb_filename *smb_fname)
6612 uint64_t allocation_size = 0;
6613 NTSTATUS status = NT_STATUS_OK;
6614 files_struct *new_fsp = NULL;
6616 if (!VALID_STAT(smb_fname->st)) {
6617 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6620 if (total_data < 8) {
6621 return NT_STATUS_INVALID_PARAMETER;
6624 allocation_size = (uint64_t)IVAL(pdata,0);
6625 #ifdef LARGE_SMB_OFF_T
6626 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6627 #else /* LARGE_SMB_OFF_T */
6628 if (IVAL(pdata,4) != 0) {
6629 /* more than 32 bits? */
6630 return NT_STATUS_INVALID_PARAMETER;
6632 #endif /* LARGE_SMB_OFF_T */
6634 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6635 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6636 (double)allocation_size));
6638 if (allocation_size) {
6639 allocation_size = smb_roundup(conn, allocation_size);
6642 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6643 return NT_STATUS_ACCESS_DENIED;
6646 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6647 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6648 (double)allocation_size));
6650 if (fsp && fsp->fh->fd != -1) {
6651 /* Open file handle. */
6652 /* Only change if needed. */
6653 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6654 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6655 return map_nt_error_from_unix(errno);
6658 /* But always update the time. */
6660 * This is equivalent to a write. Ensure it's seen immediately
6661 * if there are no pending writes.
6663 trigger_write_time_update_immediate(fsp);
6664 return NT_STATUS_OK;
6667 /* Pathname or stat or directory file. */
6668 status = SMB_VFS_CREATE_FILE(
6671 0, /* root_dir_fid */
6672 smb_fname, /* fname */
6673 FILE_WRITE_DATA, /* access_mask */
6674 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6676 FILE_OPEN, /* create_disposition*/
6677 0, /* create_options */
6678 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6679 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6680 0, /* allocation_size */
6681 0, /* private_flags */
6684 &new_fsp, /* result */
6687 if (!NT_STATUS_IS_OK(status)) {
6688 /* NB. We check for open_was_deferred in the caller. */
6692 /* Only change if needed. */
6693 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6694 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6695 status = map_nt_error_from_unix(errno);
6696 close_file(req, new_fsp, NORMAL_CLOSE);
6701 /* Changing the allocation size should set the last mod time. */
6703 * This is equivalent to a write. Ensure it's seen immediately
6704 * if there are no pending writes.
6706 trigger_write_time_update_immediate(new_fsp);
6708 close_file(req, new_fsp, NORMAL_CLOSE);
6709 return NT_STATUS_OK;
6712 /****************************************************************************
6713 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6714 ****************************************************************************/
6716 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6717 struct smb_request *req,
6721 const struct smb_filename *smb_fname,
6722 bool fail_after_createfile)
6726 if (total_data < 8) {
6727 return NT_STATUS_INVALID_PARAMETER;
6730 size = IVAL(pdata,0);
6731 #ifdef LARGE_SMB_OFF_T
6732 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6733 #else /* LARGE_SMB_OFF_T */
6734 if (IVAL(pdata,4) != 0) {
6735 /* more than 32 bits? */
6736 return NT_STATUS_INVALID_PARAMETER;
6738 #endif /* LARGE_SMB_OFF_T */
6739 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6740 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6743 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6744 return NT_STATUS_ACCESS_DENIED;
6747 return smb_set_file_size(conn, req,
6752 fail_after_createfile);
6755 /****************************************************************************
6756 Allow a UNIX info mknod.
6757 ****************************************************************************/
6759 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6762 const struct smb_filename *smb_fname)
6764 uint32 file_type = IVAL(pdata,56);
6765 #if defined(HAVE_MAKEDEV)
6766 uint32 dev_major = IVAL(pdata,60);
6767 uint32 dev_minor = IVAL(pdata,68);
6769 SMB_DEV_T dev = (SMB_DEV_T)0;
6770 uint32 raw_unixmode = IVAL(pdata,84);
6774 if (total_data < 100) {
6775 return NT_STATUS_INVALID_PARAMETER;
6778 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6779 PERM_NEW_FILE, &unixmode);
6780 if (!NT_STATUS_IS_OK(status)) {
6784 #if defined(HAVE_MAKEDEV)
6785 dev = makedev(dev_major, dev_minor);
6788 switch (file_type) {
6789 #if defined(S_IFIFO)
6790 case UNIX_TYPE_FIFO:
6791 unixmode |= S_IFIFO;
6794 #if defined(S_IFSOCK)
6795 case UNIX_TYPE_SOCKET:
6796 unixmode |= S_IFSOCK;
6799 #if defined(S_IFCHR)
6800 case UNIX_TYPE_CHARDEV:
6801 unixmode |= S_IFCHR;
6804 #if defined(S_IFBLK)
6805 case UNIX_TYPE_BLKDEV:
6806 unixmode |= S_IFBLK;
6810 return NT_STATUS_INVALID_PARAMETER;
6813 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6814 "%.0f mode 0%o for file %s\n", (double)dev,
6815 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6817 /* Ok - do the mknod. */
6818 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6819 return map_nt_error_from_unix(errno);
6822 /* If any of the other "set" calls fail we
6823 * don't want to end up with a half-constructed mknod.
6826 if (lp_inherit_perms(SNUM(conn))) {
6828 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6830 return NT_STATUS_NO_MEMORY;
6832 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6834 TALLOC_FREE(parent);
6837 return NT_STATUS_OK;
6840 /****************************************************************************
6841 Deal with SMB_SET_FILE_UNIX_BASIC.
6842 ****************************************************************************/
6844 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6845 struct smb_request *req,
6849 const struct smb_filename *smb_fname)
6851 struct smb_file_time ft;
6852 uint32 raw_unixmode;
6855 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6856 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6857 NTSTATUS status = NT_STATUS_OK;
6858 bool delete_on_fail = False;
6859 enum perm_type ptype;
6860 files_struct *all_fsps = NULL;
6861 bool modify_mtime = true;
6863 struct smb_filename *smb_fname_tmp = NULL;
6864 SMB_STRUCT_STAT sbuf;
6868 if (total_data < 100) {
6869 return NT_STATUS_INVALID_PARAMETER;
6872 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6873 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6874 size=IVAL(pdata,0); /* first 8 Bytes are size */
6875 #ifdef LARGE_SMB_OFF_T
6876 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6877 #else /* LARGE_SMB_OFF_T */
6878 if (IVAL(pdata,4) != 0) {
6879 /* more than 32 bits? */
6880 return NT_STATUS_INVALID_PARAMETER;
6882 #endif /* LARGE_SMB_OFF_T */
6885 ft.atime = interpret_long_date(pdata+24); /* access_time */
6886 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6887 set_owner = (uid_t)IVAL(pdata,40);
6888 set_grp = (gid_t)IVAL(pdata,48);
6889 raw_unixmode = IVAL(pdata,84);
6891 if (VALID_STAT(smb_fname->st)) {
6892 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6893 ptype = PERM_EXISTING_DIR;
6895 ptype = PERM_EXISTING_FILE;
6898 ptype = PERM_NEW_FILE;
6901 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6903 if (!NT_STATUS_IS_OK(status)) {
6907 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6908 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6909 smb_fname_str_dbg(smb_fname), (double)size,
6910 (unsigned int)set_owner, (unsigned int)set_grp,
6911 (int)raw_unixmode));
6913 sbuf = smb_fname->st;
6915 if (!VALID_STAT(sbuf)) {
6917 * The only valid use of this is to create character and block
6918 * devices, and named pipes. This is deprecated (IMHO) and
6919 * a new info level should be used for mknod. JRA.
6922 status = smb_unix_mknod(conn,
6926 if (!NT_STATUS_IS_OK(status)) {
6930 status = copy_smb_filename(talloc_tos(), smb_fname,
6932 if (!NT_STATUS_IS_OK(status)) {
6936 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6937 status = map_nt_error_from_unix(errno);
6938 TALLOC_FREE(smb_fname_tmp);
6939 SMB_VFS_UNLINK(conn, smb_fname);
6943 sbuf = smb_fname_tmp->st;
6944 smb_fname = smb_fname_tmp;
6946 /* Ensure we don't try and change anything else. */
6947 raw_unixmode = SMB_MODE_NO_CHANGE;
6948 size = get_file_size_stat(&sbuf);
6949 ft.atime = sbuf.st_ex_atime;
6950 ft.mtime = sbuf.st_ex_mtime;
6952 * We continue here as we might want to change the
6955 delete_on_fail = True;
6959 /* Horrible backwards compatibility hack as an old server bug
6960 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6964 size = get_file_size_stat(&sbuf);
6969 * Deal with the UNIX specific mode set.
6972 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6973 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6974 "setting mode 0%o for file %s\n",
6975 (unsigned int)unixmode,
6976 smb_fname_str_dbg(smb_fname)));
6977 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6978 return map_nt_error_from_unix(errno);
6983 * Deal with the UNIX specific uid set.
6986 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6987 (sbuf.st_ex_uid != set_owner)) {
6990 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6991 "changing owner %u for path %s\n",
6992 (unsigned int)set_owner,
6993 smb_fname_str_dbg(smb_fname)));
6995 if (S_ISLNK(sbuf.st_ex_mode)) {
6996 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6997 set_owner, (gid_t)-1);
6999 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7000 set_owner, (gid_t)-1);
7004 status = map_nt_error_from_unix(errno);
7005 if (delete_on_fail) {
7006 SMB_VFS_UNLINK(conn, smb_fname);
7013 * Deal with the UNIX specific gid set.
7016 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7017 (sbuf.st_ex_gid != set_grp)) {
7018 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7019 "changing group %u for file %s\n",
7020 (unsigned int)set_owner,
7021 smb_fname_str_dbg(smb_fname)));
7022 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7024 status = map_nt_error_from_unix(errno);
7025 if (delete_on_fail) {
7026 SMB_VFS_UNLINK(conn, smb_fname);
7032 /* Deal with any size changes. */
7034 status = smb_set_file_size(conn, req,
7040 if (!NT_STATUS_IS_OK(status)) {
7044 /* Deal with any time changes. */
7045 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7046 /* No change, don't cancel anything. */
7050 id = vfs_file_id_from_sbuf(conn, &sbuf);
7051 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7052 all_fsps = file_find_di_next(all_fsps)) {
7054 * We're setting the time explicitly for UNIX.
7055 * Cancel any pending changes over all handles.
7057 all_fsps->update_write_time_on_close = false;
7058 TALLOC_FREE(all_fsps->update_write_time_event);
7062 * Override the "setting_write_time"
7063 * parameter here as it almost does what
7064 * we need. Just remember if we modified
7065 * mtime and send the notify ourselves.
7067 if (null_timespec(ft.mtime)) {
7068 modify_mtime = false;
7071 status = smb_set_file_time(conn,
7077 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7078 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7083 /****************************************************************************
7084 Deal with SMB_SET_FILE_UNIX_INFO2.
7085 ****************************************************************************/
7087 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7088 struct smb_request *req,
7092 const struct smb_filename *smb_fname)
7098 if (total_data < 116) {
7099 return NT_STATUS_INVALID_PARAMETER;
7102 /* Start by setting all the fields that are common between UNIX_BASIC
7105 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7107 if (!NT_STATUS_IS_OK(status)) {
7111 smb_fflags = IVAL(pdata, 108);
7112 smb_fmask = IVAL(pdata, 112);
7114 /* NB: We should only attempt to alter the file flags if the client
7115 * sends a non-zero mask.
7117 if (smb_fmask != 0) {
7118 int stat_fflags = 0;
7120 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7121 smb_fmask, &stat_fflags)) {
7122 /* Client asked to alter a flag we don't understand. */
7123 return NT_STATUS_INVALID_PARAMETER;
7126 if (fsp && fsp->fh->fd != -1) {
7127 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7128 return NT_STATUS_NOT_SUPPORTED;
7130 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7131 stat_fflags) != 0) {
7132 return map_nt_error_from_unix(errno);
7137 /* XXX: need to add support for changing the create_time here. You
7138 * can do this for paths on Darwin with setattrlist(2). The right way
7139 * to hook this up is probably by extending the VFS utimes interface.
7142 return NT_STATUS_OK;
7145 /****************************************************************************
7146 Create a directory with POSIX semantics.
7147 ****************************************************************************/
7149 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7150 struct smb_request *req,
7153 struct smb_filename *smb_fname,
7154 int *pdata_return_size)
7156 NTSTATUS status = NT_STATUS_OK;
7157 uint32 raw_unixmode = 0;
7158 uint32 mod_unixmode = 0;
7159 mode_t unixmode = (mode_t)0;
7160 files_struct *fsp = NULL;
7161 uint16 info_level_return = 0;
7163 char *pdata = *ppdata;
7165 if (total_data < 18) {
7166 return NT_STATUS_INVALID_PARAMETER;
7169 raw_unixmode = IVAL(pdata,8);
7170 /* Next 4 bytes are not yet defined. */
7172 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7173 PERM_NEW_DIR, &unixmode);
7174 if (!NT_STATUS_IS_OK(status)) {
7178 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7180 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7181 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7183 status = SMB_VFS_CREATE_FILE(
7186 0, /* root_dir_fid */
7187 smb_fname, /* fname */
7188 FILE_READ_ATTRIBUTES, /* access_mask */
7189 FILE_SHARE_NONE, /* share_access */
7190 FILE_CREATE, /* create_disposition*/
7191 FILE_DIRECTORY_FILE, /* create_options */
7192 mod_unixmode, /* file_attributes */
7193 0, /* oplock_request */
7194 0, /* allocation_size */
7195 0, /* private_flags */
7201 if (NT_STATUS_IS_OK(status)) {
7202 close_file(req, fsp, NORMAL_CLOSE);
7205 info_level_return = SVAL(pdata,16);
7207 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7208 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7209 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7210 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7212 *pdata_return_size = 12;
7215 /* Realloc the data size */
7216 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7217 if (*ppdata == NULL) {
7218 *pdata_return_size = 0;
7219 return NT_STATUS_NO_MEMORY;
7223 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7224 SSVAL(pdata,2,0); /* No fnum. */
7225 SIVAL(pdata,4,info); /* Was directory created. */
7227 switch (info_level_return) {
7228 case SMB_QUERY_FILE_UNIX_BASIC:
7229 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7230 SSVAL(pdata,10,0); /* Padding. */
7231 store_file_unix_basic(conn, pdata + 12, fsp,
7234 case SMB_QUERY_FILE_UNIX_INFO2:
7235 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7236 SSVAL(pdata,10,0); /* Padding. */
7237 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7241 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7242 SSVAL(pdata,10,0); /* Padding. */
7249 /****************************************************************************
7250 Open/Create a file with POSIX semantics.
7251 ****************************************************************************/
7253 static NTSTATUS smb_posix_open(connection_struct *conn,
7254 struct smb_request *req,
7257 struct smb_filename *smb_fname,
7258 int *pdata_return_size)
7260 bool extended_oplock_granted = False;
7261 char *pdata = *ppdata;
7263 uint32 wire_open_mode = 0;
7264 uint32 raw_unixmode = 0;
7265 uint32 mod_unixmode = 0;
7266 uint32 create_disp = 0;
7267 uint32 access_mask = 0;
7268 uint32 create_options = 0;
7269 NTSTATUS status = NT_STATUS_OK;
7270 mode_t unixmode = (mode_t)0;
7271 files_struct *fsp = NULL;
7272 int oplock_request = 0;
7274 uint16 info_level_return = 0;
7276 if (total_data < 18) {
7277 return NT_STATUS_INVALID_PARAMETER;
7280 flags = IVAL(pdata,0);
7281 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7282 if (oplock_request) {
7283 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7286 wire_open_mode = IVAL(pdata,4);
7288 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7289 return smb_posix_mkdir(conn, req,
7296 switch (wire_open_mode & SMB_ACCMODE) {
7298 access_mask = FILE_READ_DATA;
7301 access_mask = FILE_WRITE_DATA;
7304 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7307 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7308 (unsigned int)wire_open_mode ));
7309 return NT_STATUS_INVALID_PARAMETER;
7312 wire_open_mode &= ~SMB_ACCMODE;
7314 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7315 create_disp = FILE_CREATE;
7316 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7317 create_disp = FILE_OVERWRITE_IF;
7318 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7319 create_disp = FILE_OPEN_IF;
7320 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7321 create_disp = FILE_OPEN;
7323 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7324 (unsigned int)wire_open_mode ));
7325 return NT_STATUS_INVALID_PARAMETER;
7328 raw_unixmode = IVAL(pdata,8);
7329 /* Next 4 bytes are not yet defined. */
7331 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7332 (VALID_STAT(smb_fname->st) ?
7333 PERM_EXISTING_FILE : PERM_NEW_FILE),
7336 if (!NT_STATUS_IS_OK(status)) {
7340 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7342 if (wire_open_mode & SMB_O_SYNC) {
7343 create_options |= FILE_WRITE_THROUGH;
7345 if (wire_open_mode & SMB_O_APPEND) {
7346 access_mask |= FILE_APPEND_DATA;
7348 if (wire_open_mode & SMB_O_DIRECT) {
7349 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7352 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7353 smb_fname_str_dbg(smb_fname),
7354 (unsigned int)wire_open_mode,
7355 (unsigned int)unixmode ));
7357 status = SMB_VFS_CREATE_FILE(
7360 0, /* root_dir_fid */
7361 smb_fname, /* fname */
7362 access_mask, /* access_mask */
7363 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7365 create_disp, /* create_disposition*/
7366 FILE_NON_DIRECTORY_FILE, /* create_options */
7367 mod_unixmode, /* file_attributes */
7368 oplock_request, /* oplock_request */
7369 0, /* allocation_size */
7370 0, /* private_flags */
7376 if (!NT_STATUS_IS_OK(status)) {
7380 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7381 extended_oplock_granted = True;
7384 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7385 extended_oplock_granted = True;
7388 info_level_return = SVAL(pdata,16);
7390 /* Allocate the correct return size. */
7392 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7393 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7394 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7395 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7397 *pdata_return_size = 12;
7400 /* Realloc the data size */
7401 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7402 if (*ppdata == NULL) {
7403 close_file(req, fsp, ERROR_CLOSE);
7404 *pdata_return_size = 0;
7405 return NT_STATUS_NO_MEMORY;
7409 if (extended_oplock_granted) {
7410 if (flags & REQUEST_BATCH_OPLOCK) {
7411 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7413 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7415 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7416 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7418 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7421 SSVAL(pdata,2,fsp->fnum);
7422 SIVAL(pdata,4,info); /* Was file created etc. */
7424 switch (info_level_return) {
7425 case SMB_QUERY_FILE_UNIX_BASIC:
7426 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7427 SSVAL(pdata,10,0); /* padding. */
7428 store_file_unix_basic(conn, pdata + 12, fsp,
7431 case SMB_QUERY_FILE_UNIX_INFO2:
7432 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7433 SSVAL(pdata,10,0); /* padding. */
7434 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7438 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7439 SSVAL(pdata,10,0); /* padding. */
7442 return NT_STATUS_OK;
7445 /****************************************************************************
7446 Delete a file with POSIX semantics.
7447 ****************************************************************************/
7449 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7450 struct smb_request *req,
7453 struct smb_filename *smb_fname)
7455 NTSTATUS status = NT_STATUS_OK;
7456 files_struct *fsp = NULL;
7460 int create_options = 0;
7462 struct share_mode_lock *lck = NULL;
7464 if (total_data < 2) {
7465 return NT_STATUS_INVALID_PARAMETER;
7468 flags = SVAL(pdata,0);
7470 if (!VALID_STAT(smb_fname->st)) {
7471 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7474 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7475 !VALID_STAT_OF_DIR(smb_fname->st)) {
7476 return NT_STATUS_NOT_A_DIRECTORY;
7479 DEBUG(10,("smb_posix_unlink: %s %s\n",
7480 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7481 smb_fname_str_dbg(smb_fname)));
7483 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7484 create_options |= FILE_DIRECTORY_FILE;
7487 status = SMB_VFS_CREATE_FILE(
7490 0, /* root_dir_fid */
7491 smb_fname, /* fname */
7492 DELETE_ACCESS, /* access_mask */
7493 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7495 FILE_OPEN, /* create_disposition*/
7496 create_options, /* create_options */
7497 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7498 0, /* oplock_request */
7499 0, /* allocation_size */
7500 0, /* private_flags */
7506 if (!NT_STATUS_IS_OK(status)) {
7511 * Don't lie to client. If we can't really delete due to
7512 * non-POSIX opens return SHARING_VIOLATION.
7515 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7518 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7519 "lock for file %s\n", fsp_str_dbg(fsp)));
7520 close_file(req, fsp, NORMAL_CLOSE);
7521 return NT_STATUS_INVALID_PARAMETER;
7525 * See if others still have the file open. If this is the case, then
7526 * don't delete. If all opens are POSIX delete we can set the delete
7527 * on close disposition.
7529 for (i=0; i<lck->num_share_modes; i++) {
7530 struct share_mode_entry *e = &lck->share_modes[i];
7531 if (is_valid_share_mode_entry(e)) {
7532 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7535 /* Fail with sharing violation. */
7536 close_file(req, fsp, NORMAL_CLOSE);
7538 return NT_STATUS_SHARING_VIOLATION;
7543 * Set the delete on close.
7545 status = smb_set_file_disposition_info(conn,
7551 if (!NT_STATUS_IS_OK(status)) {
7552 close_file(req, fsp, NORMAL_CLOSE);
7557 return close_file(req, fsp, NORMAL_CLOSE);
7560 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7561 struct smb_request *req,
7562 TALLOC_CTX *mem_ctx,
7563 uint16_t info_level,
7565 struct smb_filename *smb_fname,
7566 char **ppdata, int total_data,
7569 char *pdata = *ppdata;
7570 NTSTATUS status = NT_STATUS_OK;
7571 int data_return_size = 0;
7575 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7576 return NT_STATUS_INVALID_LEVEL;
7579 if (!CAN_WRITE(conn)) {
7580 /* Allow POSIX opens. The open path will deny
7581 * any non-readonly opens. */
7582 if (info_level != SMB_POSIX_PATH_OPEN) {
7583 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7587 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7588 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7589 fsp ? fsp->fnum : -1, info_level, total_data));
7591 switch (info_level) {
7593 case SMB_INFO_STANDARD:
7595 status = smb_set_info_standard(conn,
7603 case SMB_INFO_SET_EA:
7605 status = smb_info_set_ea(conn,
7613 case SMB_SET_FILE_BASIC_INFO:
7614 case SMB_FILE_BASIC_INFORMATION:
7616 status = smb_set_file_basic_info(conn,
7624 case SMB_FILE_ALLOCATION_INFORMATION:
7625 case SMB_SET_FILE_ALLOCATION_INFO:
7627 status = smb_set_file_allocation_info(conn, req,
7635 case SMB_FILE_END_OF_FILE_INFORMATION:
7636 case SMB_SET_FILE_END_OF_FILE_INFO:
7639 * XP/Win7 both fail after the createfile with
7640 * SMB_SET_FILE_END_OF_FILE_INFO but not
7641 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7642 * The level is known here, so pass it down
7646 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7648 status = smb_set_file_end_of_file_info(conn, req,
7657 case SMB_FILE_DISPOSITION_INFORMATION:
7658 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7661 /* JRA - We used to just ignore this on a path ?
7662 * Shouldn't this be invalid level on a pathname
7665 if (tran_call != TRANSACT2_SETFILEINFO) {
7666 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7669 status = smb_set_file_disposition_info(conn,
7677 case SMB_FILE_POSITION_INFORMATION:
7679 status = smb_file_position_information(conn,
7686 case SMB_FILE_FULL_EA_INFORMATION:
7688 status = smb_set_file_full_ea_info(conn,
7695 /* From tridge Samba4 :
7696 * MODE_INFORMATION in setfileinfo (I have no
7697 * idea what "mode information" on a file is - it takes a value of 0,
7698 * 2, 4 or 6. What could it be?).
7701 case SMB_FILE_MODE_INFORMATION:
7703 status = smb_file_mode_information(conn,
7710 * CIFS UNIX extensions.
7713 case SMB_SET_FILE_UNIX_BASIC:
7715 status = smb_set_file_unix_basic(conn, req,
7723 case SMB_SET_FILE_UNIX_INFO2:
7725 status = smb_set_file_unix_info2(conn, req,
7733 case SMB_SET_FILE_UNIX_LINK:
7736 /* We must have a pathname for this. */
7737 return NT_STATUS_INVALID_LEVEL;
7739 status = smb_set_file_unix_link(conn, req, pdata,
7740 total_data, smb_fname);
7744 case SMB_SET_FILE_UNIX_HLINK:
7747 /* We must have a pathname for this. */
7748 return NT_STATUS_INVALID_LEVEL;
7750 status = smb_set_file_unix_hlink(conn, req,
7756 case SMB_FILE_RENAME_INFORMATION:
7758 status = smb_file_rename_information(conn, req,
7764 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7766 /* SMB2 rename information. */
7767 status = smb2_file_rename_information(conn, req,
7773 case SMB_FILE_LINK_INFORMATION:
7775 status = smb_file_link_information(conn, req,
7781 #if defined(HAVE_POSIX_ACLS)
7782 case SMB_SET_POSIX_ACL:
7784 status = smb_set_posix_acl(conn,
7793 case SMB_SET_POSIX_LOCK:
7796 return NT_STATUS_INVALID_LEVEL;
7798 status = smb_set_posix_lock(conn, req,
7799 pdata, total_data, fsp);
7803 case SMB_POSIX_PATH_OPEN:
7806 /* We must have a pathname for this. */
7807 return NT_STATUS_INVALID_LEVEL;
7810 status = smb_posix_open(conn, req,
7818 case SMB_POSIX_PATH_UNLINK:
7821 /* We must have a pathname for this. */
7822 return NT_STATUS_INVALID_LEVEL;
7825 status = smb_posix_unlink(conn, req,
7833 return NT_STATUS_INVALID_LEVEL;
7836 if (!NT_STATUS_IS_OK(status)) {
7840 *ret_data_size = data_return_size;
7841 return NT_STATUS_OK;
7844 /****************************************************************************
7845 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7846 ****************************************************************************/
7848 static void call_trans2setfilepathinfo(connection_struct *conn,
7849 struct smb_request *req,
7850 unsigned int tran_call,
7851 char **pparams, int total_params,
7852 char **ppdata, int total_data,
7853 unsigned int max_data_bytes)
7855 char *params = *pparams;
7856 char *pdata = *ppdata;
7858 struct smb_filename *smb_fname = NULL;
7859 files_struct *fsp = NULL;
7860 NTSTATUS status = NT_STATUS_OK;
7861 int data_return_size = 0;
7864 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7868 if (tran_call == TRANSACT2_SETFILEINFO) {
7869 if (total_params < 4) {
7870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7874 fsp = file_fsp(req, SVAL(params,0));
7875 /* Basic check for non-null fsp. */
7876 if (!check_fsp_open(conn, req, fsp)) {
7879 info_level = SVAL(params,2);
7881 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7883 if (!NT_STATUS_IS_OK(status)) {
7884 reply_nterror(req, status);
7888 if(fsp->fh->fd == -1) {
7890 * This is actually a SETFILEINFO on a directory
7891 * handle (returned from an NT SMB). NT5.0 seems
7892 * to do this call. JRA.
7894 if (INFO_LEVEL_IS_UNIX(info_level)) {
7895 /* Always do lstat for UNIX calls. */
7896 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7897 DEBUG(3,("call_trans2setfilepathinfo: "
7898 "SMB_VFS_LSTAT of %s failed "
7900 smb_fname_str_dbg(smb_fname),
7902 reply_nterror(req, map_nt_error_from_unix(errno));
7906 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7907 DEBUG(3,("call_trans2setfilepathinfo: "
7908 "fileinfo of %s failed (%s)\n",
7909 smb_fname_str_dbg(smb_fname),
7911 reply_nterror(req, map_nt_error_from_unix(errno));
7915 } else if (fsp->print_file) {
7917 * Doing a DELETE_ON_CLOSE should cancel a print job.
7919 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7920 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7922 DEBUG(3,("call_trans2setfilepathinfo: "
7923 "Cancelling print job (%s)\n",
7927 send_trans2_replies(conn, req, params, 2,
7933 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7938 * Original code - this is an open file.
7940 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7941 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7942 "of fnum %d failed (%s)\n", fsp->fnum,
7944 reply_nterror(req, map_nt_error_from_unix(errno));
7952 if (total_params < 7) {
7953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7957 info_level = SVAL(params,0);
7958 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7959 total_params - 6, STR_TERMINATE,
7961 if (!NT_STATUS_IS_OK(status)) {
7962 reply_nterror(req, status);
7966 status = filename_convert(req, conn,
7967 req->flags2 & FLAGS2_DFS_PATHNAMES,
7972 if (!NT_STATUS_IS_OK(status)) {
7973 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7974 reply_botherror(req,
7975 NT_STATUS_PATH_NOT_COVERED,
7976 ERRSRV, ERRbadpath);
7979 reply_nterror(req, status);
7983 if (INFO_LEVEL_IS_UNIX(info_level)) {
7985 * For CIFS UNIX extensions the target name may not exist.
7988 /* Always do lstat for UNIX calls. */
7989 SMB_VFS_LSTAT(conn, smb_fname);
7991 } else if (!VALID_STAT(smb_fname->st) &&
7992 SMB_VFS_STAT(conn, smb_fname)) {
7993 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7995 smb_fname_str_dbg(smb_fname),
7997 reply_nterror(req, map_nt_error_from_unix(errno));
8002 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8003 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8004 fsp ? fsp->fnum : -1, info_level,total_data));
8006 /* Realloc the parameter size */
8007 *pparams = (char *)SMB_REALLOC(*pparams,2);
8008 if (*pparams == NULL) {
8009 reply_nterror(req, NT_STATUS_NO_MEMORY);
8016 status = smbd_do_setfilepathinfo(conn, req, req,
8022 if (!NT_STATUS_IS_OK(status)) {
8023 if (open_was_deferred(req->mid)) {
8024 /* We have re-scheduled this call. */
8027 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8028 /* We have re-scheduled this call. */
8031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8032 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8033 ERRSRV, ERRbadpath);
8036 if (info_level == SMB_POSIX_PATH_OPEN) {
8037 reply_openerror(req, status);
8041 reply_nterror(req, status);
8045 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8051 /****************************************************************************
8052 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8053 ****************************************************************************/
8055 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8056 char **pparams, int total_params,
8057 char **ppdata, int total_data,
8058 unsigned int max_data_bytes)
8060 struct smb_filename *smb_dname = NULL;
8061 char *params = *pparams;
8062 char *pdata = *ppdata;
8063 char *directory = NULL;
8064 NTSTATUS status = NT_STATUS_OK;
8065 struct ea_list *ea_list = NULL;
8066 TALLOC_CTX *ctx = talloc_tos();
8068 if (!CAN_WRITE(conn)) {
8069 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8073 if (total_params < 5) {
8074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8078 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8079 total_params - 4, STR_TERMINATE,
8081 if (!NT_STATUS_IS_OK(status)) {
8082 reply_nterror(req, status);
8086 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8088 status = filename_convert(ctx,
8090 req->flags2 & FLAGS2_DFS_PATHNAMES,
8096 if (!NT_STATUS_IS_OK(status)) {
8097 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8098 reply_botherror(req,
8099 NT_STATUS_PATH_NOT_COVERED,
8100 ERRSRV, ERRbadpath);
8103 reply_nterror(req, status);
8108 * OS/2 workplace shell seems to send SET_EA requests of "null"
8109 * length (4 bytes containing IVAL 4).
8110 * They seem to have no effect. Bug #3212. JRA.
8113 if (total_data && (total_data != 4)) {
8114 /* Any data in this call is an EA list. */
8115 if (total_data < 10) {
8116 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8120 if (IVAL(pdata,0) > total_data) {
8121 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8122 IVAL(pdata,0), (unsigned int)total_data));
8123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8127 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8134 if (!lp_ea_support(SNUM(conn))) {
8135 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8139 /* If total_data == 4 Windows doesn't care what values
8140 * are placed in that field, it just ignores them.
8141 * The System i QNTC IBM SMB client puts bad values here,
8142 * so ignore them. */
8144 status = create_directory(conn, req, smb_dname);
8146 if (!NT_STATUS_IS_OK(status)) {
8147 reply_nterror(req, status);
8151 /* Try and set any given EA. */
8153 status = set_ea(conn, NULL, smb_dname, ea_list);
8154 if (!NT_STATUS_IS_OK(status)) {
8155 reply_nterror(req, status);
8160 /* Realloc the parameter and data sizes */
8161 *pparams = (char *)SMB_REALLOC(*pparams,2);
8162 if(*pparams == NULL) {
8163 reply_nterror(req, NT_STATUS_NO_MEMORY);
8170 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8173 TALLOC_FREE(smb_dname);
8177 /****************************************************************************
8178 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8179 We don't actually do this - we just send a null response.
8180 ****************************************************************************/
8182 static void call_trans2findnotifyfirst(connection_struct *conn,
8183 struct smb_request *req,
8184 char **pparams, int total_params,
8185 char **ppdata, int total_data,
8186 unsigned int max_data_bytes)
8188 char *params = *pparams;
8191 if (total_params < 6) {
8192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8196 info_level = SVAL(params,4);
8197 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8199 switch (info_level) {
8204 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8208 /* Realloc the parameter and data sizes */
8209 *pparams = (char *)SMB_REALLOC(*pparams,6);
8210 if (*pparams == NULL) {
8211 reply_nterror(req, NT_STATUS_NO_MEMORY);
8216 SSVAL(params,0,fnf_handle);
8217 SSVAL(params,2,0); /* No changes */
8218 SSVAL(params,4,0); /* No EA errors */
8225 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8230 /****************************************************************************
8231 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8232 changes). Currently this does nothing.
8233 ****************************************************************************/
8235 static void call_trans2findnotifynext(connection_struct *conn,
8236 struct smb_request *req,
8237 char **pparams, int total_params,
8238 char **ppdata, int total_data,
8239 unsigned int max_data_bytes)
8241 char *params = *pparams;
8243 DEBUG(3,("call_trans2findnotifynext\n"));
8245 /* Realloc the parameter and data sizes */
8246 *pparams = (char *)SMB_REALLOC(*pparams,4);
8247 if (*pparams == NULL) {
8248 reply_nterror(req, NT_STATUS_NO_MEMORY);
8253 SSVAL(params,0,0); /* No changes */
8254 SSVAL(params,2,0); /* No EA errors */
8256 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8261 /****************************************************************************
8262 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8263 ****************************************************************************/
8265 static void call_trans2getdfsreferral(connection_struct *conn,
8266 struct smb_request *req,
8267 char **pparams, int total_params,
8268 char **ppdata, int total_data,
8269 unsigned int max_data_bytes)
8271 char *params = *pparams;
8272 char *pathname = NULL;
8274 int max_referral_level;
8275 NTSTATUS status = NT_STATUS_OK;
8276 TALLOC_CTX *ctx = talloc_tos();
8278 DEBUG(10,("call_trans2getdfsreferral\n"));
8280 if (total_params < 3) {
8281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8285 max_referral_level = SVAL(params,0);
8287 if(!lp_host_msdfs()) {
8288 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8292 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8293 total_params - 2, STR_TERMINATE);
8295 reply_nterror(req, NT_STATUS_NOT_FOUND);
8298 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8299 ppdata,&status)) < 0) {
8300 reply_nterror(req, status);
8304 SSVAL(req->inbuf, smb_flg2,
8305 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8306 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8311 #define LMCAT_SPL 0x53
8312 #define LMFUNC_GETJOBID 0x60
8314 /****************************************************************************
8315 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8316 ****************************************************************************/
8318 static void call_trans2ioctl(connection_struct *conn,
8319 struct smb_request *req,
8320 char **pparams, int total_params,
8321 char **ppdata, int total_data,
8322 unsigned int max_data_bytes)
8324 char *pdata = *ppdata;
8325 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8327 /* check for an invalid fid before proceeding */
8330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8334 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8335 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8336 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8337 if (*ppdata == NULL) {
8338 reply_nterror(req, NT_STATUS_NO_MEMORY);
8343 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8344 CAN ACCEPT THIS IN UNICODE. JRA. */
8347 if (fsp->print_file) {
8348 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8352 srvstr_push(pdata, req->flags2, pdata + 2,
8353 global_myname(), 15,
8354 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8355 srvstr_push(pdata, req->flags2, pdata+18,
8356 lp_servicename(SNUM(conn)), 13,
8357 STR_ASCII|STR_TERMINATE); /* Service name */
8358 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8363 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8364 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8367 /****************************************************************************
8368 Reply to a SMBfindclose (stop trans2 directory search).
8369 ****************************************************************************/
8371 void reply_findclose(struct smb_request *req)
8374 struct smbd_server_connection *sconn = req->sconn;
8376 START_PROFILE(SMBfindclose);
8379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8380 END_PROFILE(SMBfindclose);
8384 dptr_num = SVALS(req->vwv+0, 0);
8386 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8388 dptr_close(sconn, &dptr_num);
8390 reply_outbuf(req, 0, 0);
8392 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8394 END_PROFILE(SMBfindclose);
8398 /****************************************************************************
8399 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8400 ****************************************************************************/
8402 void reply_findnclose(struct smb_request *req)
8406 START_PROFILE(SMBfindnclose);
8409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8410 END_PROFILE(SMBfindnclose);
8414 dptr_num = SVAL(req->vwv+0, 0);
8416 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8418 /* We never give out valid handles for a
8419 findnotifyfirst - so any dptr_num is ok here.
8422 reply_outbuf(req, 0, 0);
8424 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8426 END_PROFILE(SMBfindnclose);
8430 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8431 struct trans_state *state)
8433 if (get_Protocol() >= PROTOCOL_NT1) {
8434 req->flags2 |= 0x40; /* IS_LONG_NAME */
8435 SSVAL(req->inbuf,smb_flg2,req->flags2);
8438 if (conn->encrypt_level == Required && !req->encrypted) {
8439 if (state->call != TRANSACT2_QFSINFO &&
8440 state->call != TRANSACT2_SETFSINFO) {
8441 DEBUG(0,("handle_trans2: encryption required "
8443 (unsigned int)state->call));
8444 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8449 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8451 /* Now we must call the relevant TRANS2 function */
8452 switch(state->call) {
8453 case TRANSACT2_OPEN:
8455 START_PROFILE(Trans2_open);
8456 call_trans2open(conn, req,
8457 &state->param, state->total_param,
8458 &state->data, state->total_data,
8459 state->max_data_return);
8460 END_PROFILE(Trans2_open);
8464 case TRANSACT2_FINDFIRST:
8466 START_PROFILE(Trans2_findfirst);
8467 call_trans2findfirst(conn, req,
8468 &state->param, state->total_param,
8469 &state->data, state->total_data,
8470 state->max_data_return);
8471 END_PROFILE(Trans2_findfirst);
8475 case TRANSACT2_FINDNEXT:
8477 START_PROFILE(Trans2_findnext);
8478 call_trans2findnext(conn, req,
8479 &state->param, state->total_param,
8480 &state->data, state->total_data,
8481 state->max_data_return);
8482 END_PROFILE(Trans2_findnext);
8486 case TRANSACT2_QFSINFO:
8488 START_PROFILE(Trans2_qfsinfo);
8489 call_trans2qfsinfo(conn, req,
8490 &state->param, state->total_param,
8491 &state->data, state->total_data,
8492 state->max_data_return);
8493 END_PROFILE(Trans2_qfsinfo);
8497 case TRANSACT2_SETFSINFO:
8499 START_PROFILE(Trans2_setfsinfo);
8500 call_trans2setfsinfo(conn, req,
8501 &state->param, state->total_param,
8502 &state->data, state->total_data,
8503 state->max_data_return);
8504 END_PROFILE(Trans2_setfsinfo);
8508 case TRANSACT2_QPATHINFO:
8509 case TRANSACT2_QFILEINFO:
8511 START_PROFILE(Trans2_qpathinfo);
8512 call_trans2qfilepathinfo(conn, req, state->call,
8513 &state->param, state->total_param,
8514 &state->data, state->total_data,
8515 state->max_data_return);
8516 END_PROFILE(Trans2_qpathinfo);
8520 case TRANSACT2_SETPATHINFO:
8521 case TRANSACT2_SETFILEINFO:
8523 START_PROFILE(Trans2_setpathinfo);
8524 call_trans2setfilepathinfo(conn, req, state->call,
8525 &state->param, state->total_param,
8526 &state->data, state->total_data,
8527 state->max_data_return);
8528 END_PROFILE(Trans2_setpathinfo);
8532 case TRANSACT2_FINDNOTIFYFIRST:
8534 START_PROFILE(Trans2_findnotifyfirst);
8535 call_trans2findnotifyfirst(conn, req,
8536 &state->param, state->total_param,
8537 &state->data, state->total_data,
8538 state->max_data_return);
8539 END_PROFILE(Trans2_findnotifyfirst);
8543 case TRANSACT2_FINDNOTIFYNEXT:
8545 START_PROFILE(Trans2_findnotifynext);
8546 call_trans2findnotifynext(conn, req,
8547 &state->param, state->total_param,
8548 &state->data, state->total_data,
8549 state->max_data_return);
8550 END_PROFILE(Trans2_findnotifynext);
8554 case TRANSACT2_MKDIR:
8556 START_PROFILE(Trans2_mkdir);
8557 call_trans2mkdir(conn, req,
8558 &state->param, state->total_param,
8559 &state->data, state->total_data,
8560 state->max_data_return);
8561 END_PROFILE(Trans2_mkdir);
8565 case TRANSACT2_GET_DFS_REFERRAL:
8567 START_PROFILE(Trans2_get_dfs_referral);
8568 call_trans2getdfsreferral(conn, req,
8569 &state->param, state->total_param,
8570 &state->data, state->total_data,
8571 state->max_data_return);
8572 END_PROFILE(Trans2_get_dfs_referral);
8576 case TRANSACT2_IOCTL:
8578 START_PROFILE(Trans2_ioctl);
8579 call_trans2ioctl(conn, req,
8580 &state->param, state->total_param,
8581 &state->data, state->total_data,
8582 state->max_data_return);
8583 END_PROFILE(Trans2_ioctl);
8588 /* Error in request */
8589 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8590 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8594 /****************************************************************************
8595 Reply to a SMBtrans2.
8596 ****************************************************************************/
8598 void reply_trans2(struct smb_request *req)
8600 connection_struct *conn = req->conn;
8605 unsigned int tran_call;
8606 struct trans_state *state;
8609 START_PROFILE(SMBtrans2);
8611 if (req->wct < 14) {
8612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8613 END_PROFILE(SMBtrans2);
8617 dsoff = SVAL(req->vwv+12, 0);
8618 dscnt = SVAL(req->vwv+11, 0);
8619 psoff = SVAL(req->vwv+10, 0);
8620 pscnt = SVAL(req->vwv+9, 0);
8621 tran_call = SVAL(req->vwv+14, 0);
8623 result = allow_new_trans(conn->pending_trans, req->mid);
8624 if (!NT_STATUS_IS_OK(result)) {
8625 DEBUG(2, ("Got invalid trans2 request: %s\n",
8626 nt_errstr(result)));
8627 reply_nterror(req, result);
8628 END_PROFILE(SMBtrans2);
8633 switch (tran_call) {
8634 /* List the allowed trans2 calls on IPC$ */
8635 case TRANSACT2_OPEN:
8636 case TRANSACT2_GET_DFS_REFERRAL:
8637 case TRANSACT2_QFILEINFO:
8638 case TRANSACT2_QFSINFO:
8639 case TRANSACT2_SETFSINFO:
8642 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8643 END_PROFILE(SMBtrans2);
8648 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8649 DEBUG(0, ("talloc failed\n"));
8650 reply_nterror(req, NT_STATUS_NO_MEMORY);
8651 END_PROFILE(SMBtrans2);
8655 state->cmd = SMBtrans2;
8657 state->mid = req->mid;
8658 state->vuid = req->vuid;
8659 state->setup_count = SVAL(req->vwv+13, 0);
8660 state->setup = NULL;
8661 state->total_param = SVAL(req->vwv+0, 0);
8662 state->param = NULL;
8663 state->total_data = SVAL(req->vwv+1, 0);
8665 state->max_param_return = SVAL(req->vwv+2, 0);
8666 state->max_data_return = SVAL(req->vwv+3, 0);
8667 state->max_setup_return = SVAL(req->vwv+4, 0);
8668 state->close_on_completion = BITSETW(req->vwv+5, 0);
8669 state->one_way = BITSETW(req->vwv+5, 1);
8671 state->call = tran_call;
8673 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8674 is so as a sanity check */
8675 if (state->setup_count != 1) {
8677 * Need to have rc=0 for ioctl to get job id for OS/2.
8678 * Network printing will fail if function is not successful.
8679 * Similar function in reply.c will be used if protocol
8680 * is LANMAN1.0 instead of LM1.2X002.
8681 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8682 * outbuf doesn't have to be set(only job id is used).
8684 if ( (state->setup_count == 4)
8685 && (tran_call == TRANSACT2_IOCTL)
8686 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8687 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8688 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8690 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8691 DEBUG(2,("Transaction is %d\n",tran_call));
8693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8694 END_PROFILE(SMBtrans2);
8699 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8702 if (state->total_data) {
8704 if (trans_oob(state->total_data, 0, dscnt)
8705 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8709 /* Can't use talloc here, the core routines do realloc on the
8710 * params and data. */
8711 state->data = (char *)SMB_MALLOC(state->total_data);
8712 if (state->data == NULL) {
8713 DEBUG(0,("reply_trans2: data malloc fail for %u "
8714 "bytes !\n", (unsigned int)state->total_data));
8716 reply_nterror(req, NT_STATUS_NO_MEMORY);
8717 END_PROFILE(SMBtrans2);
8721 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8724 if (state->total_param) {
8726 if (trans_oob(state->total_param, 0, pscnt)
8727 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8731 /* Can't use talloc here, the core routines do realloc on the
8732 * params and data. */
8733 state->param = (char *)SMB_MALLOC(state->total_param);
8734 if (state->param == NULL) {
8735 DEBUG(0,("reply_trans: param malloc fail for %u "
8736 "bytes !\n", (unsigned int)state->total_param));
8737 SAFE_FREE(state->data);
8739 reply_nterror(req, NT_STATUS_NO_MEMORY);
8740 END_PROFILE(SMBtrans2);
8744 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8747 state->received_data = dscnt;
8748 state->received_param = pscnt;
8750 if ((state->received_param == state->total_param) &&
8751 (state->received_data == state->total_data)) {
8753 handle_trans2(conn, req, state);
8755 SAFE_FREE(state->data);
8756 SAFE_FREE(state->param);
8758 END_PROFILE(SMBtrans2);
8762 DLIST_ADD(conn->pending_trans, state);
8764 /* We need to send an interim response then receive the rest
8765 of the parameter/data bytes */
8766 reply_outbuf(req, 0, 0);
8767 show_msg((char *)req->outbuf);
8768 END_PROFILE(SMBtrans2);
8773 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8774 SAFE_FREE(state->data);
8775 SAFE_FREE(state->param);
8777 END_PROFILE(SMBtrans2);
8778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8782 /****************************************************************************
8783 Reply to a SMBtranss2
8784 ****************************************************************************/
8786 void reply_transs2(struct smb_request *req)
8788 connection_struct *conn = req->conn;
8789 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8790 struct trans_state *state;
8792 START_PROFILE(SMBtranss2);
8794 show_msg((char *)req->inbuf);
8797 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8798 END_PROFILE(SMBtranss2);
8802 for (state = conn->pending_trans; state != NULL;
8803 state = state->next) {
8804 if (state->mid == req->mid) {
8809 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8811 END_PROFILE(SMBtranss2);
8815 /* Revise state->total_param and state->total_data in case they have
8816 changed downwards */
8818 if (SVAL(req->vwv+0, 0) < state->total_param)
8819 state->total_param = SVAL(req->vwv+0, 0);
8820 if (SVAL(req->vwv+1, 0) < state->total_data)
8821 state->total_data = SVAL(req->vwv+1, 0);
8823 pcnt = SVAL(req->vwv+2, 0);
8824 poff = SVAL(req->vwv+3, 0);
8825 pdisp = SVAL(req->vwv+4, 0);
8827 dcnt = SVAL(req->vwv+5, 0);
8828 doff = SVAL(req->vwv+6, 0);
8829 ddisp = SVAL(req->vwv+7, 0);
8831 state->received_param += pcnt;
8832 state->received_data += dcnt;
8834 if ((state->received_data > state->total_data) ||
8835 (state->received_param > state->total_param))
8839 if (trans_oob(state->total_param, pdisp, pcnt)
8840 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8843 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8847 if (trans_oob(state->total_data, ddisp, dcnt)
8848 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8851 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8854 if ((state->received_param < state->total_param) ||
8855 (state->received_data < state->total_data)) {
8856 END_PROFILE(SMBtranss2);
8860 handle_trans2(conn, req, state);
8862 DLIST_REMOVE(conn->pending_trans, state);
8863 SAFE_FREE(state->data);
8864 SAFE_FREE(state->param);
8867 END_PROFILE(SMBtranss2);
8872 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8873 DLIST_REMOVE(conn->pending_trans, state);
8874 SAFE_FREE(state->data);
8875 SAFE_FREE(state->param);
8877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8878 END_PROFILE(SMBtranss2);