2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
75 SAMBA_XATTR_DOSTIMESTAMPS,
81 for (i = 0; prohibited_ea_names[i]; i++) {
82 if (strequal( prohibited_ea_names[i], unix_ea_name))
85 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
86 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
92 /****************************************************************************
93 Get one EA value. Fill in a struct ea_struct.
94 ****************************************************************************/
96 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
97 files_struct *fsp, const char *fname,
98 const char *ea_name, struct ea_struct *pea)
100 /* Get the value of this xattr. Max size is 64k. */
101 size_t attr_size = 256;
107 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
109 return NT_STATUS_NO_MEMORY;
112 if (fsp && fsp->fh->fd != -1) {
113 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
115 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
118 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
124 return map_nt_error_from_unix(errno);
127 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
128 dump_data(10, (uint8 *)val, sizeret);
131 if (strnequal(ea_name, "user.", 5)) {
132 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
134 pea->name = talloc_strdup(mem_ctx, ea_name);
136 if (pea->name == NULL) {
138 return NT_STATUS_NO_MEMORY;
140 pea->value.data = (unsigned char *)val;
141 pea->value.length = (size_t)sizeret;
145 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
146 files_struct *fsp, const char *fname,
147 char ***pnames, size_t *pnum_names)
149 /* Get a list of all xattrs. Max namesize is 64k. */
150 size_t ea_namelist_size = 1024;
151 char *ea_namelist = NULL;
156 ssize_t sizeret = -1;
158 if (!lp_ea_support(SNUM(conn))) {
165 * TALLOC the result early to get the talloc hierarchy right.
168 names = TALLOC_ARRAY(mem_ctx, char *, 1);
170 DEBUG(0, ("talloc failed\n"));
171 return NT_STATUS_NO_MEMORY;
174 while (ea_namelist_size <= 65536) {
176 ea_namelist = TALLOC_REALLOC_ARRAY(
177 names, ea_namelist, char, ea_namelist_size);
178 if (ea_namelist == NULL) {
179 DEBUG(0, ("talloc failed\n"));
181 return NT_STATUS_NO_MEMORY;
184 if (fsp && fsp->fh->fd != -1) {
185 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
188 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
192 if ((sizeret == -1) && (errno == ERANGE)) {
193 ea_namelist_size *= 2;
202 return map_nt_error_from_unix(errno);
205 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
206 (unsigned int)sizeret));
216 * Ensure the result is 0-terminated
219 if (ea_namelist[sizeret-1] != '\0') {
221 return NT_STATUS_INTERNAL_ERROR;
229 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
233 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
235 DEBUG(0, ("talloc failed\n"));
237 return NT_STATUS_NO_MEMORY;
243 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
244 names[num_names++] = p;
248 *pnum_names = num_names;
252 /****************************************************************************
253 Return a linked list of the total EA's. Plus the total size
254 ****************************************************************************/
256 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
257 const char *fname, size_t *pea_total_len)
259 /* Get a list of all xattrs. Max namesize is 64k. */
262 struct ea_list *ea_list_head = NULL;
267 if (!lp_ea_support(SNUM(conn))) {
271 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
274 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
278 for (i=0; i<num_names; i++) {
279 struct ea_list *listp;
282 if (strnequal(names[i], "system.", 7)
283 || samba_private_attr_name(names[i]))
286 listp = TALLOC_P(mem_ctx, struct ea_list);
291 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
297 push_ascii_fstring(dos_ea_name, listp->ea.name);
300 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
302 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
303 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
304 (unsigned int)listp->ea.value.length));
306 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
310 /* Add on 4 for total length. */
311 if (*pea_total_len) {
315 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
316 (unsigned int)*pea_total_len));
321 /****************************************************************************
322 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
324 ****************************************************************************/
326 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
327 connection_struct *conn, struct ea_list *ea_list)
329 unsigned int ret_data_size = 4;
332 SMB_ASSERT(total_data_size >= 4);
334 if (!lp_ea_support(SNUM(conn))) {
339 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
342 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
343 dos_namelen = strlen(dos_ea_name);
344 if (dos_namelen > 255 || dos_namelen == 0) {
347 if (ea_list->ea.value.length > 65535) {
350 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
354 /* We know we have room. */
355 SCVAL(p,0,ea_list->ea.flags);
356 SCVAL(p,1,dos_namelen);
357 SSVAL(p,2,ea_list->ea.value.length);
358 fstrcpy(p+4, dos_ea_name);
359 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
361 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
362 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
365 ret_data_size = PTR_DIFF(p, pdata);
366 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
367 SIVAL(pdata,0,ret_data_size);
368 return ret_data_size;
371 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
373 unsigned int total_data_size,
374 unsigned int *ret_data_size,
375 connection_struct *conn,
376 struct ea_list *ea_list)
378 uint8_t *p = (uint8_t *)pdata;
379 uint8_t *last_start = NULL;
383 if (!lp_ea_support(SNUM(conn))) {
384 return NT_STATUS_NO_EAS_ON_FILE;
387 for (; ea_list; ea_list = ea_list->next) {
393 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
397 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
398 dos_namelen = strlen(dos_ea_name);
399 if (dos_namelen > 255 || dos_namelen == 0) {
400 return NT_STATUS_INTERNAL_ERROR;
402 if (ea_list->ea.value.length > 65535) {
403 return NT_STATUS_INTERNAL_ERROR;
406 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
409 size_t pad = 4 - (this_size % 4);
413 if (this_size > total_data_size) {
414 return NT_STATUS_INFO_LENGTH_MISMATCH;
417 /* We know we have room. */
418 SIVAL(p, 0x00, 0); /* next offset */
419 SCVAL(p, 0x04, ea_list->ea.flags);
420 SCVAL(p, 0x05, dos_namelen);
421 SSVAL(p, 0x06, ea_list->ea.value.length);
422 fstrcpy((char *)(p+0x08), dos_ea_name);
423 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
425 total_data_size -= this_size;
429 *ret_data_size = PTR_DIFF(p, pdata);
430 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
434 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
436 size_t total_ea_len = 0;
437 TALLOC_CTX *mem_ctx = NULL;
439 if (!lp_ea_support(SNUM(conn))) {
442 mem_ctx = talloc_tos();
443 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
447 /****************************************************************************
448 Ensure the EA name is case insensitive by matching any existing EA name.
449 ****************************************************************************/
451 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
454 TALLOC_CTX *mem_ctx = talloc_tos();
455 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
457 for (; ea_list; ea_list = ea_list->next) {
458 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
459 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
460 &unix_ea_name[5], ea_list->ea.name));
461 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
467 /****************************************************************************
468 Set or delete an extended attribute.
469 ****************************************************************************/
471 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
472 const struct smb_filename *smb_fname, struct ea_list *ea_list)
476 if (!lp_ea_support(SNUM(conn))) {
477 return NT_STATUS_EAS_NOT_SUPPORTED;
480 /* For now setting EAs on streams isn't supported. */
481 fname = smb_fname->base_name;
483 for (;ea_list; ea_list = ea_list->next) {
485 fstring unix_ea_name;
487 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
488 fstrcat(unix_ea_name, ea_list->ea.name);
490 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
492 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
494 if (samba_private_attr_name(unix_ea_name)) {
495 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
496 return NT_STATUS_ACCESS_DENIED;
499 if (ea_list->ea.value.length == 0) {
500 /* Remove the attribute. */
501 if (fsp && (fsp->fh->fd != -1)) {
502 DEBUG(10,("set_ea: deleting ea name %s on "
503 "file %s by file descriptor.\n",
504 unix_ea_name, fsp_str_dbg(fsp)));
505 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
507 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
508 unix_ea_name, fname));
509 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
512 /* Removing a non existent attribute always succeeds. */
513 if (ret == -1 && errno == ENOATTR) {
514 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
520 if (fsp && (fsp->fh->fd != -1)) {
521 DEBUG(10,("set_ea: setting ea name %s on file "
522 "%s by file descriptor.\n",
523 unix_ea_name, fsp_str_dbg(fsp)));
524 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
525 ea_list->ea.value.data, ea_list->ea.value.length, 0);
527 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
528 unix_ea_name, fname));
529 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
530 ea_list->ea.value.data, ea_list->ea.value.length, 0);
536 if (errno == ENOTSUP) {
537 return NT_STATUS_EAS_NOT_SUPPORTED;
540 return map_nt_error_from_unix(errno);
546 /****************************************************************************
547 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
548 ****************************************************************************/
550 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
552 struct ea_list *ea_list_head = NULL;
553 size_t converted_size, offset = 0;
555 while (offset + 2 < data_size) {
556 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
557 unsigned int namelen = CVAL(pdata,offset);
559 offset++; /* Go past the namelen byte. */
561 /* integer wrap paranioa. */
562 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
563 (offset > data_size) || (namelen > data_size) ||
564 (offset + namelen >= data_size)) {
567 /* Ensure the name is null terminated. */
568 if (pdata[offset + namelen] != '\0') {
571 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
573 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
574 "failed: %s", strerror(errno)));
580 offset += (namelen + 1); /* Go past the name + terminating zero. */
581 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
582 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
588 /****************************************************************************
589 Read one EA list entry from the buffer.
590 ****************************************************************************/
592 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
594 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
596 unsigned int namelen;
597 size_t converted_size;
607 eal->ea.flags = CVAL(pdata,0);
608 namelen = CVAL(pdata,1);
609 val_len = SVAL(pdata,2);
611 if (4 + namelen + 1 + val_len > data_size) {
615 /* Ensure the name is null terminated. */
616 if (pdata[namelen + 4] != '\0') {
619 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
620 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
627 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
628 if (!eal->ea.value.data) {
632 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
634 /* Ensure we're null terminated just in case we print the value. */
635 eal->ea.value.data[val_len] = '\0';
636 /* But don't count the null. */
637 eal->ea.value.length--;
640 *pbytes_used = 4 + namelen + 1 + val_len;
643 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
644 dump_data(10, eal->ea.value.data, eal->ea.value.length);
649 /****************************************************************************
650 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
651 ****************************************************************************/
653 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
655 struct ea_list *ea_list_head = NULL;
657 size_t bytes_used = 0;
659 while (offset < data_size) {
660 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
666 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
667 offset += bytes_used;
673 /****************************************************************************
674 Count the total EA size needed.
675 ****************************************************************************/
677 static size_t ea_list_size(struct ea_list *ealist)
680 struct ea_list *listp;
683 for (listp = ealist; listp; listp = listp->next) {
684 push_ascii_fstring(dos_ea_name, listp->ea.name);
685 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
687 /* Add on 4 for total length. */
695 /****************************************************************************
696 Return a union of EA's from a file list and a list of names.
697 The TALLOC context for the two lists *MUST* be identical as we steal
698 memory from one list to add to another. JRA.
699 ****************************************************************************/
701 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
703 struct ea_list *nlistp, *flistp;
705 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
706 for (flistp = file_list; flistp; flistp = flistp->next) {
707 if (strequal(nlistp->ea.name, flistp->ea.name)) {
713 /* Copy the data from this entry. */
714 nlistp->ea.flags = flistp->ea.flags;
715 nlistp->ea.value = flistp->ea.value;
718 nlistp->ea.flags = 0;
719 ZERO_STRUCT(nlistp->ea.value);
723 *total_ea_len = ea_list_size(name_list);
727 /****************************************************************************
728 Send the required number of replies back.
729 We assume all fields other than the data fields are
730 set correctly for the type of call.
731 HACK ! Always assumes smb_setup field is zero.
732 ****************************************************************************/
734 void send_trans2_replies(connection_struct *conn,
735 struct smb_request *req,
742 /* As we are using a protocol > LANMAN1 then the max_send
743 variable must have been set in the sessetupX call.
744 This takes precedence over the max_xmit field in the
745 global struct. These different max_xmit variables should
746 be merged as this is now too confusing */
748 int data_to_send = datasize;
749 int params_to_send = paramsize;
751 const char *pp = params;
752 const char *pd = pdata;
753 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
754 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
755 int data_alignment_offset = 0;
756 bool overflow = False;
757 struct smbd_server_connection *sconn = smbd_server_conn;
758 int max_send = sconn->smb1.sessions.max_send;
760 /* Modify the data_to_send and datasize and set the error if
761 we're trying to send more than max_data_bytes. We still send
762 the part of the packet(s) that fit. Strange, but needed
765 if (max_data_bytes > 0 && datasize > max_data_bytes) {
766 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
767 max_data_bytes, datasize ));
768 datasize = data_to_send = max_data_bytes;
772 /* If there genuinely are no parameters or data to send just send the empty packet */
774 if(params_to_send == 0 && data_to_send == 0) {
775 reply_outbuf(req, 10, 0);
776 show_msg((char *)req->outbuf);
777 if (!srv_send_smb(smbd_server_fd(),
780 IS_CONN_ENCRYPTED(conn),
782 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
784 TALLOC_FREE(req->outbuf);
788 /* When sending params and data ensure that both are nicely aligned */
789 /* Only do this alignment when there is also data to send - else
790 can cause NT redirector problems. */
792 if (((params_to_send % 4) != 0) && (data_to_send != 0))
793 data_alignment_offset = 4 - (params_to_send % 4);
795 /* Space is bufsize minus Netbios over TCP header minus SMB header */
796 /* The alignment_offset is to align the param bytes on an even byte
797 boundary. NT 4.0 Beta needs this to work correctly. */
799 useable_space = max_send - (smb_size
802 + data_alignment_offset);
804 if (useable_space < 0) {
805 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
806 "= %d!!!", useable_space));
807 exit_server_cleanly("send_trans2_replies: Not enough space");
810 while (params_to_send || data_to_send) {
811 /* Calculate whether we will totally or partially fill this packet */
813 total_sent_thistime = params_to_send + data_to_send;
815 /* We can never send more than useable_space */
817 * Note that 'useable_space' does not include the alignment offsets,
818 * but we must include the alignment offsets in the calculation of
819 * the length of the data we send over the wire, as the alignment offsets
820 * are sent here. Fix from Marc_Jacobsen@hp.com.
823 total_sent_thistime = MIN(total_sent_thistime, useable_space);
825 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
826 + data_alignment_offset);
829 * We might have SMBtrans2s in req which was transferred to
830 * the outbuf, fix that.
832 SCVAL(req->outbuf, smb_com, SMBtrans2);
834 /* Set total params and data to be sent */
835 SSVAL(req->outbuf,smb_tprcnt,paramsize);
836 SSVAL(req->outbuf,smb_tdrcnt,datasize);
838 /* Calculate how many parameters and data we can fit into
839 * this packet. Parameters get precedence
842 params_sent_thistime = MIN(params_to_send,useable_space);
843 data_sent_thistime = useable_space - params_sent_thistime;
844 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
846 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
848 /* smb_proff is the offset from the start of the SMB header to the
849 parameter bytes, however the first 4 bytes of outbuf are
850 the Netbios over TCP header. Thus use smb_base() to subtract
851 them from the calculation */
853 SSVAL(req->outbuf,smb_proff,
854 ((smb_buf(req->outbuf)+alignment_offset)
855 - smb_base(req->outbuf)));
857 if(params_sent_thistime == 0)
858 SSVAL(req->outbuf,smb_prdisp,0);
860 /* Absolute displacement of param bytes sent in this packet */
861 SSVAL(req->outbuf,smb_prdisp,pp - params);
863 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
864 if(data_sent_thistime == 0) {
865 SSVAL(req->outbuf,smb_droff,0);
866 SSVAL(req->outbuf,smb_drdisp, 0);
868 /* The offset of the data bytes is the offset of the
869 parameter bytes plus the number of parameters being sent this time */
870 SSVAL(req->outbuf, smb_droff,
871 ((smb_buf(req->outbuf)+alignment_offset)
872 - smb_base(req->outbuf))
873 + params_sent_thistime + data_alignment_offset);
874 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
877 /* Initialize the padding for alignment */
879 if (alignment_offset != 0) {
880 memset(smb_buf(req->outbuf), 0, alignment_offset);
883 /* Copy the param bytes into the packet */
885 if(params_sent_thistime) {
886 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
887 params_sent_thistime);
890 /* Copy in the data bytes */
891 if(data_sent_thistime) {
892 if (data_alignment_offset != 0) {
893 memset((smb_buf(req->outbuf)+alignment_offset+
894 params_sent_thistime), 0,
895 data_alignment_offset);
897 memcpy(smb_buf(req->outbuf)+alignment_offset
898 +params_sent_thistime+data_alignment_offset,
899 pd,data_sent_thistime);
902 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
903 params_sent_thistime, data_sent_thistime, useable_space));
904 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
905 params_to_send, data_to_send, paramsize, datasize));
908 error_packet_set((char *)req->outbuf,
909 ERRDOS,ERRbufferoverflow,
910 STATUS_BUFFER_OVERFLOW,
914 /* Send the packet */
915 show_msg((char *)req->outbuf);
916 if (!srv_send_smb(smbd_server_fd(),
919 IS_CONN_ENCRYPTED(conn),
921 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
923 TALLOC_FREE(req->outbuf);
925 pp += params_sent_thistime;
926 pd += data_sent_thistime;
928 params_to_send -= params_sent_thistime;
929 data_to_send -= data_sent_thistime;
932 if(params_to_send < 0 || data_to_send < 0) {
933 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
934 params_to_send, data_to_send));
942 /****************************************************************************
943 Reply to a TRANSACT2_OPEN.
944 ****************************************************************************/
946 static void call_trans2open(connection_struct *conn,
947 struct smb_request *req,
948 char **pparams, int total_params,
949 char **ppdata, int total_data,
950 unsigned int max_data_bytes)
952 struct smb_filename *smb_fname = NULL;
953 char *params = *pparams;
954 char *pdata = *ppdata;
959 bool return_additional_info;
972 struct ea_list *ea_list = NULL;
977 uint32 create_disposition;
978 uint32 create_options = 0;
979 TALLOC_CTX *ctx = talloc_tos();
982 * Ensure we have enough parameters to perform the operation.
985 if (total_params < 29) {
986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
990 flags = SVAL(params, 0);
991 deny_mode = SVAL(params, 2);
992 open_attr = SVAL(params,6);
993 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
994 if (oplock_request) {
995 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
999 return_additional_info = BITSETW(params,0);
1000 open_sattr = SVAL(params, 4);
1001 open_time = make_unix_date3(params+8);
1003 open_ofun = SVAL(params,12);
1004 open_size = IVAL(params,14);
1005 pname = ¶ms[28];
1008 reply_doserror(req, ERRSRV, ERRaccess);
1012 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1013 total_params - 28, STR_TERMINATE,
1015 if (!NT_STATUS_IS_OK(status)) {
1016 reply_nterror(req, status);
1020 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1021 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1022 (unsigned int)open_ofun, open_size));
1024 status = filename_convert(ctx,
1026 req->flags2 & FLAGS2_DFS_PATHNAMES,
1031 if (!NT_STATUS_IS_OK(status)) {
1032 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1033 reply_botherror(req,
1034 NT_STATUS_PATH_NOT_COVERED,
1035 ERRSRV, ERRbadpath);
1038 reply_nterror(req, status);
1042 if (open_ofun == 0) {
1043 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1047 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1048 &access_mask, &share_mode,
1049 &create_disposition,
1051 reply_doserror(req, ERRDOS, ERRbadaccess);
1055 /* Any data in this call is an EA list. */
1056 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1057 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1061 if (total_data != 4) {
1062 if (total_data < 10) {
1063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1067 if (IVAL(pdata,0) > total_data) {
1068 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1069 IVAL(pdata,0), (unsigned int)total_data));
1070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1074 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1080 } else if (IVAL(pdata,0) != 4) {
1081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1085 status = SMB_VFS_CREATE_FILE(
1088 0, /* root_dir_fid */
1089 smb_fname, /* fname */
1090 access_mask, /* access_mask */
1091 share_mode, /* share_access */
1092 create_disposition, /* create_disposition*/
1093 create_options, /* create_options */
1094 open_attr, /* file_attributes */
1095 oplock_request, /* oplock_request */
1096 open_size, /* allocation_size */
1098 ea_list, /* ea_list */
1100 &smb_action); /* psbuf */
1102 if (!NT_STATUS_IS_OK(status)) {
1103 if (open_was_deferred(req->mid)) {
1104 /* We have re-scheduled this call. */
1107 reply_openerror(req, status);
1111 size = get_file_size_stat(&smb_fname->st);
1112 fattr = dos_mode(conn, smb_fname);
1113 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1114 inode = smb_fname->st.st_ex_ino;
1116 close_file(req, fsp, ERROR_CLOSE);
1117 reply_doserror(req, ERRDOS,ERRnoaccess);
1121 /* Realloc the size of parameters and data we will return */
1122 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1123 if(*pparams == NULL ) {
1124 reply_nterror(req, NT_STATUS_NO_MEMORY);
1129 SSVAL(params,0,fsp->fnum);
1130 SSVAL(params,2,fattr);
1131 srv_put_dos_date2(params,4, mtime);
1132 SIVAL(params,8, (uint32)size);
1133 SSVAL(params,12,deny_mode);
1134 SSVAL(params,14,0); /* open_type - file or directory. */
1135 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1137 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1138 smb_action |= EXTENDED_OPLOCK_GRANTED;
1141 SSVAL(params,18,smb_action);
1144 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1146 SIVAL(params,20,inode);
1147 SSVAL(params,24,0); /* Padding. */
1149 uint32 ea_size = estimate_ea_size(conn, fsp,
1150 fsp->fsp_name->base_name);
1151 SIVAL(params, 26, ea_size);
1153 SIVAL(params, 26, 0);
1156 /* Send the required number of replies */
1157 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1159 TALLOC_FREE(smb_fname);
1162 /*********************************************************
1163 Routine to check if a given string matches exactly.
1164 as a special case a mask of "." does NOT match. That
1165 is required for correct wildcard semantics
1166 Case can be significant or not.
1167 **********************************************************/
1169 static bool exact_match(bool has_wild,
1170 bool case_sensitive,
1174 if (mask[0] == '.' && mask[1] == 0) {
1182 if (case_sensitive) {
1183 return strcmp(str,mask)==0;
1185 return StrCaseCmp(str,mask) == 0;
1189 /****************************************************************************
1190 Return the filetype for UNIX extensions.
1191 ****************************************************************************/
1193 static uint32 unix_filetype(mode_t mode)
1196 return UNIX_TYPE_FILE;
1197 else if(S_ISDIR(mode))
1198 return UNIX_TYPE_DIR;
1200 else if(S_ISLNK(mode))
1201 return UNIX_TYPE_SYMLINK;
1204 else if(S_ISCHR(mode))
1205 return UNIX_TYPE_CHARDEV;
1208 else if(S_ISBLK(mode))
1209 return UNIX_TYPE_BLKDEV;
1212 else if(S_ISFIFO(mode))
1213 return UNIX_TYPE_FIFO;
1216 else if(S_ISSOCK(mode))
1217 return UNIX_TYPE_SOCKET;
1220 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1221 return UNIX_TYPE_UNKNOWN;
1224 /****************************************************************************
1225 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1226 ****************************************************************************/
1228 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1230 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1231 const SMB_STRUCT_STAT *psbuf,
1233 enum perm_type ptype,
1238 if (perms == SMB_MODE_NO_CHANGE) {
1239 if (!VALID_STAT(*psbuf)) {
1240 return NT_STATUS_INVALID_PARAMETER;
1242 *ret_perms = psbuf->st_ex_mode;
1243 return NT_STATUS_OK;
1247 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1248 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1249 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1250 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1251 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1252 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1253 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1254 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1255 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1257 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1260 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1263 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1268 /* Apply mode mask */
1269 ret &= lp_create_mask(SNUM(conn));
1270 /* Add in force bits */
1271 ret |= lp_force_create_mode(SNUM(conn));
1274 ret &= lp_dir_mask(SNUM(conn));
1275 /* Add in force bits */
1276 ret |= lp_force_dir_mode(SNUM(conn));
1278 case PERM_EXISTING_FILE:
1279 /* Apply mode mask */
1280 ret &= lp_security_mask(SNUM(conn));
1281 /* Add in force bits */
1282 ret |= lp_force_security_mode(SNUM(conn));
1284 case PERM_EXISTING_DIR:
1285 /* Apply mode mask */
1286 ret &= lp_dir_security_mask(SNUM(conn));
1287 /* Add in force bits */
1288 ret |= lp_force_dir_security_mode(SNUM(conn));
1293 return NT_STATUS_OK;
1296 /****************************************************************************
1297 Needed to show the msdfs symlinks as directories. Modifies psbuf
1298 to be a directory if it's a msdfs link.
1299 ****************************************************************************/
1301 static bool check_msdfs_link(connection_struct *conn,
1302 const char *pathname,
1303 SMB_STRUCT_STAT *psbuf)
1305 int saved_errno = errno;
1306 if(lp_host_msdfs() &&
1307 lp_msdfs_root(SNUM(conn)) &&
1308 is_msdfs_link(conn, pathname, psbuf)) {
1310 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1313 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1314 errno = saved_errno;
1317 errno = saved_errno;
1322 /****************************************************************************
1323 Get a level dependent lanman2 dir entry.
1324 ****************************************************************************/
1326 struct smbd_dirptr_lanman2_state {
1327 connection_struct *conn;
1328 uint32_t info_level;
1329 bool check_mangled_names;
1331 bool got_exact_match;
1334 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1340 struct smbd_dirptr_lanman2_state *state =
1341 (struct smbd_dirptr_lanman2_state *)private_data;
1343 char mangled_name[13]; /* mangled 8.3 name. */
1347 /* Mangle fname if it's an illegal name. */
1348 if (mangle_must_mangle(dname, state->conn->params)) {
1349 ok = name_to_8_3(dname, mangled_name,
1350 true, state->conn->params);
1354 fname = mangled_name;
1359 got_match = exact_match(state->has_wild,
1360 state->conn->case_sensitive,
1362 state->got_exact_match = got_match;
1364 got_match = mask_match(fname, mask,
1365 state->conn->case_sensitive);
1368 if(!got_match && state->check_mangled_names &&
1369 !mangle_is_8_3(fname, false, state->conn->params)) {
1371 * It turns out that NT matches wildcards against
1372 * both long *and* short names. This may explain some
1373 * of the wildcard wierdness from old DOS clients
1374 * that some people have been seeing.... JRA.
1376 /* Force the mangling into 8.3. */
1377 ok = name_to_8_3(fname, mangled_name,
1378 false, state->conn->params);
1383 got_match = exact_match(state->has_wild,
1384 state->conn->case_sensitive,
1385 mangled_name, mask);
1386 state->got_exact_match = got_match;
1388 got_match = mask_match(mangled_name, mask,
1389 state->conn->case_sensitive);
1397 *_fname = talloc_strdup(ctx, fname);
1398 if (*_fname == NULL) {
1405 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1407 struct smb_filename *smb_fname,
1410 struct smbd_dirptr_lanman2_state *state =
1411 (struct smbd_dirptr_lanman2_state *)private_data;
1412 bool ms_dfs_link = false;
1415 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1416 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1417 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1418 "Couldn't lstat [%s] (%s)\n",
1419 smb_fname_str_dbg(smb_fname),
1423 } else if (!VALID_STAT(smb_fname->st) &&
1424 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1425 /* Needed to show the msdfs symlinks as
1428 ms_dfs_link = check_msdfs_link(state->conn,
1429 smb_fname->base_name,
1432 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1433 "Couldn't stat [%s] (%s)\n",
1434 smb_fname_str_dbg(smb_fname),
1441 mode = dos_mode_msdfs(state->conn, smb_fname);
1443 mode = dos_mode(state->conn, smb_fname);
1450 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1451 connection_struct *conn,
1453 uint32_t info_level,
1454 struct ea_list *name_list,
1455 bool check_mangled_names,
1456 bool requires_resume_key,
1459 const struct smb_filename *smb_fname,
1460 uint64_t space_remaining,
1465 uint64_t *last_entry_off)
1467 char *p, *q, *pdata = *ppdata;
1469 uint64_t file_size = 0;
1470 uint64_t allocation_size = 0;
1472 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1473 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1474 time_t c_date = (time_t)0;
1476 char *last_entry_ptr;
1478 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1480 *out_of_space = false;
1482 ZERO_STRUCT(mdate_ts);
1483 ZERO_STRUCT(adate_ts);
1484 ZERO_STRUCT(create_date_ts);
1485 ZERO_STRUCT(cdate_ts);
1487 if (!(mode & aDIR)) {
1488 file_size = get_file_size_stat(&smb_fname->st);
1490 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1492 mdate_ts = smb_fname->st.st_ex_mtime;
1493 adate_ts = smb_fname->st.st_ex_atime;
1494 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1495 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1497 if (lp_dos_filetime_resolution(SNUM(conn))) {
1498 dos_filetime_timespec(&create_date_ts);
1499 dos_filetime_timespec(&mdate_ts);
1500 dos_filetime_timespec(&adate_ts);
1501 dos_filetime_timespec(&cdate_ts);
1504 create_date = convert_timespec_to_time_t(create_date_ts);
1505 mdate = convert_timespec_to_time_t(mdate_ts);
1506 adate = convert_timespec_to_time_t(adate_ts);
1507 c_date = convert_timespec_to_time_t(cdate_ts);
1512 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1514 switch (info_level) {
1515 case SMB_FIND_INFO_STANDARD:
1516 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1517 if(requires_resume_key) {
1521 srv_put_dos_date2(p,0,create_date);
1522 srv_put_dos_date2(p,4,adate);
1523 srv_put_dos_date2(p,8,mdate);
1524 SIVAL(p,12,(uint32)file_size);
1525 SIVAL(p,16,(uint32)allocation_size);
1529 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1530 p += ucs2_align(base_data, p, 0);
1532 len = srvstr_push(base_data, flags2, p,
1533 fname, PTR_DIFF(end_data, p),
1535 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1537 SCVAL(nameptr, -1, len - 2);
1539 SCVAL(nameptr, -1, 0);
1543 SCVAL(nameptr, -1, len - 1);
1545 SCVAL(nameptr, -1, 0);
1551 case SMB_FIND_EA_SIZE:
1552 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1553 if (requires_resume_key) {
1557 srv_put_dos_date2(p,0,create_date);
1558 srv_put_dos_date2(p,4,adate);
1559 srv_put_dos_date2(p,8,mdate);
1560 SIVAL(p,12,(uint32)file_size);
1561 SIVAL(p,16,(uint32)allocation_size);
1564 unsigned int ea_size = estimate_ea_size(conn, NULL,
1565 smb_fname->base_name);
1566 SIVAL(p,22,ea_size); /* Extended attributes */
1570 len = srvstr_push(base_data, flags2,
1571 p, fname, PTR_DIFF(end_data, p),
1572 STR_TERMINATE | STR_NOALIGN);
1573 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1586 SCVAL(nameptr,0,len);
1588 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1591 case SMB_FIND_EA_LIST:
1593 struct ea_list *file_list = NULL;
1596 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1600 if (requires_resume_key) {
1604 srv_put_dos_date2(p,0,create_date);
1605 srv_put_dos_date2(p,4,adate);
1606 srv_put_dos_date2(p,8,mdate);
1607 SIVAL(p,12,(uint32)file_size);
1608 SIVAL(p,16,(uint32)allocation_size);
1610 p += 22; /* p now points to the EA area. */
1612 file_list = get_ea_list_from_file(ctx, conn, NULL,
1613 smb_fname->base_name,
1615 name_list = ea_list_union(name_list, file_list, &ea_len);
1617 /* We need to determine if this entry will fit in the space available. */
1618 /* Max string size is 255 bytes. */
1619 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1620 *out_of_space = true;
1621 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1622 return False; /* Not finished - just out of space */
1625 /* Push the ea_data followed by the name. */
1626 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1628 len = srvstr_push(base_data, flags2,
1629 p + 1, fname, PTR_DIFF(end_data, p+1),
1630 STR_TERMINATE | STR_NOALIGN);
1631 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1644 SCVAL(nameptr,0,len);
1646 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1650 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1651 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1652 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1654 SIVAL(p,0,reskey); p += 4;
1655 put_long_date_timespec(p,create_date_ts); p += 8;
1656 put_long_date_timespec(p,adate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 put_long_date_timespec(p,cdate_ts); p += 8;
1659 SOFF_T(p,0,file_size); p += 8;
1660 SOFF_T(p,0,allocation_size); p += 8;
1661 SIVAL(p,0,nt_extmode); p += 4;
1662 q = p; p += 4; /* q is placeholder for name length. */
1664 unsigned int ea_size = estimate_ea_size(conn, NULL,
1665 smb_fname->base_name);
1666 SIVAL(p,0,ea_size); /* Extended attributes */
1669 /* Clear the short name buffer. This is
1670 * IMPORTANT as not doing so will trigger
1671 * a Win2k client bug. JRA.
1673 if (!was_8_3 && check_mangled_names) {
1674 char mangled_name[13]; /* mangled 8.3 name. */
1675 if (!name_to_8_3(fname,mangled_name,True,
1677 /* Error - mangle failed ! */
1678 memset(mangled_name,'\0',12);
1680 mangled_name[12] = 0;
1681 len = srvstr_push(base_data, flags2,
1682 p+2, mangled_name, 24,
1683 STR_UPPER|STR_UNICODE);
1685 memset(p + 2 + len,'\0',24 - len);
1692 len = srvstr_push(base_data, flags2, p,
1693 fname, PTR_DIFF(end_data, p),
1694 STR_TERMINATE_ASCII);
1697 SIVAL(p,0,0); /* Ensure any padding is null. */
1698 len = PTR_DIFF(p, pdata);
1699 len = (len + 3) & ~3;
1704 case SMB_FIND_FILE_DIRECTORY_INFO:
1705 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1707 SIVAL(p,0,reskey); p += 4;
1708 put_long_date_timespec(p,create_date_ts); p += 8;
1709 put_long_date_timespec(p,adate_ts); p += 8;
1710 put_long_date_timespec(p,mdate_ts); p += 8;
1711 put_long_date_timespec(p,cdate_ts); p += 8;
1712 SOFF_T(p,0,file_size); p += 8;
1713 SOFF_T(p,0,allocation_size); p += 8;
1714 SIVAL(p,0,nt_extmode); p += 4;
1715 len = srvstr_push(base_data, flags2,
1716 p + 4, fname, PTR_DIFF(end_data, p+4),
1717 STR_TERMINATE_ASCII);
1720 SIVAL(p,0,0); /* Ensure any padding is null. */
1721 len = PTR_DIFF(p, pdata);
1722 len = (len + 3) & ~3;
1727 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1728 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1730 SIVAL(p,0,reskey); p += 4;
1731 put_long_date_timespec(p,create_date_ts); p += 8;
1732 put_long_date_timespec(p,adate_ts); p += 8;
1733 put_long_date_timespec(p,mdate_ts); p += 8;
1734 put_long_date_timespec(p,cdate_ts); p += 8;
1735 SOFF_T(p,0,file_size); p += 8;
1736 SOFF_T(p,0,allocation_size); p += 8;
1737 SIVAL(p,0,nt_extmode); p += 4;
1738 q = p; p += 4; /* q is placeholder for name length. */
1740 unsigned int ea_size = estimate_ea_size(conn, NULL,
1741 smb_fname->base_name);
1742 SIVAL(p,0,ea_size); /* Extended attributes */
1745 len = srvstr_push(base_data, flags2, p,
1746 fname, PTR_DIFF(end_data, p),
1747 STR_TERMINATE_ASCII);
1751 SIVAL(p,0,0); /* Ensure any padding is null. */
1752 len = PTR_DIFF(p, pdata);
1753 len = (len + 3) & ~3;
1758 case SMB_FIND_FILE_NAMES_INFO:
1759 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1761 SIVAL(p,0,reskey); p += 4;
1763 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1764 acl on a dir (tridge) */
1765 len = srvstr_push(base_data, flags2, p,
1766 fname, PTR_DIFF(end_data, p),
1767 STR_TERMINATE_ASCII);
1770 SIVAL(p,0,0); /* Ensure any padding is null. */
1771 len = PTR_DIFF(p, pdata);
1772 len = (len + 3) & ~3;
1777 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1778 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1780 SIVAL(p,0,reskey); p += 4;
1781 put_long_date_timespec(p,create_date_ts); p += 8;
1782 put_long_date_timespec(p,adate_ts); p += 8;
1783 put_long_date_timespec(p,mdate_ts); p += 8;
1784 put_long_date_timespec(p,cdate_ts); p += 8;
1785 SOFF_T(p,0,file_size); p += 8;
1786 SOFF_T(p,0,allocation_size); p += 8;
1787 SIVAL(p,0,nt_extmode); p += 4;
1788 q = p; p += 4; /* q is placeholder for name length. */
1790 unsigned int ea_size = estimate_ea_size(conn, NULL,
1791 smb_fname->base_name);
1792 SIVAL(p,0,ea_size); /* Extended attributes */
1795 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1796 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1797 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1798 len = srvstr_push(base_data, flags2, p,
1799 fname, PTR_DIFF(end_data, p),
1800 STR_TERMINATE_ASCII);
1803 SIVAL(p,0,0); /* Ensure any padding is null. */
1804 len = PTR_DIFF(p, pdata);
1805 len = (len + 3) & ~3;
1810 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1811 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1812 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1814 SIVAL(p,0,reskey); p += 4;
1815 put_long_date_timespec(p,create_date_ts); p += 8;
1816 put_long_date_timespec(p,adate_ts); p += 8;
1817 put_long_date_timespec(p,mdate_ts); p += 8;
1818 put_long_date_timespec(p,cdate_ts); p += 8;
1819 SOFF_T(p,0,file_size); p += 8;
1820 SOFF_T(p,0,allocation_size); p += 8;
1821 SIVAL(p,0,nt_extmode); p += 4;
1822 q = p; p += 4; /* q is placeholder for name length */
1824 unsigned int ea_size = estimate_ea_size(conn, NULL,
1825 smb_fname->base_name);
1826 SIVAL(p,0,ea_size); /* Extended attributes */
1829 /* Clear the short name buffer. This is
1830 * IMPORTANT as not doing so will trigger
1831 * a Win2k client bug. JRA.
1833 if (!was_8_3 && check_mangled_names) {
1834 char mangled_name[13]; /* mangled 8.3 name. */
1835 if (!name_to_8_3(fname,mangled_name,True,
1837 /* Error - mangle failed ! */
1838 memset(mangled_name,'\0',12);
1840 mangled_name[12] = 0;
1841 len = srvstr_push(base_data, flags2,
1842 p+2, mangled_name, 24,
1843 STR_UPPER|STR_UNICODE);
1846 memset(p + 2 + len,'\0',24 - len);
1853 SSVAL(p,0,0); p += 2; /* Reserved ? */
1854 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1855 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1856 len = srvstr_push(base_data, flags2, p,
1857 fname, PTR_DIFF(end_data, p),
1858 STR_TERMINATE_ASCII);
1861 SIVAL(p,0,0); /* Ensure any padding is null. */
1862 len = PTR_DIFF(p, pdata);
1863 len = (len + 3) & ~3;
1868 /* CIFS UNIX Extension. */
1870 case SMB_FIND_FILE_UNIX:
1871 case SMB_FIND_FILE_UNIX_INFO2:
1873 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1875 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1877 if (info_level == SMB_FIND_FILE_UNIX) {
1878 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1879 p = store_file_unix_basic(conn, p,
1880 NULL, &smb_fname->st);
1881 len = srvstr_push(base_data, flags2, p,
1882 fname, PTR_DIFF(end_data, p),
1885 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1886 p = store_file_unix_basic_info2(conn, p,
1887 NULL, &smb_fname->st);
1890 len = srvstr_push(base_data, flags2, p, fname,
1891 PTR_DIFF(end_data, p), 0);
1892 SIVAL(nameptr, 0, len);
1896 SIVAL(p,0,0); /* Ensure any padding is null. */
1898 len = PTR_DIFF(p, pdata);
1899 len = (len + 3) & ~3;
1900 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1902 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1910 if (PTR_DIFF(p,pdata) > space_remaining) {
1911 *out_of_space = true;
1912 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1913 return false; /* Not finished - just out of space */
1916 /* Setup the last entry pointer, as an offset from base_data */
1917 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1918 /* Advance the data pointer to the next slot */
1924 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1925 connection_struct *conn,
1926 struct dptr_struct *dirptr,
1928 const char *path_mask,
1931 int requires_resume_key,
1937 int space_remaining,
1939 bool *got_exact_match,
1940 int *_last_entry_off,
1941 struct ea_list *name_list)
1944 const char *mask = NULL;
1945 long prev_dirpos = 0;
1948 struct smb_filename *smb_fname = NULL;
1949 struct smbd_dirptr_lanman2_state state;
1951 uint64_t last_entry_off = 0;
1955 state.info_level = info_level;
1956 state.check_mangled_names = lp_manglednames(conn->params);
1957 state.has_wild = dptr_has_wild(dirptr);
1958 state.got_exact_match = false;
1960 *out_of_space = false;
1961 *got_exact_match = false;
1963 p = strrchr_m(path_mask,'/');
1974 ok = smbd_dirptr_get_entry(ctx,
1980 smbd_dirptr_lanman2_match_fn,
1981 smbd_dirptr_lanman2_mode_fn,
1991 *got_exact_match = state.got_exact_match;
1993 ok = smbd_marshall_dir_entry(ctx,
1998 state.check_mangled_names,
1999 requires_resume_key,
2010 TALLOC_FREE(smb_fname);
2011 if (*out_of_space) {
2012 dptr_SeekDir(dirptr, prev_dirpos);
2019 *_last_entry_off = last_entry_off;
2023 /****************************************************************************
2024 Reply to a TRANS2_FINDFIRST.
2025 ****************************************************************************/
2027 static void call_trans2findfirst(connection_struct *conn,
2028 struct smb_request *req,
2029 char **pparams, int total_params,
2030 char **ppdata, int total_data,
2031 unsigned int max_data_bytes)
2033 /* We must be careful here that we don't return more than the
2034 allowed number of data bytes. If this means returning fewer than
2035 maxentries then so be it. We assume that the redirector has
2036 enough room for the fixed number of parameter bytes it has
2038 struct smb_filename *smb_dname = NULL;
2039 char *params = *pparams;
2040 char *pdata = *ppdata;
2044 uint16 findfirst_flags;
2045 bool close_after_first;
2047 bool requires_resume_key;
2049 char *directory = NULL;
2052 int last_entry_off=0;
2056 bool finished = False;
2057 bool dont_descend = False;
2058 bool out_of_space = False;
2059 int space_remaining;
2060 bool mask_contains_wcard = False;
2061 struct ea_list *ea_list = NULL;
2062 NTSTATUS ntstatus = NT_STATUS_OK;
2063 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2064 TALLOC_CTX *ctx = talloc_tos();
2065 struct dptr_struct *dirptr = NULL;
2066 struct smbd_server_connection *sconn = smbd_server_conn;
2068 if (total_params < 13) {
2069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2073 dirtype = SVAL(params,0);
2074 maxentries = SVAL(params,2);
2075 findfirst_flags = SVAL(params,4);
2076 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2077 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2078 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2079 info_level = SVAL(params,6);
2081 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2082 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2083 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2084 info_level, max_data_bytes));
2087 /* W2K3 seems to treat zero as 1. */
2091 switch (info_level) {
2092 case SMB_FIND_INFO_STANDARD:
2093 case SMB_FIND_EA_SIZE:
2094 case SMB_FIND_EA_LIST:
2095 case SMB_FIND_FILE_DIRECTORY_INFO:
2096 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2097 case SMB_FIND_FILE_NAMES_INFO:
2098 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2099 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2100 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2102 case SMB_FIND_FILE_UNIX:
2103 case SMB_FIND_FILE_UNIX_INFO2:
2104 /* Always use filesystem for UNIX mtime query. */
2105 ask_sharemode = false;
2106 if (!lp_unix_extensions()) {
2107 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2112 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2116 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2117 params+12, total_params - 12,
2118 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2119 if (!NT_STATUS_IS_OK(ntstatus)) {
2120 reply_nterror(req, ntstatus);
2124 ntstatus = filename_convert(ctx, conn,
2125 req->flags2 & FLAGS2_DFS_PATHNAMES,
2128 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2129 &mask_contains_wcard,
2131 if (!NT_STATUS_IS_OK(ntstatus)) {
2132 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2133 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2134 ERRSRV, ERRbadpath);
2137 reply_nterror(req, ntstatus);
2141 mask = smb_dname->original_lcomp;
2143 directory = smb_dname->base_name;
2145 p = strrchr_m(directory,'/');
2147 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2148 if((directory[0] == '.') && (directory[1] == '\0')) {
2149 mask = talloc_strdup(ctx,"*");
2151 reply_nterror(req, NT_STATUS_NO_MEMORY);
2154 mask_contains_wcard = True;
2156 directory = talloc_strdup(talloc_tos(), "./");
2158 reply_nterror(req, NT_STATUS_NO_MEMORY);
2165 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2167 if (info_level == SMB_FIND_EA_LIST) {
2170 if (total_data < 4) {
2171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2175 ea_size = IVAL(pdata,0);
2176 if (ea_size != total_data) {
2177 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2178 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2183 if (!lp_ea_support(SNUM(conn))) {
2184 reply_doserror(req, ERRDOS, ERReasnotsupported);
2188 /* Pull out the list of names. */
2189 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2196 *ppdata = (char *)SMB_REALLOC(
2197 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2198 if(*ppdata == NULL ) {
2199 reply_nterror(req, NT_STATUS_NO_MEMORY);
2203 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2205 /* Realloc the params space */
2206 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2207 if (*pparams == NULL) {
2208 reply_nterror(req, NT_STATUS_NO_MEMORY);
2213 /* Save the wildcard match and attribs we are using on this directory -
2214 needed as lanman2 assumes these are being saved between calls */
2216 ntstatus = dptr_create(conn,
2222 mask_contains_wcard,
2226 if (!NT_STATUS_IS_OK(ntstatus)) {
2227 reply_nterror(req, ntstatus);
2231 dptr_num = dptr_dnum(dirptr);
2232 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2234 /* Initialize per TRANS2_FIND_FIRST operation data */
2235 dptr_init_search_op(dirptr);
2237 /* We don't need to check for VOL here as this is returned by
2238 a different TRANS2 call. */
2240 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2241 directory,lp_dontdescend(SNUM(conn))));
2242 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2243 dont_descend = True;
2246 space_remaining = max_data_bytes;
2247 out_of_space = False;
2249 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2250 bool got_exact_match = False;
2252 /* this is a heuristic to avoid seeking the dirptr except when
2253 absolutely necessary. It allows for a filename of about 40 chars */
2254 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2255 out_of_space = True;
2258 finished = !get_lanman2_dir_entry(ctx,
2262 mask,dirtype,info_level,
2263 requires_resume_key,dont_descend,
2266 space_remaining, &out_of_space,
2268 &last_entry_off, ea_list);
2271 if (finished && out_of_space)
2274 if (!finished && !out_of_space)
2278 * As an optimisation if we know we aren't looking
2279 * for a wildcard name (ie. the name matches the wildcard exactly)
2280 * then we can finish on any (first) match.
2281 * This speeds up large directory searches. JRA.
2287 /* Ensure space_remaining never goes -ve. */
2288 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2289 space_remaining = 0;
2290 out_of_space = true;
2292 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2296 /* Check if we can close the dirptr */
2297 if(close_after_first || (finished && close_if_end)) {
2298 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2299 dptr_close(sconn, &dptr_num);
2303 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2304 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2305 * the protocol level is less than NT1. Tested with smbclient. JRA.
2306 * This should fix the OS/2 client bug #2335.
2309 if(numentries == 0) {
2310 dptr_close(sconn, &dptr_num);
2311 if (Protocol < PROTOCOL_NT1) {
2312 reply_doserror(req, ERRDOS, ERRnofiles);
2315 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2316 ERRDOS, ERRbadfile);
2321 /* At this point pdata points to numentries directory entries. */
2323 /* Set up the return parameter block */
2324 SSVAL(params,0,dptr_num);
2325 SSVAL(params,2,numentries);
2326 SSVAL(params,4,finished);
2327 SSVAL(params,6,0); /* Never an EA error */
2328 SSVAL(params,8,last_entry_off);
2330 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2333 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2334 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2336 reply_nterror(req, NT_STATUS_NO_MEMORY);
2340 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2341 smb_fn_name(req->cmd),
2342 mask, directory, dirtype, numentries ) );
2345 * Force a name mangle here to ensure that the
2346 * mask as an 8.3 name is top of the mangled cache.
2347 * The reasons for this are subtle. Don't remove
2348 * this code unless you know what you are doing
2349 * (see PR#13758). JRA.
2352 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2353 char mangled_name[13];
2354 name_to_8_3(mask, mangled_name, True, conn->params);
2357 TALLOC_FREE(smb_dname);
2361 /****************************************************************************
2362 Reply to a TRANS2_FINDNEXT.
2363 ****************************************************************************/
2365 static void call_trans2findnext(connection_struct *conn,
2366 struct smb_request *req,
2367 char **pparams, int total_params,
2368 char **ppdata, int total_data,
2369 unsigned int max_data_bytes)
2371 /* We must be careful here that we don't return more than the
2372 allowed number of data bytes. If this means returning fewer than
2373 maxentries then so be it. We assume that the redirector has
2374 enough room for the fixed number of parameter bytes it has
2376 char *params = *pparams;
2377 char *pdata = *ppdata;
2383 uint16 findnext_flags;
2384 bool close_after_request;
2386 bool requires_resume_key;
2388 bool mask_contains_wcard = False;
2389 char *resume_name = NULL;
2390 const char *mask = NULL;
2391 const char *directory = NULL;
2395 int i, last_entry_off=0;
2396 bool finished = False;
2397 bool dont_descend = False;
2398 bool out_of_space = False;
2399 int space_remaining;
2400 struct ea_list *ea_list = NULL;
2401 NTSTATUS ntstatus = NT_STATUS_OK;
2402 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2403 TALLOC_CTX *ctx = talloc_tos();
2404 struct dptr_struct *dirptr;
2405 struct smbd_server_connection *sconn = smbd_server_conn;
2407 if (total_params < 13) {
2408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2412 dptr_num = SVAL(params,0);
2413 maxentries = SVAL(params,2);
2414 info_level = SVAL(params,4);
2415 resume_key = IVAL(params,6);
2416 findnext_flags = SVAL(params,10);
2417 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2418 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2419 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2420 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2422 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2424 total_params - 12, STR_TERMINATE, &ntstatus,
2425 &mask_contains_wcard);
2426 if (!NT_STATUS_IS_OK(ntstatus)) {
2427 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2428 complain (it thinks we're asking for the directory above the shared
2429 path or an invalid name). Catch this as the resume name is only compared, never used in
2430 a file access. JRA. */
2431 srvstr_pull_talloc(ctx, params, req->flags2,
2432 &resume_name, params+12,
2436 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2437 reply_nterror(req, ntstatus);
2442 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2443 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2444 resume_key = %d resume name = %s continue=%d level = %d\n",
2445 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2446 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2449 /* W2K3 seems to treat zero as 1. */
2453 switch (info_level) {
2454 case SMB_FIND_INFO_STANDARD:
2455 case SMB_FIND_EA_SIZE:
2456 case SMB_FIND_EA_LIST:
2457 case SMB_FIND_FILE_DIRECTORY_INFO:
2458 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2459 case SMB_FIND_FILE_NAMES_INFO:
2460 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2461 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2462 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2464 case SMB_FIND_FILE_UNIX:
2465 case SMB_FIND_FILE_UNIX_INFO2:
2466 /* Always use filesystem for UNIX mtime query. */
2467 ask_sharemode = false;
2468 if (!lp_unix_extensions()) {
2469 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2474 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2478 if (info_level == SMB_FIND_EA_LIST) {
2481 if (total_data < 4) {
2482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2486 ea_size = IVAL(pdata,0);
2487 if (ea_size != total_data) {
2488 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2489 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2494 if (!lp_ea_support(SNUM(conn))) {
2495 reply_doserror(req, ERRDOS, ERReasnotsupported);
2499 /* Pull out the list of names. */
2500 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2507 *ppdata = (char *)SMB_REALLOC(
2508 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2509 if(*ppdata == NULL) {
2510 reply_nterror(req, NT_STATUS_NO_MEMORY);
2515 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2517 /* Realloc the params space */
2518 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2519 if(*pparams == NULL ) {
2520 reply_nterror(req, NT_STATUS_NO_MEMORY);
2526 /* Check that the dptr is valid */
2527 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2528 reply_doserror(req, ERRDOS, ERRnofiles);
2532 directory = dptr_path(sconn, dptr_num);
2534 /* Get the wildcard mask from the dptr */
2535 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2536 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2537 reply_doserror(req, ERRDOS, ERRnofiles);
2543 /* Get the attr mask from the dptr */
2544 dirtype = dptr_attr(sconn, dptr_num);
2546 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2547 dptr_num, mask, dirtype,
2549 dptr_TellDir(dirptr)));
2551 /* Initialize per TRANS2_FIND_NEXT operation data */
2552 dptr_init_search_op(dirptr);
2554 /* We don't need to check for VOL here as this is returned by
2555 a different TRANS2 call. */
2557 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2558 directory,lp_dontdescend(SNUM(conn))));
2559 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2560 dont_descend = True;
2563 space_remaining = max_data_bytes;
2564 out_of_space = False;
2567 * Seek to the correct position. We no longer use the resume key but
2568 * depend on the last file name instead.
2571 if(*resume_name && !continue_bit) {
2574 long current_pos = 0;
2576 * Remember, name_to_8_3 is called by
2577 * get_lanman2_dir_entry(), so the resume name
2578 * could be mangled. Ensure we check the unmangled name.
2581 if (mangle_is_mangled(resume_name, conn->params)) {
2582 char *new_resume_name = NULL;
2583 mangle_lookup_name_from_8_3(ctx,
2587 if (new_resume_name) {
2588 resume_name = new_resume_name;
2593 * Fix for NT redirector problem triggered by resume key indexes
2594 * changing between directory scans. We now return a resume key of 0
2595 * and instead look for the filename to continue from (also given
2596 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2597 * findfirst/findnext (as is usual) then the directory pointer
2598 * should already be at the correct place.
2601 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2602 } /* end if resume_name && !continue_bit */
2604 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2605 bool got_exact_match = False;
2607 /* this is a heuristic to avoid seeking the dirptr except when
2608 absolutely necessary. It allows for a filename of about 40 chars */
2609 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2610 out_of_space = True;
2613 finished = !get_lanman2_dir_entry(ctx,
2617 mask,dirtype,info_level,
2618 requires_resume_key,dont_descend,
2621 space_remaining, &out_of_space,
2623 &last_entry_off, ea_list);
2626 if (finished && out_of_space)
2629 if (!finished && !out_of_space)
2633 * As an optimisation if we know we aren't looking
2634 * for a wildcard name (ie. the name matches the wildcard exactly)
2635 * then we can finish on any (first) match.
2636 * This speeds up large directory searches. JRA.
2642 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2645 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2646 smb_fn_name(req->cmd),
2647 mask, directory, dirtype, numentries ) );
2649 /* Check if we can close the dirptr */
2650 if(close_after_request || (finished && close_if_end)) {
2651 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2652 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2655 /* Set up the return parameter block */
2656 SSVAL(params,0,numentries);
2657 SSVAL(params,2,finished);
2658 SSVAL(params,4,0); /* Never an EA error */
2659 SSVAL(params,6,last_entry_off);
2661 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2667 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2669 E_md4hash(lp_servicename(SNUM(conn)),objid);
2673 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2675 SMB_ASSERT(extended_info != NULL);
2677 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2678 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2679 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2680 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2681 #ifdef SAMBA_VERSION_REVISION
2682 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2684 extended_info->samba_subversion = 0;
2685 #ifdef SAMBA_VERSION_RC_RELEASE
2686 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2688 #ifdef SAMBA_VERSION_PRE_RELEASE
2689 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2692 #ifdef SAMBA_VERSION_VENDOR_PATCH
2693 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2695 extended_info->samba_gitcommitdate = 0;
2696 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2697 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2700 memset(extended_info->samba_version_string, 0,
2701 sizeof(extended_info->samba_version_string));
2703 snprintf (extended_info->samba_version_string,
2704 sizeof(extended_info->samba_version_string),
2705 "%s", samba_version_string());
2708 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2709 TALLOC_CTX *mem_ctx,
2710 uint16_t info_level,
2712 unsigned int max_data_bytes,
2716 char *pdata, *end_data;
2717 int data_len = 0, len;
2718 const char *vname = volume_label(SNUM(conn));
2719 int snum = SNUM(conn);
2720 char *fstype = lp_fstype(SNUM(conn));
2721 uint32 additional_flags = 0;
2722 struct smb_filename *smb_fname_dot = NULL;
2727 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2728 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2729 "info level (0x%x) on IPC$.\n",
2730 (unsigned int)info_level));
2731 return NT_STATUS_ACCESS_DENIED;
2735 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2737 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2739 if (!NT_STATUS_IS_OK(status)) {
2743 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2744 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2745 TALLOC_FREE(smb_fname_dot);
2746 return map_nt_error_from_unix(errno);
2749 st = smb_fname_dot->st;
2750 TALLOC_FREE(smb_fname_dot);
2752 *ppdata = (char *)SMB_REALLOC(
2753 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2754 if (*ppdata == NULL) {
2755 return NT_STATUS_NO_MEMORY;
2759 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2760 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2762 switch (info_level) {
2763 case SMB_INFO_ALLOCATION:
2765 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2767 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2768 return map_nt_error_from_unix(errno);
2771 block_size = lp_block_size(snum);
2772 if (bsize < block_size) {
2773 uint64_t factor = block_size/bsize;
2778 if (bsize > block_size) {
2779 uint64_t factor = bsize/block_size;
2784 bytes_per_sector = 512;
2785 sectors_per_unit = bsize/bytes_per_sector;
2787 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2788 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2789 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2791 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2792 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2793 SIVAL(pdata,l1_cUnit,dsize);
2794 SIVAL(pdata,l1_cUnitAvail,dfree);
2795 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2799 case SMB_INFO_VOLUME:
2800 /* Return volume name */
2802 * Add volume serial number - hash of a combination of
2803 * the called hostname and the service name.
2805 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2807 * Win2k3 and previous mess this up by sending a name length
2808 * one byte short. I believe only older clients (OS/2 Win9x) use
2809 * this call so try fixing this by adding a terminating null to
2810 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2814 pdata+l2_vol_szVolLabel, vname,
2815 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2816 STR_NOALIGN|STR_TERMINATE);
2817 SCVAL(pdata,l2_vol_cch,len);
2818 data_len = l2_vol_szVolLabel + len;
2819 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2820 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2824 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2825 case SMB_FS_ATTRIBUTE_INFORMATION:
2827 additional_flags = 0;
2828 #if defined(HAVE_SYS_QUOTAS)
2829 additional_flags |= FILE_VOLUME_QUOTAS;
2832 if(lp_nt_acl_support(SNUM(conn))) {
2833 additional_flags |= FILE_PERSISTENT_ACLS;
2836 /* Capabilities are filled in at connection time through STATVFS call */
2837 additional_flags |= conn->fs_capabilities;
2839 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2840 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2841 additional_flags); /* FS ATTRIBUTES */
2843 SIVAL(pdata,4,255); /* Max filename component length */
2844 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2845 and will think we can't do long filenames */
2846 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2847 PTR_DIFF(end_data, pdata+12),
2850 data_len = 12 + len;
2853 case SMB_QUERY_FS_LABEL_INFO:
2854 case SMB_FS_LABEL_INFORMATION:
2855 len = srvstr_push(pdata, flags2, pdata+4, vname,
2856 PTR_DIFF(end_data, pdata+4), 0);
2861 case SMB_QUERY_FS_VOLUME_INFO:
2862 case SMB_FS_VOLUME_INFORMATION:
2865 * Add volume serial number - hash of a combination of
2866 * the called hostname and the service name.
2868 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2869 (str_checksum(get_local_machine_name())<<16));
2871 /* Max label len is 32 characters. */
2872 len = srvstr_push(pdata, flags2, pdata+18, vname,
2873 PTR_DIFF(end_data, pdata+18),
2875 SIVAL(pdata,12,len);
2878 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2879 (int)strlen(vname),vname, lp_servicename(snum)));
2882 case SMB_QUERY_FS_SIZE_INFO:
2883 case SMB_FS_SIZE_INFORMATION:
2885 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2887 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2888 return map_nt_error_from_unix(errno);
2890 block_size = lp_block_size(snum);
2891 if (bsize < block_size) {
2892 uint64_t factor = block_size/bsize;
2897 if (bsize > block_size) {
2898 uint64_t factor = bsize/block_size;
2903 bytes_per_sector = 512;
2904 sectors_per_unit = bsize/bytes_per_sector;
2905 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2906 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2907 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2908 SBIG_UINT(pdata,0,dsize);
2909 SBIG_UINT(pdata,8,dfree);
2910 SIVAL(pdata,16,sectors_per_unit);
2911 SIVAL(pdata,20,bytes_per_sector);
2915 case SMB_FS_FULL_SIZE_INFORMATION:
2917 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2919 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2920 return map_nt_error_from_unix(errno);
2922 block_size = lp_block_size(snum);
2923 if (bsize < block_size) {
2924 uint64_t factor = block_size/bsize;
2929 if (bsize > block_size) {
2930 uint64_t factor = bsize/block_size;
2935 bytes_per_sector = 512;
2936 sectors_per_unit = bsize/bytes_per_sector;
2937 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2938 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2939 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2940 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2941 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2942 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2943 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2944 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2948 case SMB_QUERY_FS_DEVICE_INFO:
2949 case SMB_FS_DEVICE_INFORMATION:
2951 SIVAL(pdata,0,0); /* dev type */
2952 SIVAL(pdata,4,0); /* characteristics */
2955 #ifdef HAVE_SYS_QUOTAS
2956 case SMB_FS_QUOTA_INFORMATION:
2958 * what we have to send --metze:
2960 * Unknown1: 24 NULL bytes
2961 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2962 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2963 * Quota Flags: 2 byte :
2964 * Unknown3: 6 NULL bytes
2968 * details for Quota Flags:
2970 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2971 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2972 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2973 * 0x0001 Enable Quotas: enable quota for this fs
2977 /* we need to fake up a fsp here,
2978 * because its not send in this call
2981 SMB_NTQUOTA_STRUCT quotas;
2984 ZERO_STRUCT(quotas);
2990 if (conn->server_info->utok.uid != sec_initial_uid()) {
2991 DEBUG(0,("set_user_quota: access_denied "
2992 "service [%s] user [%s]\n",
2993 lp_servicename(SNUM(conn)),
2994 conn->server_info->unix_name));
2995 return NT_STATUS_ACCESS_DENIED;
2998 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2999 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3000 return map_nt_error_from_unix(errno);
3005 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3006 lp_servicename(SNUM(conn))));
3008 /* Unknown1 24 NULL bytes*/
3009 SBIG_UINT(pdata,0,(uint64_t)0);
3010 SBIG_UINT(pdata,8,(uint64_t)0);
3011 SBIG_UINT(pdata,16,(uint64_t)0);
3013 /* Default Soft Quota 8 bytes */
3014 SBIG_UINT(pdata,24,quotas.softlim);
3016 /* Default Hard Quota 8 bytes */
3017 SBIG_UINT(pdata,32,quotas.hardlim);
3019 /* Quota flag 2 bytes */
3020 SSVAL(pdata,40,quotas.qflags);
3022 /* Unknown3 6 NULL bytes */
3028 #endif /* HAVE_SYS_QUOTAS */
3029 case SMB_FS_OBJECTID_INFORMATION:
3031 unsigned char objid[16];
3032 struct smb_extended_info extended_info;
3033 memcpy(pdata,create_volume_objectid(conn, objid),16);
3034 samba_extended_info_version (&extended_info);
3035 SIVAL(pdata,16,extended_info.samba_magic);
3036 SIVAL(pdata,20,extended_info.samba_version);
3037 SIVAL(pdata,24,extended_info.samba_subversion);
3038 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3039 memcpy(pdata+36,extended_info.samba_version_string,28);
3045 * Query the version and capabilities of the CIFS UNIX extensions
3049 case SMB_QUERY_CIFS_UNIX_INFO:
3051 bool large_write = lp_min_receive_file_size() &&
3052 !srv_is_signing_active(smbd_server_conn);
3053 bool large_read = !srv_is_signing_active(smbd_server_conn);
3054 int encrypt_caps = 0;
3056 if (!lp_unix_extensions()) {
3057 return NT_STATUS_INVALID_LEVEL;
3060 switch (conn->encrypt_level) {
3066 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3069 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3070 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3071 large_write = false;
3077 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3078 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3080 /* We have POSIX ACLs, pathname, encryption,
3081 * large read/write, and locking capability. */
3083 SBIG_UINT(pdata,4,((uint64_t)(
3084 CIFS_UNIX_POSIX_ACLS_CAP|
3085 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3086 CIFS_UNIX_FCNTL_LOCKS_CAP|
3087 CIFS_UNIX_EXTATTR_CAP|
3088 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3090 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3092 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3096 case SMB_QUERY_POSIX_FS_INFO:
3099 vfs_statvfs_struct svfs;
3101 if (!lp_unix_extensions()) {
3102 return NT_STATUS_INVALID_LEVEL;
3105 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3109 SIVAL(pdata,0,svfs.OptimalTransferSize);
3110 SIVAL(pdata,4,svfs.BlockSize);
3111 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3112 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3113 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3114 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3115 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3116 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3117 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3119 } else if (rc == EOPNOTSUPP) {
3120 return NT_STATUS_INVALID_LEVEL;
3121 #endif /* EOPNOTSUPP */
3123 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3124 return NT_STATUS_DOS(ERRSRV, ERRerror);
3129 case SMB_QUERY_POSIX_WHOAMI:
3135 if (!lp_unix_extensions()) {
3136 return NT_STATUS_INVALID_LEVEL;
3139 if (max_data_bytes < 40) {
3140 return NT_STATUS_BUFFER_TOO_SMALL;
3143 /* We ARE guest if global_sid_Builtin_Guests is
3144 * in our list of SIDs.
3146 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3147 conn->server_info->ptok)) {
3148 flags |= SMB_WHOAMI_GUEST;
3151 /* We are NOT guest if global_sid_Authenticated_Users
3152 * is in our list of SIDs.
3154 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3155 conn->server_info->ptok)) {
3156 flags &= ~SMB_WHOAMI_GUEST;
3159 /* NOTE: 8 bytes for UID/GID, irrespective of native
3160 * platform size. This matches
3161 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3163 data_len = 4 /* flags */
3170 + 4 /* pad/reserved */
3171 + (conn->server_info->utok.ngroups * 8)
3173 + (conn->server_info->ptok->num_sids *
3177 SIVAL(pdata, 0, flags);
3178 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3180 (uint64_t)conn->server_info->utok.uid);
3181 SBIG_UINT(pdata, 16,
3182 (uint64_t)conn->server_info->utok.gid);
3185 if (data_len >= max_data_bytes) {
3186 /* Potential overflow, skip the GIDs and SIDs. */
3188 SIVAL(pdata, 24, 0); /* num_groups */
3189 SIVAL(pdata, 28, 0); /* num_sids */
3190 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3191 SIVAL(pdata, 36, 0); /* reserved */
3197 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3198 SIVAL(pdata, 28, conn->server_info->num_sids);
3200 /* We walk the SID list twice, but this call is fairly
3201 * infrequent, and I don't expect that it's performance
3202 * sensitive -- jpeach
3204 for (i = 0, sid_bytes = 0;
3205 i < conn->server_info->ptok->num_sids; ++i) {
3206 sid_bytes += ndr_size_dom_sid(
3207 &conn->server_info->ptok->user_sids[i],
3212 /* SID list byte count */
3213 SIVAL(pdata, 32, sid_bytes);
3215 /* 4 bytes pad/reserved - must be zero */
3216 SIVAL(pdata, 36, 0);
3220 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3221 SBIG_UINT(pdata, data_len,
3222 (uint64_t)conn->server_info->utok.groups[i]);
3228 i < conn->server_info->ptok->num_sids; ++i) {
3229 int sid_len = ndr_size_dom_sid(
3230 &conn->server_info->ptok->user_sids[i],
3234 sid_linearize(pdata + data_len, sid_len,
3235 &conn->server_info->ptok->user_sids[i]);
3236 data_len += sid_len;
3242 case SMB_MAC_QUERY_FS_INFO:
3244 * Thursby MAC extension... ONLY on NTFS filesystems
3245 * once we do streams then we don't need this
3247 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3249 SIVAL(pdata,84,0x100); /* Don't support mac... */
3254 return NT_STATUS_INVALID_LEVEL;
3257 *ret_data_len = data_len;
3258 return NT_STATUS_OK;
3261 /****************************************************************************
3262 Reply to a TRANS2_QFSINFO (query filesystem info).
3263 ****************************************************************************/
3265 static void call_trans2qfsinfo(connection_struct *conn,
3266 struct smb_request *req,
3267 char **pparams, int total_params,
3268 char **ppdata, int total_data,
3269 unsigned int max_data_bytes)
3271 char *params = *pparams;
3272 uint16_t info_level;
3276 if (total_params < 2) {
3277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3281 info_level = SVAL(params,0);
3283 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3284 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3285 DEBUG(0,("call_trans2qfsinfo: encryption required "
3286 "and info level 0x%x sent.\n",
3287 (unsigned int)info_level));
3288 exit_server_cleanly("encryption required "
3294 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3296 status = smbd_do_qfsinfo(conn, req,
3301 if (!NT_STATUS_IS_OK(status)) {
3302 reply_nterror(req, status);
3306 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3309 DEBUG( 4, ( "%s info_level = %d\n",
3310 smb_fn_name(req->cmd), info_level) );
3315 /****************************************************************************
3316 Reply to a TRANS2_SETFSINFO (set filesystem info).
3317 ****************************************************************************/
3319 static void call_trans2setfsinfo(connection_struct *conn,
3320 struct smb_request *req,
3321 char **pparams, int total_params,
3322 char **ppdata, int total_data,
3323 unsigned int max_data_bytes)
3325 char *pdata = *ppdata;
3326 char *params = *pparams;
3329 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3332 if (total_params < 4) {
3333 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3339 info_level = SVAL(params,2);
3342 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3343 info_level != SMB_SET_CIFS_UNIX_INFO) {
3344 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3345 "info level (0x%x) on IPC$.\n",
3346 (unsigned int)info_level));
3347 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3352 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3353 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3354 DEBUG(0,("call_trans2setfsinfo: encryption required "
3355 "and info level 0x%x sent.\n",
3356 (unsigned int)info_level));
3357 exit_server_cleanly("encryption required "
3363 switch(info_level) {
3364 case SMB_SET_CIFS_UNIX_INFO:
3366 uint16 client_unix_major;
3367 uint16 client_unix_minor;
3368 uint32 client_unix_cap_low;
3369 uint32 client_unix_cap_high;
3371 if (!lp_unix_extensions()) {
3373 NT_STATUS_INVALID_LEVEL);
3377 /* There should be 12 bytes of capabilities set. */
3378 if (total_data < 8) {
3381 NT_STATUS_INVALID_PARAMETER);
3384 client_unix_major = SVAL(pdata,0);
3385 client_unix_minor = SVAL(pdata,2);
3386 client_unix_cap_low = IVAL(pdata,4);
3387 client_unix_cap_high = IVAL(pdata,8);
3388 /* Just print these values for now. */
3389 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3390 cap_low = 0x%x, cap_high = 0x%x\n",
3391 (unsigned int)client_unix_major,
3392 (unsigned int)client_unix_minor,
3393 (unsigned int)client_unix_cap_low,
3394 (unsigned int)client_unix_cap_high ));
3396 /* Here is where we must switch to posix pathname processing... */
3397 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3398 lp_set_posix_pathnames();
3399 mangle_change_to_posix();
3402 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3403 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3404 /* Client that knows how to do posix locks,
3405 * but not posix open/mkdir operations. Set a
3406 * default type for read/write checks. */
3408 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3414 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3417 size_t param_len = 0;
3418 size_t data_len = total_data;
3420 if (!lp_unix_extensions()) {
3423 NT_STATUS_INVALID_LEVEL);
3427 if (lp_smb_encrypt(SNUM(conn)) == false) {
3430 NT_STATUS_NOT_SUPPORTED);
3434 DEBUG( 4,("call_trans2setfsinfo: "
3435 "request transport encryption.\n"));
3437 status = srv_request_encryption_setup(conn,
3438 (unsigned char **)ppdata,
3440 (unsigned char **)pparams,
3443 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3444 !NT_STATUS_IS_OK(status)) {
3445 reply_nterror(req, status);
3449 send_trans2_replies(conn, req,
3456 if (NT_STATUS_IS_OK(status)) {
3457 /* Server-side transport
3458 * encryption is now *on*. */
3459 status = srv_encryption_start(conn);
3460 if (!NT_STATUS_IS_OK(status)) {
3461 exit_server_cleanly(
3462 "Failure in setting "
3463 "up encrypted transport");
3469 case SMB_FS_QUOTA_INFORMATION:
3471 files_struct *fsp = NULL;
3472 SMB_NTQUOTA_STRUCT quotas;
3474 ZERO_STRUCT(quotas);
3477 if ((conn->server_info->utok.uid != sec_initial_uid())
3478 ||!CAN_WRITE(conn)) {
3479 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3480 lp_servicename(SNUM(conn)),
3481 conn->server_info->unix_name));
3482 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3486 /* note: normaly there're 48 bytes,
3487 * but we didn't use the last 6 bytes for now
3490 fsp = file_fsp(req, SVAL(params,0));
3492 if (!check_fsp_ntquota_handle(conn, req,
3494 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3496 req, NT_STATUS_INVALID_HANDLE);
3500 if (total_data < 42) {
3501 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3505 NT_STATUS_INVALID_PARAMETER);
3509 /* unknown_1 24 NULL bytes in pdata*/
3511 /* the soft quotas 8 bytes (uint64_t)*/
3512 quotas.softlim = (uint64_t)IVAL(pdata,24);
3513 #ifdef LARGE_SMB_OFF_T
3514 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3515 #else /* LARGE_SMB_OFF_T */
3516 if ((IVAL(pdata,28) != 0)&&
3517 ((quotas.softlim != 0xFFFFFFFF)||
3518 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3519 /* more than 32 bits? */
3522 NT_STATUS_INVALID_PARAMETER);
3525 #endif /* LARGE_SMB_OFF_T */
3527 /* the hard quotas 8 bytes (uint64_t)*/
3528 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3529 #ifdef LARGE_SMB_OFF_T
3530 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3531 #else /* LARGE_SMB_OFF_T */
3532 if ((IVAL(pdata,36) != 0)&&
3533 ((quotas.hardlim != 0xFFFFFFFF)||
3534 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3535 /* more than 32 bits? */
3538 NT_STATUS_INVALID_PARAMETER);
3541 #endif /* LARGE_SMB_OFF_T */
3543 /* quota_flags 2 bytes **/
3544 quotas.qflags = SVAL(pdata,40);
3546 /* unknown_2 6 NULL bytes follow*/
3548 /* now set the quotas */
3549 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3550 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3551 reply_nterror(req, map_nt_error_from_unix(errno));
3558 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3560 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3566 * sending this reply works fine,
3567 * but I'm not sure it's the same
3568 * like windows do...
3571 reply_outbuf(req, 10, 0);
3574 #if defined(HAVE_POSIX_ACLS)
3575 /****************************************************************************
3576 Utility function to count the number of entries in a POSIX acl.
3577 ****************************************************************************/
3579 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3581 unsigned int ace_count = 0;
3582 int entry_id = SMB_ACL_FIRST_ENTRY;
3583 SMB_ACL_ENTRY_T entry;
3585 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3587 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3588 entry_id = SMB_ACL_NEXT_ENTRY;
3595 /****************************************************************************
3596 Utility function to marshall a POSIX acl into wire format.
3597 ****************************************************************************/
3599 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3601 int entry_id = SMB_ACL_FIRST_ENTRY;
3602 SMB_ACL_ENTRY_T entry;
3604 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3605 SMB_ACL_TAG_T tagtype;
3606 SMB_ACL_PERMSET_T permset;
3607 unsigned char perms = 0;
3608 unsigned int own_grp;
3611 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3612 entry_id = SMB_ACL_NEXT_ENTRY;
3615 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3616 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3620 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3621 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3625 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3626 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3627 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3629 SCVAL(pdata,1,perms);
3632 case SMB_ACL_USER_OBJ:
3633 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3634 own_grp = (unsigned int)pst->st_ex_uid;
3635 SIVAL(pdata,2,own_grp);
3640 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3642 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3645 own_grp = (unsigned int)*puid;
3646 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3647 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3648 SIVAL(pdata,2,own_grp);
3652 case SMB_ACL_GROUP_OBJ:
3653 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3654 own_grp = (unsigned int)pst->st_ex_gid;
3655 SIVAL(pdata,2,own_grp);
3660 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3662 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3665 own_grp = (unsigned int)*pgid;
3666 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3667 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3668 SIVAL(pdata,2,own_grp);
3673 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3674 SIVAL(pdata,2,0xFFFFFFFF);
3675 SIVAL(pdata,6,0xFFFFFFFF);
3678 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3679 SIVAL(pdata,2,0xFFFFFFFF);
3680 SIVAL(pdata,6,0xFFFFFFFF);
3683 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3686 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3693 /****************************************************************************
3694 Store the FILE_UNIX_BASIC info.
3695 ****************************************************************************/
3697 static char *store_file_unix_basic(connection_struct *conn,
3700 const SMB_STRUCT_STAT *psbuf)
3702 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3703 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3705 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3708 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3711 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3712 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3713 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3716 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3720 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3724 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3727 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3731 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3735 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3738 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3742 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3749 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3750 * the chflags(2) (or equivalent) flags.
3752 * XXX: this really should be behind the VFS interface. To do this, we would
3753 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3754 * Each VFS module could then implement its own mapping as appropriate for the
3755 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3757 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3761 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3765 { UF_IMMUTABLE, EXT_IMMUTABLE },
3769 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3773 { UF_HIDDEN, EXT_HIDDEN },
3776 /* Do not remove. We need to guarantee that this array has at least one
3777 * entry to build on HP-UX.
3783 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3784 uint32 *smb_fflags, uint32 *smb_fmask)
3788 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3789 *smb_fmask |= info2_flags_map[i].smb_fflag;
3790 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3791 *smb_fflags |= info2_flags_map[i].smb_fflag;
3796 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3797 const uint32 smb_fflags,
3798 const uint32 smb_fmask,
3801 uint32 max_fmask = 0;
3804 *stat_fflags = psbuf->st_ex_flags;
3806 /* For each flags requested in smb_fmask, check the state of the
3807 * corresponding flag in smb_fflags and set or clear the matching
3811 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3812 max_fmask |= info2_flags_map[i].smb_fflag;
3813 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3814 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3815 *stat_fflags |= info2_flags_map[i].stat_fflag;
3817 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3822 /* If smb_fmask is asking to set any bits that are not supported by
3823 * our flag mappings, we should fail.
3825 if ((smb_fmask & max_fmask) != smb_fmask) {
3833 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3834 * of file flags and birth (create) time.
3836 static char *store_file_unix_basic_info2(connection_struct *conn,
3839 const SMB_STRUCT_STAT *psbuf)
3841 uint32 file_flags = 0;
3842 uint32 flags_mask = 0;
3844 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3846 /* Create (birth) time 64 bit */
3847 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3850 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3851 SIVAL(pdata, 0, file_flags); /* flags */
3852 SIVAL(pdata, 4, flags_mask); /* mask */
3858 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3859 const struct stream_struct *streams,
3861 unsigned int max_data_bytes,
3862 unsigned int *data_size)
3865 unsigned int ofs = 0;
3867 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3868 unsigned int next_offset;
3870 smb_ucs2_t *namebuf;
3872 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3873 streams[i].name, &namelen) ||
3876 return NT_STATUS_INVALID_PARAMETER;
3880 * name_buf is now null-terminated, we need to marshall as not
3886 SIVAL(data, ofs+4, namelen);
3887 SOFF_T(data, ofs+8, streams[i].size);
3888 SOFF_T(data, ofs+16, streams[i].alloc_size);
3889 memcpy(data+ofs+24, namebuf, namelen);
3890 TALLOC_FREE(namebuf);
3892 next_offset = ofs + 24 + namelen;
3894 if (i == num_streams-1) {
3895 SIVAL(data, ofs, 0);
3898 unsigned int align = ndr_align_size(next_offset, 8);
3900 memset(data+next_offset, 0, align);
3901 next_offset += align;
3903 SIVAL(data, ofs, next_offset - ofs);
3912 return NT_STATUS_OK;
3915 /****************************************************************************
3916 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3917 ****************************************************************************/
3919 static void call_trans2qpipeinfo(connection_struct *conn,
3920 struct smb_request *req,
3921 unsigned int tran_call,
3922 char **pparams, int total_params,
3923 char **ppdata, int total_data,
3924 unsigned int max_data_bytes)
3926 char *params = *pparams;
3927 char *pdata = *ppdata;
3928 unsigned int data_size = 0;
3929 unsigned int param_size = 2;
3934 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3938 if (total_params < 4) {
3939 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3943 fsp = file_fsp(req, SVAL(params,0));
3944 if (!fsp_is_np(fsp)) {
3945 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3949 info_level = SVAL(params,2);
3951 *pparams = (char *)SMB_REALLOC(*pparams,2);
3952 if (*pparams == NULL) {
3953 reply_nterror(req, NT_STATUS_NO_MEMORY);
3958 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3959 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3960 if (*ppdata == NULL ) {
3961 reply_nterror(req, NT_STATUS_NO_MEMORY);
3966 switch (info_level) {
3967 case SMB_FILE_STANDARD_INFORMATION:
3969 SOFF_T(pdata,0,4096LL);
3976 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3980 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3986 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3987 TALLOC_CTX *mem_ctx,
3988 uint16_t info_level,
3990 const struct smb_filename *smb_fname,
3991 bool delete_pending,
3992 struct timespec write_time_ts,
3994 struct ea_list *ea_list,
3995 int lock_data_count,
3998 unsigned int max_data_bytes,
4000 unsigned int *pdata_size)
4002 char *pdata = *ppdata;
4003 char *dstart, *dend;
4004 unsigned int data_size;
4005 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4006 time_t create_time, mtime, atime, c_time;
4007 SMB_STRUCT_STAT sbuf;
4014 uint64_t file_size = 0;
4016 uint64_t allocation_size = 0;
4017 uint64_t file_index = 0;
4018 uint32_t access_mask = 0;
4020 sbuf = smb_fname->st;
4022 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4023 return NT_STATUS_INVALID_LEVEL;
4026 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4027 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4028 info_level, max_data_bytes));
4031 mode = dos_mode_msdfs(conn, smb_fname);
4033 mode = dos_mode(conn, smb_fname);
4036 mode = FILE_ATTRIBUTE_NORMAL;
4038 nlink = sbuf.st_ex_nlink;
4040 if (nlink && (mode&aDIR)) {
4044 if ((nlink > 0) && delete_pending) {
4048 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4049 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4050 if (*ppdata == NULL) {
4051 return NT_STATUS_NO_MEMORY;
4055 dend = dstart + data_size - 1;
4057 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4058 update_stat_ex_mtime(&sbuf, write_time_ts);
4061 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4062 mtime_ts = sbuf.st_ex_mtime;
4063 atime_ts = sbuf.st_ex_atime;
4064 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4066 if (lp_dos_filetime_resolution(SNUM(conn))) {
4067 dos_filetime_timespec(&create_time_ts);
4068 dos_filetime_timespec(&mtime_ts);
4069 dos_filetime_timespec(&atime_ts);
4070 dos_filetime_timespec(&ctime_ts);
4073 create_time = convert_timespec_to_time_t(create_time_ts);
4074 mtime = convert_timespec_to_time_t(mtime_ts);
4075 atime = convert_timespec_to_time_t(atime_ts);
4076 c_time = convert_timespec_to_time_t(ctime_ts);
4078 p = strrchr_m(smb_fname->base_name,'/');
4080 base_name = smb_fname->base_name;
4084 /* NT expects the name to be in an exact form of the *full*
4085 filename. See the trans2 torture test */
4086 if (ISDOT(base_name)) {
4087 dos_fname = talloc_strdup(mem_ctx, "\\");
4089 return NT_STATUS_NO_MEMORY;
4092 dos_fname = talloc_asprintf(mem_ctx,
4094 smb_fname->base_name);
4096 return NT_STATUS_NO_MEMORY;
4098 if (is_ntfs_stream_smb_fname(smb_fname)) {
4099 dos_fname = talloc_asprintf(dos_fname, "%s",
4100 smb_fname->stream_name);
4102 return NT_STATUS_NO_MEMORY;
4106 string_replace(dos_fname, '/', '\\');
4109 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4112 /* Do we have this path open ? */
4114 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4115 fsp1 = file_find_di_first(fileid);
4116 if (fsp1 && fsp1->initial_allocation_size) {
4117 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4121 if (!(mode & aDIR)) {
4122 file_size = get_file_size_stat(&sbuf);
4126 pos = fsp->fh->position_information;
4130 access_mask = fsp->access_mask;
4132 /* GENERIC_EXECUTE mapping from Windows */
4133 access_mask = 0x12019F;
4136 /* This should be an index number - looks like
4139 I think this causes us to fail the IFSKIT
4140 BasicFileInformationTest. -tpot */
4141 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4142 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4144 switch (info_level) {
4145 case SMB_INFO_STANDARD:
4146 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4148 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4149 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4150 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4151 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4152 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4153 SSVAL(pdata,l1_attrFile,mode);
4156 case SMB_INFO_QUERY_EA_SIZE:
4158 unsigned int ea_size =
4159 estimate_ea_size(conn, fsp,
4160 smb_fname->base_name);
4161 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4163 srv_put_dos_date2(pdata,0,create_time);
4164 srv_put_dos_date2(pdata,4,atime);
4165 srv_put_dos_date2(pdata,8,mtime); /* write time */
4166 SIVAL(pdata,12,(uint32)file_size);
4167 SIVAL(pdata,16,(uint32)allocation_size);
4168 SSVAL(pdata,20,mode);
4169 SIVAL(pdata,22,ea_size);
4173 case SMB_INFO_IS_NAME_VALID:
4174 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4176 /* os/2 needs this ? really ?*/
4177 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4179 /* This is only reached for qpathinfo */
4183 case SMB_INFO_QUERY_EAS_FROM_LIST:
4185 size_t total_ea_len = 0;
4186 struct ea_list *ea_file_list = NULL;
4188 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4191 get_ea_list_from_file(mem_ctx, conn, fsp,
4192 smb_fname->base_name,
4194 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4196 if (!ea_list || (total_ea_len > data_size)) {
4198 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4202 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4206 case SMB_INFO_QUERY_ALL_EAS:
4208 /* We have data_size bytes to put EA's into. */
4209 size_t total_ea_len = 0;
4211 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4213 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4214 smb_fname->base_name,
4216 if (!ea_list || (total_ea_len > data_size)) {
4218 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4222 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4226 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4228 /* We have data_size bytes to put EA's into. */
4229 size_t total_ea_len = 0;
4230 struct ea_list *ea_file_list = NULL;
4232 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4234 /*TODO: add filtering and index handling */
4237 get_ea_list_from_file(mem_ctx, conn, fsp,
4238 smb_fname->base_name,
4240 if (!ea_file_list) {
4241 return NT_STATUS_NO_EAS_ON_FILE;
4244 status = fill_ea_chained_buffer(mem_ctx,
4248 conn, ea_file_list);
4249 if (!NT_STATUS_IS_OK(status)) {
4255 case SMB_FILE_BASIC_INFORMATION:
4256 case SMB_QUERY_FILE_BASIC_INFO:
4258 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4259 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4260 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4262 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4266 put_long_date_timespec(pdata,create_time_ts);
4267 put_long_date_timespec(pdata+8,atime_ts);
4268 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4269 put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4270 SIVAL(pdata,32,mode);
4272 DEBUG(5,("SMB_QFBI - "));
4273 DEBUG(5,("create: %s ", ctime(&create_time)));
4274 DEBUG(5,("access: %s ", ctime(&atime)));
4275 DEBUG(5,("write: %s ", ctime(&mtime)));
4276 DEBUG(5,("change: %s ", ctime(&c_time)));
4277 DEBUG(5,("mode: %x\n", mode));
4280 case SMB_FILE_STANDARD_INFORMATION:
4281 case SMB_QUERY_FILE_STANDARD_INFO:
4283 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4285 SOFF_T(pdata,0,allocation_size);
4286 SOFF_T(pdata,8,file_size);
4287 SIVAL(pdata,16,nlink);
4288 SCVAL(pdata,20,delete_pending?1:0);
4289 SCVAL(pdata,21,(mode&aDIR)?1:0);
4290 SSVAL(pdata,22,0); /* Padding. */
4293 case SMB_FILE_EA_INFORMATION:
4294 case SMB_QUERY_FILE_EA_INFO:
4296 unsigned int ea_size =
4297 estimate_ea_size(conn, fsp, smb_fname->base_name);
4298 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4300 SIVAL(pdata,0,ea_size);
4304 /* Get the 8.3 name - used if NT SMB was negotiated. */
4305 case SMB_QUERY_FILE_ALT_NAME_INFO:
4306 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4309 char mangled_name[13];
4310 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4311 if (!name_to_8_3(base_name,mangled_name,
4312 True,conn->params)) {
4313 return NT_STATUS_NO_MEMORY;
4315 len = srvstr_push(dstart, flags2,
4316 pdata+4, mangled_name,
4317 PTR_DIFF(dend, pdata+4),
4319 data_size = 4 + len;
4324 case SMB_QUERY_FILE_NAME_INFO:
4328 this must be *exactly* right for ACLs on mapped drives to work
4330 len = srvstr_push(dstart, flags2,
4332 PTR_DIFF(dend, pdata+4),
4334 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4335 data_size = 4 + len;
4340 case SMB_FILE_ALLOCATION_INFORMATION:
4341 case SMB_QUERY_FILE_ALLOCATION_INFO:
4342 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4344 SOFF_T(pdata,0,allocation_size);
4347 case SMB_FILE_END_OF_FILE_INFORMATION:
4348 case SMB_QUERY_FILE_END_OF_FILEINFO:
4349 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4351 SOFF_T(pdata,0,file_size);
4354 case SMB_QUERY_FILE_ALL_INFO:
4355 case SMB_FILE_ALL_INFORMATION:
4358 unsigned int ea_size =
4359 estimate_ea_size(conn, fsp, smb_fname->base_name);
4360 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4361 put_long_date_timespec(pdata,create_time_ts);
4362 put_long_date_timespec(pdata+8,atime_ts);
4363 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4364 put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4365 SIVAL(pdata,32,mode);
4366 SIVAL(pdata,36,0); /* padding. */
4368 SOFF_T(pdata,0,allocation_size);
4369 SOFF_T(pdata,8,file_size);
4370 SIVAL(pdata,16,nlink);
4371 SCVAL(pdata,20,delete_pending);
4372 SCVAL(pdata,21,(mode&aDIR)?1:0);
4375 SIVAL(pdata,0,ea_size);
4376 pdata += 4; /* EA info */
4377 len = srvstr_push(dstart, flags2,
4379 PTR_DIFF(dend, pdata+4),
4383 data_size = PTR_DIFF(pdata,(*ppdata));
4387 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4390 unsigned int ea_size =
4391 estimate_ea_size(conn, fsp, smb_fname->base_name);
4392 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4393 put_long_date_timespec(pdata+0x00,create_time_ts);
4394 put_long_date_timespec(pdata+0x08,atime_ts);
4395 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4396 put_long_date_timespec(pdata+0x18,ctime_ts); /* change time */
4397 SIVAL(pdata, 0x20, mode);
4398 SIVAL(pdata, 0x24, 0); /* padding. */
4399 SBVAL(pdata, 0x28, allocation_size);
4400 SBVAL(pdata, 0x30, file_size);
4401 SIVAL(pdata, 0x38, nlink);
4402 SCVAL(pdata, 0x3C, delete_pending);
4403 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4404 SSVAL(pdata, 0x3E, 0); /* padding */
4405 SBVAL(pdata, 0x40, file_index);
4406 SIVAL(pdata, 0x48, ea_size);
4407 SIVAL(pdata, 0x4C, access_mask);
4408 SBVAL(pdata, 0x50, pos);
4409 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4410 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4414 len = srvstr_push(dstart, flags2,
4416 PTR_DIFF(dend, pdata+4),
4420 data_size = PTR_DIFF(pdata,(*ppdata));
4423 case SMB_FILE_INTERNAL_INFORMATION:
4425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4426 SBVAL(pdata, 0, file_index);
4430 case SMB_FILE_ACCESS_INFORMATION:
4431 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4432 SIVAL(pdata, 0, access_mask);
4436 case SMB_FILE_NAME_INFORMATION:
4437 /* Pathname with leading '\'. */
4440 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4442 SIVAL(pdata,0,byte_len);
4443 data_size = 4 + byte_len;
4447 case SMB_FILE_DISPOSITION_INFORMATION:
4448 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4450 SCVAL(pdata,0,delete_pending);
4453 case SMB_FILE_POSITION_INFORMATION:
4454 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4456 SOFF_T(pdata,0,pos);
4459 case SMB_FILE_MODE_INFORMATION:
4460 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4461 SIVAL(pdata,0,mode);
4465 case SMB_FILE_ALIGNMENT_INFORMATION:
4466 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4467 SIVAL(pdata,0,0); /* No alignment needed. */
4472 * NT4 server just returns "invalid query" to this - if we try
4473 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4476 /* The first statement above is false - verified using Thursby
4477 * client against NT4 -- gcolley.
4479 case SMB_QUERY_FILE_STREAM_INFO:
4480 case SMB_FILE_STREAM_INFORMATION: {
4481 unsigned int num_streams;
4482 struct stream_struct *streams;
4484 DEBUG(10,("smbd_do_qfilepathinfo: "
4485 "SMB_FILE_STREAM_INFORMATION\n"));
4487 if (is_ntfs_stream_smb_fname(smb_fname)) {
4488 return NT_STATUS_INVALID_PARAMETER;
4491 status = SMB_VFS_STREAMINFO(
4492 conn, fsp, smb_fname->base_name, talloc_tos(),
4493 &num_streams, &streams);
4495 if (!NT_STATUS_IS_OK(status)) {
4496 DEBUG(10, ("could not get stream info: %s\n",
4497 nt_errstr(status)));
4501 status = marshall_stream_info(num_streams, streams,
4502 pdata, max_data_bytes,
4505 if (!NT_STATUS_IS_OK(status)) {
4506 DEBUG(10, ("marshall_stream_info failed: %s\n",
4507 nt_errstr(status)));
4511 TALLOC_FREE(streams);
4515 case SMB_QUERY_COMPRESSION_INFO:
4516 case SMB_FILE_COMPRESSION_INFORMATION:
4517 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4518 SOFF_T(pdata,0,file_size);
4519 SIVAL(pdata,8,0); /* ??? */
4520 SIVAL(pdata,12,0); /* ??? */
4524 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4525 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4526 put_long_date_timespec(pdata,create_time_ts);
4527 put_long_date_timespec(pdata+8,atime_ts);
4528 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4529 put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4530 SOFF_T(pdata,32,allocation_size);
4531 SOFF_T(pdata,40,file_size);
4532 SIVAL(pdata,48,mode);
4533 SIVAL(pdata,52,0); /* ??? */
4537 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4538 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4539 SIVAL(pdata,0,mode);
4545 * CIFS UNIX Extensions.
4548 case SMB_QUERY_FILE_UNIX_BASIC:
4550 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4551 data_size = PTR_DIFF(pdata,(*ppdata));
4555 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4557 for (i=0; i<100; i++)
4558 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4564 case SMB_QUERY_FILE_UNIX_INFO2:
4566 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4567 data_size = PTR_DIFF(pdata,(*ppdata));
4571 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4573 for (i=0; i<100; i++)
4574 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4580 case SMB_QUERY_FILE_UNIX_LINK:
4583 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4586 return NT_STATUS_NO_MEMORY;
4589 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4591 if(!S_ISLNK(sbuf.st_ex_mode)) {
4592 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4595 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4597 len = SMB_VFS_READLINK(conn,
4598 smb_fname->base_name,
4601 return map_nt_error_from_unix(errno);
4604 len = srvstr_push(dstart, flags2,
4606 PTR_DIFF(dend, pdata),
4609 data_size = PTR_DIFF(pdata,(*ppdata));
4614 #if defined(HAVE_POSIX_ACLS)
4615 case SMB_QUERY_POSIX_ACL:
4617 SMB_ACL_T file_acl = NULL;
4618 SMB_ACL_T def_acl = NULL;
4619 uint16 num_file_acls = 0;
4620 uint16 num_def_acls = 0;
4622 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4623 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4626 SMB_VFS_SYS_ACL_GET_FILE(conn,
4627 smb_fname->base_name,
4628 SMB_ACL_TYPE_ACCESS);
4631 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4632 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4633 "not implemented on "
4634 "filesystem containing %s\n",
4635 smb_fname->base_name));
4636 return NT_STATUS_NOT_IMPLEMENTED;
4639 if (S_ISDIR(sbuf.st_ex_mode)) {
4640 if (fsp && fsp->is_directory) {
4642 SMB_VFS_SYS_ACL_GET_FILE(
4644 fsp->fsp_name->base_name,
4645 SMB_ACL_TYPE_DEFAULT);
4648 SMB_VFS_SYS_ACL_GET_FILE(
4650 smb_fname->base_name,
4651 SMB_ACL_TYPE_DEFAULT);
4653 def_acl = free_empty_sys_acl(conn, def_acl);
4656 num_file_acls = count_acl_entries(conn, file_acl);
4657 num_def_acls = count_acl_entries(conn, def_acl);
4659 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4660 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4662 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4663 SMB_POSIX_ACL_HEADER_SIZE) ));
4665 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4668 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4670 return NT_STATUS_BUFFER_TOO_SMALL;
4673 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4674 SSVAL(pdata,2,num_file_acls);
4675 SSVAL(pdata,4,num_def_acls);
4676 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4678 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4681 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4683 return NT_STATUS_INTERNAL_ERROR;
4685 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4687 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4690 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4692 return NT_STATUS_INTERNAL_ERROR;
4696 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4699 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4701 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4707 case SMB_QUERY_POSIX_LOCK:
4712 enum brl_type lock_type;
4714 /* We need an open file with a real fd for this. */
4715 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4716 return NT_STATUS_INVALID_LEVEL;
4719 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4720 return NT_STATUS_INVALID_PARAMETER;
4723 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4724 case POSIX_LOCK_TYPE_READ:
4725 lock_type = READ_LOCK;
4727 case POSIX_LOCK_TYPE_WRITE:
4728 lock_type = WRITE_LOCK;
4730 case POSIX_LOCK_TYPE_UNLOCK:
4732 /* There's no point in asking for an unlock... */
4733 return NT_STATUS_INVALID_PARAMETER;
4736 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4737 #if defined(HAVE_LONGLONG)
4738 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4739 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4740 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4741 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4742 #else /* HAVE_LONGLONG */
4743 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4744 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4745 #endif /* HAVE_LONGLONG */
4747 status = query_lock(fsp,
4754 if (ERROR_WAS_LOCK_DENIED(status)) {
4755 /* Here we need to report who has it locked... */
4756 data_size = POSIX_LOCK_DATA_SIZE;
4758 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4759 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4760 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4761 #if defined(HAVE_LONGLONG)
4762 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4763 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4764 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4765 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4766 #else /* HAVE_LONGLONG */
4767 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4768 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4769 #endif /* HAVE_LONGLONG */
4771 } else if (NT_STATUS_IS_OK(status)) {
4772 /* For success we just return a copy of what we sent
4773 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4774 data_size = POSIX_LOCK_DATA_SIZE;
4775 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4776 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4784 return NT_STATUS_INVALID_LEVEL;
4787 *pdata_size = data_size;
4788 return NT_STATUS_OK;
4791 /****************************************************************************
4792 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4793 file name or file id).
4794 ****************************************************************************/
4796 static void call_trans2qfilepathinfo(connection_struct *conn,
4797 struct smb_request *req,
4798 unsigned int tran_call,
4799 char **pparams, int total_params,
4800 char **ppdata, int total_data,
4801 unsigned int max_data_bytes)
4803 char *params = *pparams;
4804 char *pdata = *ppdata;
4806 unsigned int data_size = 0;
4807 unsigned int param_size = 2;
4808 struct smb_filename *smb_fname = NULL;
4809 bool delete_pending = False;
4810 struct timespec write_time_ts;
4811 files_struct *fsp = NULL;
4812 struct file_id fileid;
4813 struct ea_list *ea_list = NULL;
4814 int lock_data_count = 0;
4815 char *lock_data = NULL;
4816 bool ms_dfs_link = false;
4817 NTSTATUS status = NT_STATUS_OK;
4820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4824 ZERO_STRUCT(write_time_ts);
4826 if (tran_call == TRANSACT2_QFILEINFO) {
4827 if (total_params < 4) {
4828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4833 call_trans2qpipeinfo(conn, req, tran_call,
4834 pparams, total_params,
4840 fsp = file_fsp(req, SVAL(params,0));
4841 info_level = SVAL(params,2);
4843 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4845 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4846 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4850 /* Initial check for valid fsp ptr. */
4851 if (!check_fsp_open(conn, req, fsp)) {
4855 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4857 if (!NT_STATUS_IS_OK(status)) {
4858 reply_nterror(req, status);
4862 if(fsp->fake_file_handle) {
4864 * This is actually for the QUOTA_FAKE_FILE --metze
4867 /* We know this name is ok, it's already passed the checks. */
4869 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4871 * This is actually a QFILEINFO on a directory
4872 * handle (returned from an NT SMB). NT5.0 seems
4873 * to do this call. JRA.
4876 if (INFO_LEVEL_IS_UNIX(info_level)) {
4877 /* Always do lstat for UNIX calls. */
4878 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4879 DEBUG(3,("call_trans2qfilepathinfo: "
4880 "SMB_VFS_LSTAT of %s failed "
4882 smb_fname_str_dbg(smb_fname),
4885 map_nt_error_from_unix(errno));
4888 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4889 DEBUG(3,("call_trans2qfilepathinfo: "
4890 "SMB_VFS_STAT of %s failed (%s)\n",
4891 smb_fname_str_dbg(smb_fname),
4894 map_nt_error_from_unix(errno));
4898 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4899 get_file_infos(fileid, &delete_pending, &write_time_ts);
4902 * Original code - this is an open file.
4904 if (!check_fsp(conn, req, fsp)) {
4908 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4909 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4910 fsp->fnum, strerror(errno)));
4912 map_nt_error_from_unix(errno));
4915 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4916 get_file_infos(fileid, &delete_pending, &write_time_ts);
4923 if (total_params < 7) {
4924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4928 info_level = SVAL(params,0);
4930 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4932 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4933 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4937 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4939 STR_TERMINATE, &status);
4940 if (!NT_STATUS_IS_OK(status)) {
4941 reply_nterror(req, status);
4945 status = filename_convert(req,
4947 req->flags2 & FLAGS2_DFS_PATHNAMES,
4952 if (!NT_STATUS_IS_OK(status)) {
4953 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4954 reply_botherror(req,
4955 NT_STATUS_PATH_NOT_COVERED,
4956 ERRSRV, ERRbadpath);
4959 reply_nterror(req, status);
4963 /* If this is a stream, check if there is a delete_pending. */
4964 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4965 && is_ntfs_stream_smb_fname(smb_fname)) {
4966 struct smb_filename *smb_fname_base = NULL;
4968 /* Create an smb_filename with stream_name == NULL. */
4970 create_synthetic_smb_fname(talloc_tos(),
4971 smb_fname->base_name,
4974 if (!NT_STATUS_IS_OK(status)) {
4975 reply_nterror(req, status);
4979 if (INFO_LEVEL_IS_UNIX(info_level)) {
4980 /* Always do lstat for UNIX calls. */
4981 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4982 DEBUG(3,("call_trans2qfilepathinfo: "
4983 "SMB_VFS_LSTAT of %s failed "
4985 smb_fname_str_dbg(smb_fname_base),
4987 TALLOC_FREE(smb_fname_base);
4989 map_nt_error_from_unix(errno));
4993 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4994 DEBUG(3,("call_trans2qfilepathinfo: "
4995 "fileinfo of %s failed "
4997 smb_fname_str_dbg(smb_fname_base),
4999 TALLOC_FREE(smb_fname_base);
5001 map_nt_error_from_unix(errno));
5006 fileid = vfs_file_id_from_sbuf(conn,
5007 &smb_fname_base->st);
5008 TALLOC_FREE(smb_fname_base);
5009 get_file_infos(fileid, &delete_pending, NULL);
5010 if (delete_pending) {
5011 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5016 if (INFO_LEVEL_IS_UNIX(info_level)) {
5017 /* Always do lstat for UNIX calls. */
5018 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5019 DEBUG(3,("call_trans2qfilepathinfo: "
5020 "SMB_VFS_LSTAT of %s failed (%s)\n",
5021 smb_fname_str_dbg(smb_fname),
5024 map_nt_error_from_unix(errno));
5028 } else if (!VALID_STAT(smb_fname->st) &&
5029 SMB_VFS_STAT(conn, smb_fname) &&
5030 (info_level != SMB_INFO_IS_NAME_VALID)) {
5031 ms_dfs_link = check_msdfs_link(conn,
5032 smb_fname->base_name,
5036 DEBUG(3,("call_trans2qfilepathinfo: "
5037 "SMB_VFS_STAT of %s failed (%s)\n",
5038 smb_fname_str_dbg(smb_fname),
5041 map_nt_error_from_unix(errno));
5046 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5047 get_file_infos(fileid, &delete_pending, &write_time_ts);
5048 if (delete_pending) {
5049 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5054 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5055 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5056 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5058 /* Pull out any data sent here before we realloc. */
5059 switch (info_level) {
5060 case SMB_INFO_QUERY_EAS_FROM_LIST:
5062 /* Pull any EA list from the data portion. */
5065 if (total_data < 4) {
5067 req, NT_STATUS_INVALID_PARAMETER);
5070 ea_size = IVAL(pdata,0);
5072 if (total_data > 0 && ea_size != total_data) {
5073 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5074 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5076 req, NT_STATUS_INVALID_PARAMETER);
5080 if (!lp_ea_support(SNUM(conn))) {
5081 reply_doserror(req, ERRDOS,
5082 ERReasnotsupported);
5086 /* Pull out the list of names. */
5087 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5090 req, NT_STATUS_INVALID_PARAMETER);
5096 case SMB_QUERY_POSIX_LOCK:
5098 if (fsp == NULL || fsp->fh->fd == -1) {
5099 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5103 if (total_data != POSIX_LOCK_DATA_SIZE) {
5105 req, NT_STATUS_INVALID_PARAMETER);
5109 /* Copy the lock range data. */
5110 lock_data = (char *)TALLOC_MEMDUP(
5111 req, pdata, total_data);
5113 reply_nterror(req, NT_STATUS_NO_MEMORY);
5116 lock_data_count = total_data;
5122 *pparams = (char *)SMB_REALLOC(*pparams,2);
5123 if (*pparams == NULL) {
5124 reply_nterror(req, NT_STATUS_NO_MEMORY);
5131 * draft-leach-cifs-v1-spec-02.txt
5132 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5135 * The requested information is placed in the Data portion of the
5136 * transaction response. For the information levels greater than 0x100,
5137 * the transaction response has 1 parameter word which should be
5138 * ignored by the client.
5140 * However Windows only follows this rule for the IS_NAME_VALID call.
5142 switch (info_level) {
5143 case SMB_INFO_IS_NAME_VALID:
5148 if ((info_level & 0xFF00) == 0xFF00) {
5150 * We use levels that start with 0xFF00
5151 * internally to represent SMB2 specific levels
5153 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5157 status = smbd_do_qfilepathinfo(conn, req, info_level,
5159 delete_pending, write_time_ts,
5160 ms_dfs_link, ea_list,
5161 lock_data_count, lock_data,
5162 req->flags2, max_data_bytes,
5163 ppdata, &data_size);
5164 if (!NT_STATUS_IS_OK(status)) {
5165 reply_nterror(req, status);
5169 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5175 /****************************************************************************
5176 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5178 ****************************************************************************/
5180 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5181 connection_struct *conn,
5182 const struct smb_filename *smb_fname_old,
5183 const struct smb_filename *smb_fname_new)
5185 NTSTATUS status = NT_STATUS_OK;
5187 /* source must already exist. */
5188 if (!VALID_STAT(smb_fname_old->st)) {
5189 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5192 /* Disallow if newname already exists. */
5193 if (VALID_STAT(smb_fname_new->st)) {
5194 return NT_STATUS_OBJECT_NAME_COLLISION;
5197 /* No links from a directory. */
5198 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5199 return NT_STATUS_FILE_IS_A_DIRECTORY;
5202 /* Setting a hardlink to/from a stream isn't currently supported. */
5203 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5204 is_ntfs_stream_smb_fname(smb_fname_new)) {
5205 return NT_STATUS_INVALID_PARAMETER;
5208 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5209 smb_fname_old->base_name, smb_fname_new->base_name));
5211 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5212 smb_fname_new->base_name) != 0) {
5213 status = map_nt_error_from_unix(errno);
5214 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5215 nt_errstr(status), smb_fname_old->base_name,
5216 smb_fname_new->base_name));
5221 /****************************************************************************
5222 Deal with setting the time from any of the setfilepathinfo functions.
5223 ****************************************************************************/
5225 NTSTATUS smb_set_file_time(connection_struct *conn,
5227 const struct smb_filename *smb_fname,
5228 struct smb_file_time *ft,
5229 bool setting_write_time)
5231 struct smb_filename *smb_fname_base = NULL;
5233 FILE_NOTIFY_CHANGE_LAST_ACCESS
5234 |FILE_NOTIFY_CHANGE_LAST_WRITE
5235 |FILE_NOTIFY_CHANGE_CREATION;
5238 if (!VALID_STAT(smb_fname->st)) {
5239 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5242 /* get some defaults (no modifications) if any info is zero or -1. */
5243 if (null_timespec(ft->create_time)) {
5244 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5247 if (null_timespec(ft->atime)) {
5248 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5251 if (null_timespec(ft->mtime)) {
5252 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5255 if (!setting_write_time) {
5256 /* ft->mtime comes from change time, not write time. */
5257 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5260 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5261 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5262 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5263 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5264 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5265 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5266 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5267 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5269 if (setting_write_time) {
5271 * This was a Windows setfileinfo on an open file.
5272 * NT does this a lot. We also need to
5273 * set the time here, as it can be read by
5274 * FindFirst/FindNext and with the patch for bug #2045
5275 * in smbd/fileio.c it ensures that this timestamp is
5276 * kept sticky even after a write. We save the request
5277 * away and will set it on file close and after a write. JRA.
5280 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5281 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5284 if (fsp->base_fsp) {
5285 set_sticky_write_time_fsp(fsp->base_fsp,
5288 set_sticky_write_time_fsp(fsp, ft->mtime);
5291 set_sticky_write_time_path(
5292 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5297 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5299 /* Always call ntimes on the base, even if a stream was passed in. */
5300 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5301 NULL, &smb_fname->st,
5303 if (!NT_STATUS_IS_OK(status)) {
5307 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5308 TALLOC_FREE(smb_fname_base);
5309 return map_nt_error_from_unix(errno);
5311 TALLOC_FREE(smb_fname_base);
5313 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5314 smb_fname->base_name);
5315 return NT_STATUS_OK;
5318 /****************************************************************************
5319 Deal with setting the dosmode from any of the setfilepathinfo functions.
5320 ****************************************************************************/
5322 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5323 const struct smb_filename *smb_fname,
5326 struct smb_filename *smb_fname_base = NULL;
5329 if (!VALID_STAT(smb_fname->st)) {
5330 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5333 /* Always operate on the base_name, even if a stream was passed in. */
5334 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5335 NULL, &smb_fname->st,
5337 if (!NT_STATUS_IS_OK(status)) {
5342 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5349 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5351 /* check the mode isn't different, before changing it */
5352 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5353 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5354 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5355 (unsigned int)dosmode));
5357 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5359 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5361 smb_fname_str_dbg(smb_fname_base),
5363 status = map_nt_error_from_unix(errno);
5367 status = NT_STATUS_OK;
5369 TALLOC_FREE(smb_fname_base);
5373 /****************************************************************************
5374 Deal with setting the size from any of the setfilepathinfo functions.
5375 ****************************************************************************/
5377 static NTSTATUS smb_set_file_size(connection_struct *conn,
5378 struct smb_request *req,
5380 const struct smb_filename *smb_fname,
5381 const SMB_STRUCT_STAT *psbuf,
5384 NTSTATUS status = NT_STATUS_OK;
5385 struct smb_filename *smb_fname_tmp = NULL;
5386 files_struct *new_fsp = NULL;
5388 if (!VALID_STAT(*psbuf)) {
5389 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5392 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5394 if (size == get_file_size_stat(psbuf)) {
5395 return NT_STATUS_OK;
5398 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5399 smb_fname_str_dbg(smb_fname), (double)size));
5401 if (fsp && fsp->fh->fd != -1) {
5402 /* Handle based call. */
5403 if (vfs_set_filelen(fsp, size) == -1) {
5404 return map_nt_error_from_unix(errno);
5406 trigger_write_time_update_immediate(fsp);
5407 return NT_STATUS_OK;
5410 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5411 if (!NT_STATUS_IS_OK(status)) {
5415 smb_fname_tmp->st = *psbuf;
5417 status = SMB_VFS_CREATE_FILE(
5420 0, /* root_dir_fid */
5421 smb_fname_tmp, /* fname */
5422 FILE_WRITE_ATTRIBUTES, /* access_mask */
5423 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5425 FILE_OPEN, /* create_disposition*/
5426 0, /* create_options */
5427 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5428 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5429 0, /* allocation_size */
5432 &new_fsp, /* result */
5435 TALLOC_FREE(smb_fname_tmp);
5437 if (!NT_STATUS_IS_OK(status)) {
5438 /* NB. We check for open_was_deferred in the caller. */
5442 if (vfs_set_filelen(new_fsp, size) == -1) {
5443 status = map_nt_error_from_unix(errno);
5444 close_file(req, new_fsp,NORMAL_CLOSE);
5448 trigger_write_time_update_immediate(new_fsp);
5449 close_file(req, new_fsp,NORMAL_CLOSE);
5450 return NT_STATUS_OK;
5453 /****************************************************************************
5454 Deal with SMB_INFO_SET_EA.
5455 ****************************************************************************/
5457 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5461 const struct smb_filename *smb_fname)
5463 struct ea_list *ea_list = NULL;
5464 TALLOC_CTX *ctx = NULL;
5465 NTSTATUS status = NT_STATUS_OK;
5467 if (total_data < 10) {
5469 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5470 length. They seem to have no effect. Bug #3212. JRA */
5472 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5473 /* We're done. We only get EA info in this call. */
5474 return NT_STATUS_OK;
5477 return NT_STATUS_INVALID_PARAMETER;
5480 if (IVAL(pdata,0) > total_data) {
5481 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5482 IVAL(pdata,0), (unsigned int)total_data));
5483 return NT_STATUS_INVALID_PARAMETER;
5487 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5489 return NT_STATUS_INVALID_PARAMETER;
5491 status = set_ea(conn, fsp, smb_fname, ea_list);
5496 /****************************************************************************
5497 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5498 ****************************************************************************/
5500 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5504 const struct smb_filename *smb_fname)
5506 NTSTATUS status = NT_STATUS_OK;
5507 bool delete_on_close;
5510 if (total_data < 1) {
5511 return NT_STATUS_INVALID_PARAMETER;
5515 return NT_STATUS_INVALID_HANDLE;
5518 delete_on_close = (CVAL(pdata,0) ? True : False);
5519 dosmode = dos_mode(conn, smb_fname);
5521 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5522 "delete_on_close = %u\n",
5523 smb_fname_str_dbg(smb_fname),
5524 (unsigned int)dosmode,
5525 (unsigned int)delete_on_close ));
5527 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5529 if (!NT_STATUS_IS_OK(status)) {
5533 /* The set is across all open files on this dev/inode pair. */
5534 if (!set_delete_on_close(fsp, delete_on_close,
5535 &conn->server_info->utok)) {
5536 return NT_STATUS_ACCESS_DENIED;
5538 return NT_STATUS_OK;
5541 /****************************************************************************
5542 Deal with SMB_FILE_POSITION_INFORMATION.
5543 ****************************************************************************/
5545 static NTSTATUS smb_file_position_information(connection_struct *conn,
5550 uint64_t position_information;
5552 if (total_data < 8) {
5553 return NT_STATUS_INVALID_PARAMETER;
5557 /* Ignore on pathname based set. */
5558 return NT_STATUS_OK;
5561 position_information = (uint64_t)IVAL(pdata,0);
5562 #ifdef LARGE_SMB_OFF_T
5563 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5564 #else /* LARGE_SMB_OFF_T */
5565 if (IVAL(pdata,4) != 0) {
5566 /* more than 32 bits? */
5567 return NT_STATUS_INVALID_PARAMETER;
5569 #endif /* LARGE_SMB_OFF_T */
5571 DEBUG(10,("smb_file_position_information: Set file position "
5572 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5573 (double)position_information));
5574 fsp->fh->position_information = position_information;
5575 return NT_STATUS_OK;
5578 /****************************************************************************
5579 Deal with SMB_FILE_MODE_INFORMATION.
5580 ****************************************************************************/
5582 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5588 if (total_data < 4) {
5589 return NT_STATUS_INVALID_PARAMETER;
5591 mode = IVAL(pdata,0);
5592 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5593 return NT_STATUS_INVALID_PARAMETER;
5595 return NT_STATUS_OK;
5598 /****************************************************************************
5599 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5600 ****************************************************************************/
5602 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5603 struct smb_request *req,
5606 const struct smb_filename *smb_fname)
5608 char *link_target = NULL;
5609 const char *newname = smb_fname->base_name;
5610 NTSTATUS status = NT_STATUS_OK;
5611 TALLOC_CTX *ctx = talloc_tos();
5613 /* Set a symbolic link. */
5614 /* Don't allow this if follow links is false. */
5616 if (total_data == 0) {
5617 return NT_STATUS_INVALID_PARAMETER;
5620 if (!lp_symlinks(SNUM(conn))) {
5621 return NT_STATUS_ACCESS_DENIED;
5624 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5625 total_data, STR_TERMINATE);
5628 return NT_STATUS_INVALID_PARAMETER;
5631 /* !widelinks forces the target path to be within the share. */
5632 /* This means we can interpret the target as a pathname. */
5633 if (!lp_widelinks(SNUM(conn))) {
5634 char *rel_name = NULL;
5635 char *last_dirp = NULL;
5637 if (*link_target == '/') {
5638 /* No absolute paths allowed. */
5639 return NT_STATUS_ACCESS_DENIED;
5641 rel_name = talloc_strdup(ctx,newname);
5643 return NT_STATUS_NO_MEMORY;
5645 last_dirp = strrchr_m(rel_name, '/');
5647 last_dirp[1] = '\0';
5649 rel_name = talloc_strdup(ctx,"./");
5651 return NT_STATUS_NO_MEMORY;
5654 rel_name = talloc_asprintf_append(rel_name,
5658 return NT_STATUS_NO_MEMORY;
5661 status = check_name(conn, rel_name);
5662 if (!NT_STATUS_IS_OK(status)) {
5667 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5668 newname, link_target ));
5670 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5671 return map_nt_error_from_unix(errno);
5674 return NT_STATUS_OK;
5677 /****************************************************************************
5678 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5679 ****************************************************************************/
5681 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5682 struct smb_request *req,
5683 const char *pdata, int total_data,
5684 const struct smb_filename *smb_fname_new)
5686 char *oldname = NULL;
5687 struct smb_filename *smb_fname_old = NULL;
5688 TALLOC_CTX *ctx = talloc_tos();
5689 NTSTATUS status = NT_STATUS_OK;
5691 /* Set a hard link. */
5692 if (total_data == 0) {
5693 return NT_STATUS_INVALID_PARAMETER;
5696 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5697 total_data, STR_TERMINATE, &status);
5698 if (!NT_STATUS_IS_OK(status)) {
5702 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5703 smb_fname_str_dbg(smb_fname_new), oldname));
5705 status = filename_convert(ctx,
5707 req->flags2 & FLAGS2_DFS_PATHNAMES,
5712 if (!NT_STATUS_IS_OK(status)) {
5716 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5719 /****************************************************************************
5720 Deal with SMB_FILE_RENAME_INFORMATION.
5721 ****************************************************************************/
5723 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5724 struct smb_request *req,
5728 struct smb_filename *smb_fname_src)
5733 char *newname = NULL;
5734 struct smb_filename *smb_fname_dst = NULL;
5735 bool dest_has_wcard = False;
5736 NTSTATUS status = NT_STATUS_OK;
5738 TALLOC_CTX *ctx = talloc_tos();
5740 if (total_data < 13) {
5741 return NT_STATUS_INVALID_PARAMETER;
5744 overwrite = (CVAL(pdata,0) ? True : False);
5745 root_fid = IVAL(pdata,4);
5746 len = IVAL(pdata,8);
5748 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5749 return NT_STATUS_INVALID_PARAMETER;
5752 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5755 if (!NT_STATUS_IS_OK(status)) {
5759 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5762 status = resolve_dfspath_wcard(ctx, conn,
5763 req->flags2 & FLAGS2_DFS_PATHNAMES,
5767 if (!NT_STATUS_IS_OK(status)) {
5771 /* Check the new name has no '/' characters. */
5772 if (strchr_m(newname, '/')) {
5773 return NT_STATUS_NOT_SUPPORTED;
5776 if (fsp && fsp->base_fsp) {
5777 /* newname must be a stream name. */
5778 if (newname[0] != ':') {
5779 return NT_STATUS_NOT_SUPPORTED;
5782 /* Create an smb_fname to call rename_internals_fsp() with. */
5783 status = create_synthetic_smb_fname(talloc_tos(),
5784 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5786 if (!NT_STATUS_IS_OK(status)) {
5791 * Set the original last component, since
5792 * rename_internals_fsp() requires it.
5794 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5796 if (smb_fname_dst->original_lcomp == NULL) {
5797 status = NT_STATUS_NO_MEMORY;
5803 * Build up an smb_fname_dst based on the filename passed in.
5804 * We basically just strip off the last component, and put on
5805 * the newname instead.
5807 char *base_name = NULL;
5809 /* newname must *not* be a stream name. */
5810 if (newname[0] == ':') {
5811 return NT_STATUS_NOT_SUPPORTED;
5815 * Strip off the last component (filename) of the path passed
5818 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5820 return NT_STATUS_NO_MEMORY;
5822 p = strrchr_m(base_name, '/');
5826 base_name = talloc_strdup(ctx, "./");
5828 return NT_STATUS_NO_MEMORY;
5831 /* Append the new name. */
5832 base_name = talloc_asprintf_append(base_name,
5836 return NT_STATUS_NO_MEMORY;
5839 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
5842 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
5845 /* If an error we expect this to be
5846 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5848 if (!NT_STATUS_IS_OK(status)) {
5849 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5853 /* Create an smb_fname to call rename_internals_fsp() */
5854 status = create_synthetic_smb_fname(ctx,
5858 if (!NT_STATUS_IS_OK(status)) {
5865 DEBUG(10,("smb_file_rename_information: "
5866 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5867 fsp->fnum, fsp_str_dbg(fsp),
5868 smb_fname_str_dbg(smb_fname_dst)));
5869 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5872 DEBUG(10,("smb_file_rename_information: "
5873 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5874 smb_fname_str_dbg(smb_fname_src),
5875 smb_fname_str_dbg(smb_fname_dst)));
5876 status = rename_internals(ctx, conn, req, smb_fname_src,
5877 smb_fname_dst, 0, overwrite, false,
5879 FILE_WRITE_ATTRIBUTES);
5882 TALLOC_FREE(smb_fname_dst);
5886 /****************************************************************************
5887 Deal with SMB_SET_POSIX_ACL.
5888 ****************************************************************************/
5890 #if defined(HAVE_POSIX_ACLS)
5891 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5895 const struct smb_filename *smb_fname)
5897 uint16 posix_acl_version;
5898 uint16 num_file_acls;
5899 uint16 num_def_acls;
5900 bool valid_file_acls = True;
5901 bool valid_def_acls = True;
5903 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5904 return NT_STATUS_INVALID_PARAMETER;
5906 posix_acl_version = SVAL(pdata,0);
5907 num_file_acls = SVAL(pdata,2);
5908 num_def_acls = SVAL(pdata,4);
5910 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5911 valid_file_acls = False;
5915 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5916 valid_def_acls = False;
5920 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5921 return NT_STATUS_INVALID_PARAMETER;
5924 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5925 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5926 return NT_STATUS_INVALID_PARAMETER;
5929 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5930 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
5931 (unsigned int)num_file_acls,
5932 (unsigned int)num_def_acls));
5934 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
5935 smb_fname->base_name, num_file_acls,
5936 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5937 return map_nt_error_from_unix(errno);
5940 if (valid_def_acls && !set_unix_posix_default_acl(conn,
5941 smb_fname->base_name, &smb_fname->st, num_def_acls,
5942 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5943 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5944 return map_nt_error_from_unix(errno);
5946 return NT_STATUS_OK;
5950 /****************************************************************************
5951 Deal with SMB_SET_POSIX_LOCK.
5952 ****************************************************************************/
5954 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5955 struct smb_request *req,
5963 bool blocking_lock = False;
5964 enum brl_type lock_type;
5966 NTSTATUS status = NT_STATUS_OK;
5968 if (fsp == NULL || fsp->fh->fd == -1) {
5969 return NT_STATUS_INVALID_HANDLE;
5972 if (total_data != POSIX_LOCK_DATA_SIZE) {
5973 return NT_STATUS_INVALID_PARAMETER;
5976 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5977 case POSIX_LOCK_TYPE_READ:
5978 lock_type = READ_LOCK;
5980 case POSIX_LOCK_TYPE_WRITE:
5981 /* Return the right POSIX-mappable error code for files opened read-only. */
5982 if (!fsp->can_write) {
5983 return NT_STATUS_INVALID_HANDLE;
5985 lock_type = WRITE_LOCK;
5987 case POSIX_LOCK_TYPE_UNLOCK:
5988 lock_type = UNLOCK_LOCK;
5991 return NT_STATUS_INVALID_PARAMETER;
5994 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5995 blocking_lock = False;
5996 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5997 blocking_lock = True;
5999 return NT_STATUS_INVALID_PARAMETER;
6002 if (!lp_blocking_locks(SNUM(conn))) {
6003 blocking_lock = False;
6006 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6007 #if defined(HAVE_LONGLONG)
6008 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6009 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6010 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6011 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6012 #else /* HAVE_LONGLONG */
6013 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6014 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6015 #endif /* HAVE_LONGLONG */
6017 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6018 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6020 (unsigned int)lock_type,
6021 (unsigned int)lock_pid,
6025 if (lock_type == UNLOCK_LOCK) {
6026 status = do_unlock(smbd_messaging_context(),
6033 uint32 block_smbpid;
6035 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6047 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6049 * A blocking lock was requested. Package up
6050 * this smb into a queued request and push it
6051 * onto the blocking lock queue.
6053 if(push_blocking_lock_request(br_lck,
6056 -1, /* infinite timeout. */
6064 TALLOC_FREE(br_lck);
6068 TALLOC_FREE(br_lck);
6074 /****************************************************************************
6075 Deal with SMB_SET_FILE_BASIC_INFO.
6076 ****************************************************************************/
6078 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6082 const struct smb_filename *smb_fname)
6084 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6085 struct smb_file_time ft;
6087 NTSTATUS status = NT_STATUS_OK;
6091 if (total_data < 36) {
6092 return NT_STATUS_INVALID_PARAMETER;
6095 /* Set the attributes */
6096 dosmode = IVAL(pdata,32);
6097 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6098 if (!NT_STATUS_IS_OK(status)) {
6103 ft.create_time = interpret_long_date(pdata);
6106 ft.atime = interpret_long_date(pdata+8);
6109 ft.mtime = interpret_long_date(pdata+16);
6112 ft.ctime = interpret_long_date(pdata+24);
6114 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6115 smb_fname_str_dbg(smb_fname)));
6117 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6121 /****************************************************************************
6122 Deal with SMB_INFO_STANDARD.
6123 ****************************************************************************/
6125 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6129 const struct smb_filename *smb_fname)
6131 struct smb_file_time ft;
6135 if (total_data < 12) {
6136 return NT_STATUS_INVALID_PARAMETER;
6140 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6142 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6144 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6146 DEBUG(10,("smb_set_info_standard: file %s\n",
6147 smb_fname_str_dbg(smb_fname)));
6149 return smb_set_file_time(conn,
6156 /****************************************************************************
6157 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6158 ****************************************************************************/
6160 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6161 struct smb_request *req,
6165 struct smb_filename *smb_fname)
6167 uint64_t allocation_size = 0;
6168 NTSTATUS status = NT_STATUS_OK;
6169 files_struct *new_fsp = NULL;
6171 if (!VALID_STAT(smb_fname->st)) {
6172 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6175 if (total_data < 8) {
6176 return NT_STATUS_INVALID_PARAMETER;
6179 allocation_size = (uint64_t)IVAL(pdata,0);
6180 #ifdef LARGE_SMB_OFF_T
6181 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6182 #else /* LARGE_SMB_OFF_T */
6183 if (IVAL(pdata,4) != 0) {
6184 /* more than 32 bits? */
6185 return NT_STATUS_INVALID_PARAMETER;
6187 #endif /* LARGE_SMB_OFF_T */
6189 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6190 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6191 (double)allocation_size));
6193 if (allocation_size) {
6194 allocation_size = smb_roundup(conn, allocation_size);
6197 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6198 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6199 (double)allocation_size));
6201 if (fsp && fsp->fh->fd != -1) {
6202 /* Open file handle. */
6203 /* Only change if needed. */
6204 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6205 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6206 return map_nt_error_from_unix(errno);
6209 /* But always update the time. */
6211 * This is equivalent to a write. Ensure it's seen immediately
6212 * if there are no pending writes.
6214 trigger_write_time_update_immediate(fsp);
6215 return NT_STATUS_OK;
6218 /* Pathname or stat or directory file. */
6219 status = SMB_VFS_CREATE_FILE(
6222 0, /* root_dir_fid */
6223 smb_fname, /* fname */
6224 FILE_WRITE_DATA, /* access_mask */
6225 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6227 FILE_OPEN, /* create_disposition*/
6228 0, /* create_options */
6229 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6230 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6231 0, /* allocation_size */
6234 &new_fsp, /* result */
6237 if (!NT_STATUS_IS_OK(status)) {
6238 /* NB. We check for open_was_deferred in the caller. */
6242 /* Only change if needed. */
6243 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6244 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6245 status = map_nt_error_from_unix(errno);
6246 close_file(req, new_fsp, NORMAL_CLOSE);
6251 /* Changing the allocation size should set the last mod time. */
6253 * This is equivalent to a write. Ensure it's seen immediately
6254 * if there are no pending writes.
6256 trigger_write_time_update_immediate(new_fsp);
6258 close_file(req, new_fsp, NORMAL_CLOSE);
6259 return NT_STATUS_OK;
6262 /****************************************************************************
6263 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6264 ****************************************************************************/
6266 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6267 struct smb_request *req,
6271 const struct smb_filename *smb_fname)
6275 if (total_data < 8) {
6276 return NT_STATUS_INVALID_PARAMETER;
6279 size = IVAL(pdata,0);
6280 #ifdef LARGE_SMB_OFF_T
6281 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6282 #else /* LARGE_SMB_OFF_T */
6283 if (IVAL(pdata,4) != 0) {
6284 /* more than 32 bits? */
6285 return NT_STATUS_INVALID_PARAMETER;
6287 #endif /* LARGE_SMB_OFF_T */
6288 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6289 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6292 return smb_set_file_size(conn, req,
6299 /****************************************************************************
6300 Allow a UNIX info mknod.
6301 ****************************************************************************/
6303 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6306 const struct smb_filename *smb_fname)
6308 uint32 file_type = IVAL(pdata,56);
6309 #if defined(HAVE_MAKEDEV)
6310 uint32 dev_major = IVAL(pdata,60);
6311 uint32 dev_minor = IVAL(pdata,68);
6313 SMB_DEV_T dev = (SMB_DEV_T)0;
6314 uint32 raw_unixmode = IVAL(pdata,84);
6318 if (total_data < 100) {
6319 return NT_STATUS_INVALID_PARAMETER;
6322 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6323 PERM_NEW_FILE, &unixmode);
6324 if (!NT_STATUS_IS_OK(status)) {
6328 #if defined(HAVE_MAKEDEV)
6329 dev = makedev(dev_major, dev_minor);
6332 switch (file_type) {
6333 #if defined(S_IFIFO)
6334 case UNIX_TYPE_FIFO:
6335 unixmode |= S_IFIFO;
6338 #if defined(S_IFSOCK)
6339 case UNIX_TYPE_SOCKET:
6340 unixmode |= S_IFSOCK;
6343 #if defined(S_IFCHR)
6344 case UNIX_TYPE_CHARDEV:
6345 unixmode |= S_IFCHR;
6348 #if defined(S_IFBLK)
6349 case UNIX_TYPE_BLKDEV:
6350 unixmode |= S_IFBLK;
6354 return NT_STATUS_INVALID_PARAMETER;
6357 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6358 "%.0f mode 0%o for file %s\n", (double)dev,
6359 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6361 /* Ok - do the mknod. */
6362 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6363 return map_nt_error_from_unix(errno);
6366 /* If any of the other "set" calls fail we
6367 * don't want to end up with a half-constructed mknod.
6370 if (lp_inherit_perms(SNUM(conn))) {
6372 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6374 return NT_STATUS_NO_MEMORY;
6376 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6378 TALLOC_FREE(parent);
6381 return NT_STATUS_OK;
6384 /****************************************************************************
6385 Deal with SMB_SET_FILE_UNIX_BASIC.
6386 ****************************************************************************/
6388 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6389 struct smb_request *req,
6393 const struct smb_filename *smb_fname)
6395 struct smb_file_time ft;
6396 uint32 raw_unixmode;
6399 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6400 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6401 NTSTATUS status = NT_STATUS_OK;
6402 bool delete_on_fail = False;
6403 enum perm_type ptype;
6404 files_struct *all_fsps = NULL;
6405 bool modify_mtime = true;
6407 SMB_STRUCT_STAT sbuf;
6411 if (total_data < 100) {
6412 return NT_STATUS_INVALID_PARAMETER;
6415 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6416 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6417 size=IVAL(pdata,0); /* first 8 Bytes are size */
6418 #ifdef LARGE_SMB_OFF_T
6419 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6420 #else /* LARGE_SMB_OFF_T */
6421 if (IVAL(pdata,4) != 0) {
6422 /* more than 32 bits? */
6423 return NT_STATUS_INVALID_PARAMETER;
6425 #endif /* LARGE_SMB_OFF_T */
6428 ft.atime = interpret_long_date(pdata+24); /* access_time */
6429 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6430 set_owner = (uid_t)IVAL(pdata,40);
6431 set_grp = (gid_t)IVAL(pdata,48);
6432 raw_unixmode = IVAL(pdata,84);
6434 if (VALID_STAT(smb_fname->st)) {
6435 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6436 ptype = PERM_EXISTING_DIR;
6438 ptype = PERM_EXISTING_FILE;
6441 ptype = PERM_NEW_FILE;
6444 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6446 if (!NT_STATUS_IS_OK(status)) {
6450 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6451 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6452 smb_fname_str_dbg(smb_fname), (double)size,
6453 (unsigned int)set_owner, (unsigned int)set_grp,
6454 (int)raw_unixmode));
6456 sbuf = smb_fname->st;
6458 if (!VALID_STAT(sbuf)) {
6459 struct smb_filename *smb_fname_tmp = NULL;
6461 * The only valid use of this is to create character and block
6462 * devices, and named pipes. This is deprecated (IMHO) and
6463 * a new info level should be used for mknod. JRA.
6466 status = smb_unix_mknod(conn,
6470 if (!NT_STATUS_IS_OK(status)) {
6474 status = copy_smb_filename(talloc_tos(), smb_fname,
6476 if (!NT_STATUS_IS_OK(status)) {
6480 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6481 status = map_nt_error_from_unix(errno);
6482 TALLOC_FREE(smb_fname_tmp);
6483 SMB_VFS_UNLINK(conn, smb_fname);
6487 sbuf = smb_fname_tmp->st;
6488 TALLOC_FREE(smb_fname_tmp);
6490 /* Ensure we don't try and change anything else. */
6491 raw_unixmode = SMB_MODE_NO_CHANGE;
6492 size = get_file_size_stat(&sbuf);
6493 ft.atime = sbuf.st_ex_atime;
6494 ft.mtime = sbuf.st_ex_mtime;
6496 * We continue here as we might want to change the
6499 delete_on_fail = True;
6503 /* Horrible backwards compatibility hack as an old server bug
6504 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6508 size = get_file_size_stat(&sbuf);
6513 * Deal with the UNIX specific mode set.
6516 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6517 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6518 "setting mode 0%o for file %s\n",
6519 (unsigned int)unixmode,
6520 smb_fname_str_dbg(smb_fname)));
6521 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6522 return map_nt_error_from_unix(errno);
6527 * Deal with the UNIX specific uid set.
6530 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6531 (sbuf.st_ex_uid != set_owner)) {
6534 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6535 "changing owner %u for path %s\n",
6536 (unsigned int)set_owner,
6537 smb_fname_str_dbg(smb_fname)));
6539 if (S_ISLNK(sbuf.st_ex_mode)) {
6540 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6541 set_owner, (gid_t)-1);
6543 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6544 set_owner, (gid_t)-1);
6548 status = map_nt_error_from_unix(errno);
6549 if (delete_on_fail) {
6550 SMB_VFS_UNLINK(conn, smb_fname);
6557 * Deal with the UNIX specific gid set.
6560 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6561 (sbuf.st_ex_gid != set_grp)) {
6562 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6563 "changing group %u for file %s\n",
6564 (unsigned int)set_owner,
6565 smb_fname_str_dbg(smb_fname)));
6566 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6568 status = map_nt_error_from_unix(errno);
6569 if (delete_on_fail) {
6570 SMB_VFS_UNLINK(conn, smb_fname);
6576 /* Deal with any size changes. */
6578 status = smb_set_file_size(conn, req,
6583 if (!NT_STATUS_IS_OK(status)) {
6587 /* Deal with any time changes. */
6588 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6589 /* No change, don't cancel anything. */
6593 id = vfs_file_id_from_sbuf(conn, &sbuf);
6594 for(all_fsps = file_find_di_first(id); all_fsps;
6595 all_fsps = file_find_di_next(all_fsps)) {
6597 * We're setting the time explicitly for UNIX.
6598 * Cancel any pending changes over all handles.
6600 all_fsps->update_write_time_on_close = false;
6601 TALLOC_FREE(all_fsps->update_write_time_event);
6605 * Override the "setting_write_time"
6606 * parameter here as it almost does what
6607 * we need. Just remember if we modified
6608 * mtime and send the notify ourselves.
6610 if (null_timespec(ft.mtime)) {
6611 modify_mtime = false;
6614 status = smb_set_file_time(conn,
6620 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6621 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6626 /****************************************************************************
6627 Deal with SMB_SET_FILE_UNIX_INFO2.
6628 ****************************************************************************/
6630 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6631 struct smb_request *req,
6635 const struct smb_filename *smb_fname)
6641 if (total_data < 116) {
6642 return NT_STATUS_INVALID_PARAMETER;
6645 /* Start by setting all the fields that are common between UNIX_BASIC
6648 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6650 if (!NT_STATUS_IS_OK(status)) {
6654 smb_fflags = IVAL(pdata, 108);
6655 smb_fmask = IVAL(pdata, 112);
6657 /* NB: We should only attempt to alter the file flags if the client
6658 * sends a non-zero mask.
6660 if (smb_fmask != 0) {
6661 int stat_fflags = 0;
6663 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6664 smb_fmask, &stat_fflags)) {
6665 /* Client asked to alter a flag we don't understand. */
6666 return NT_STATUS_INVALID_PARAMETER;
6669 if (fsp && fsp->fh->fd != -1) {
6670 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6671 return NT_STATUS_NOT_SUPPORTED;
6673 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6674 stat_fflags) != 0) {
6675 return map_nt_error_from_unix(errno);
6680 /* XXX: need to add support for changing the create_time here. You
6681 * can do this for paths on Darwin with setattrlist(2). The right way
6682 * to hook this up is probably by extending the VFS utimes interface.
6685 return NT_STATUS_OK;
6688 /****************************************************************************
6689 Create a directory with POSIX semantics.
6690 ****************************************************************************/
6692 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6693 struct smb_request *req,
6696 struct smb_filename *smb_fname,
6697 int *pdata_return_size)
6699 NTSTATUS status = NT_STATUS_OK;
6700 uint32 raw_unixmode = 0;
6701 uint32 mod_unixmode = 0;
6702 mode_t unixmode = (mode_t)0;
6703 files_struct *fsp = NULL;
6704 uint16 info_level_return = 0;
6706 char *pdata = *ppdata;
6708 if (total_data < 18) {
6709 return NT_STATUS_INVALID_PARAMETER;
6712 raw_unixmode = IVAL(pdata,8);
6713 /* Next 4 bytes are not yet defined. */
6715 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6716 PERM_NEW_DIR, &unixmode);
6717 if (!NT_STATUS_IS_OK(status)) {
6721 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6723 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6724 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6726 status = SMB_VFS_CREATE_FILE(
6729 0, /* root_dir_fid */
6730 smb_fname, /* fname */
6731 FILE_READ_ATTRIBUTES, /* access_mask */
6732 FILE_SHARE_NONE, /* share_access */
6733 FILE_CREATE, /* create_disposition*/
6734 FILE_DIRECTORY_FILE, /* create_options */
6735 mod_unixmode, /* file_attributes */
6736 0, /* oplock_request */
6737 0, /* allocation_size */
6743 if (NT_STATUS_IS_OK(status)) {
6744 close_file(req, fsp, NORMAL_CLOSE);
6747 info_level_return = SVAL(pdata,16);
6749 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6750 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6751 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6752 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6754 *pdata_return_size = 12;
6757 /* Realloc the data size */
6758 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6759 if (*ppdata == NULL) {
6760 *pdata_return_size = 0;
6761 return NT_STATUS_NO_MEMORY;
6765 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6766 SSVAL(pdata,2,0); /* No fnum. */
6767 SIVAL(pdata,4,info); /* Was directory created. */
6769 switch (info_level_return) {
6770 case SMB_QUERY_FILE_UNIX_BASIC:
6771 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6772 SSVAL(pdata,10,0); /* Padding. */
6773 store_file_unix_basic(conn, pdata + 12, fsp,
6776 case SMB_QUERY_FILE_UNIX_INFO2:
6777 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6778 SSVAL(pdata,10,0); /* Padding. */
6779 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6783 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6784 SSVAL(pdata,10,0); /* Padding. */
6791 /****************************************************************************
6792 Open/Create a file with POSIX semantics.
6793 ****************************************************************************/
6795 static NTSTATUS smb_posix_open(connection_struct *conn,
6796 struct smb_request *req,
6799 struct smb_filename *smb_fname,
6800 int *pdata_return_size)
6802 bool extended_oplock_granted = False;
6803 char *pdata = *ppdata;
6805 uint32 wire_open_mode = 0;
6806 uint32 raw_unixmode = 0;
6807 uint32 mod_unixmode = 0;
6808 uint32 create_disp = 0;
6809 uint32 access_mask = 0;
6810 uint32 create_options = 0;
6811 NTSTATUS status = NT_STATUS_OK;
6812 mode_t unixmode = (mode_t)0;
6813 files_struct *fsp = NULL;
6814 int oplock_request = 0;
6816 uint16 info_level_return = 0;
6818 if (total_data < 18) {
6819 return NT_STATUS_INVALID_PARAMETER;
6822 flags = IVAL(pdata,0);
6823 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6824 if (oplock_request) {
6825 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6828 wire_open_mode = IVAL(pdata,4);
6830 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6831 return smb_posix_mkdir(conn, req,
6838 switch (wire_open_mode & SMB_ACCMODE) {
6840 access_mask = FILE_READ_DATA;
6843 access_mask = FILE_WRITE_DATA;
6846 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6849 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6850 (unsigned int)wire_open_mode ));
6851 return NT_STATUS_INVALID_PARAMETER;
6854 wire_open_mode &= ~SMB_ACCMODE;
6856 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6857 create_disp = FILE_CREATE;
6858 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6859 create_disp = FILE_OVERWRITE_IF;
6860 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6861 create_disp = FILE_OPEN_IF;
6862 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6863 create_disp = FILE_OPEN;
6865 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6866 (unsigned int)wire_open_mode ));
6867 return NT_STATUS_INVALID_PARAMETER;
6870 raw_unixmode = IVAL(pdata,8);
6871 /* Next 4 bytes are not yet defined. */
6873 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6874 (VALID_STAT(smb_fname->st) ?
6875 PERM_EXISTING_FILE : PERM_NEW_FILE),
6878 if (!NT_STATUS_IS_OK(status)) {
6882 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6884 if (wire_open_mode & SMB_O_SYNC) {
6885 create_options |= FILE_WRITE_THROUGH;
6887 if (wire_open_mode & SMB_O_APPEND) {
6888 access_mask |= FILE_APPEND_DATA;
6890 if (wire_open_mode & SMB_O_DIRECT) {
6891 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6894 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6895 smb_fname_str_dbg(smb_fname),
6896 (unsigned int)wire_open_mode,
6897 (unsigned int)unixmode ));
6899 status = SMB_VFS_CREATE_FILE(
6902 0, /* root_dir_fid */
6903 smb_fname, /* fname */
6904 access_mask, /* access_mask */
6905 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6907 create_disp, /* create_disposition*/
6908 FILE_NON_DIRECTORY_FILE, /* create_options */
6909 mod_unixmode, /* file_attributes */
6910 oplock_request, /* oplock_request */
6911 0, /* allocation_size */
6917 if (!NT_STATUS_IS_OK(status)) {
6921 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6922 extended_oplock_granted = True;
6925 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6926 extended_oplock_granted = True;
6929 info_level_return = SVAL(pdata,16);
6931 /* Allocate the correct return size. */
6933 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6934 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6935 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6936 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6938 *pdata_return_size = 12;
6941 /* Realloc the data size */
6942 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6943 if (*ppdata == NULL) {
6944 close_file(req, fsp, ERROR_CLOSE);
6945 *pdata_return_size = 0;
6946 return NT_STATUS_NO_MEMORY;
6950 if (extended_oplock_granted) {
6951 if (flags & REQUEST_BATCH_OPLOCK) {
6952 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6954 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6956 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6957 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6959 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6962 SSVAL(pdata,2,fsp->fnum);
6963 SIVAL(pdata,4,info); /* Was file created etc. */
6965 switch (info_level_return) {
6966 case SMB_QUERY_FILE_UNIX_BASIC:
6967 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6968 SSVAL(pdata,10,0); /* padding. */
6969 store_file_unix_basic(conn, pdata + 12, fsp,
6972 case SMB_QUERY_FILE_UNIX_INFO2:
6973 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6974 SSVAL(pdata,10,0); /* padding. */
6975 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6979 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6980 SSVAL(pdata,10,0); /* padding. */
6983 return NT_STATUS_OK;
6986 /****************************************************************************
6987 Delete a file with POSIX semantics.
6988 ****************************************************************************/
6990 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6991 struct smb_request *req,
6994 struct smb_filename *smb_fname)
6996 NTSTATUS status = NT_STATUS_OK;
6997 files_struct *fsp = NULL;
7001 int create_options = 0;
7003 struct share_mode_lock *lck = NULL;
7005 if (total_data < 2) {
7006 return NT_STATUS_INVALID_PARAMETER;
7009 flags = SVAL(pdata,0);
7011 if (!VALID_STAT(smb_fname->st)) {
7012 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7015 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7016 !VALID_STAT_OF_DIR(smb_fname->st)) {
7017 return NT_STATUS_NOT_A_DIRECTORY;
7020 DEBUG(10,("smb_posix_unlink: %s %s\n",
7021 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7022 smb_fname_str_dbg(smb_fname)));
7024 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7025 create_options |= FILE_DIRECTORY_FILE;
7028 status = SMB_VFS_CREATE_FILE(
7031 0, /* root_dir_fid */
7032 smb_fname, /* fname */
7033 DELETE_ACCESS, /* access_mask */
7034 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7036 FILE_OPEN, /* create_disposition*/
7037 create_options, /* create_options */
7038 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7039 0, /* oplock_request */
7040 0, /* allocation_size */
7046 if (!NT_STATUS_IS_OK(status)) {
7051 * Don't lie to client. If we can't really delete due to
7052 * non-POSIX opens return SHARING_VIOLATION.
7055 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7058 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7059 "lock for file %s\n", fsp_str_dbg(fsp)));
7060 close_file(req, fsp, NORMAL_CLOSE);
7061 return NT_STATUS_INVALID_PARAMETER;
7065 * See if others still have the file open. If this is the case, then
7066 * don't delete. If all opens are POSIX delete we can set the delete
7067 * on close disposition.
7069 for (i=0; i<lck->num_share_modes; i++) {
7070 struct share_mode_entry *e = &lck->share_modes[i];
7071 if (is_valid_share_mode_entry(e)) {
7072 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7075 /* Fail with sharing violation. */
7076 close_file(req, fsp, NORMAL_CLOSE);
7078 return NT_STATUS_SHARING_VIOLATION;
7083 * Set the delete on close.
7085 status = smb_set_file_disposition_info(conn,
7091 if (!NT_STATUS_IS_OK(status)) {
7092 close_file(req, fsp, NORMAL_CLOSE);
7097 return close_file(req, fsp, NORMAL_CLOSE);
7100 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7101 struct smb_request *req,
7102 TALLOC_CTX *mem_ctx,
7103 uint16_t info_level,
7105 struct smb_filename *smb_fname,
7106 char **ppdata, int total_data,
7109 char *pdata = *ppdata;
7110 NTSTATUS status = NT_STATUS_OK;
7111 int data_return_size = 0;
7115 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7116 return NT_STATUS_INVALID_LEVEL;
7119 if (!CAN_WRITE(conn)) {
7120 /* Allow POSIX opens. The open path will deny
7121 * any non-readonly opens. */
7122 if (info_level != SMB_POSIX_PATH_OPEN) {
7123 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7127 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7128 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7129 fsp ? fsp->fnum : -1, info_level, total_data));
7131 switch (info_level) {
7133 case SMB_INFO_STANDARD:
7135 status = smb_set_info_standard(conn,
7143 case SMB_INFO_SET_EA:
7145 status = smb_info_set_ea(conn,
7153 case SMB_SET_FILE_BASIC_INFO:
7154 case SMB_FILE_BASIC_INFORMATION:
7156 status = smb_set_file_basic_info(conn,
7164 case SMB_FILE_ALLOCATION_INFORMATION:
7165 case SMB_SET_FILE_ALLOCATION_INFO:
7167 status = smb_set_file_allocation_info(conn, req,
7175 case SMB_FILE_END_OF_FILE_INFORMATION:
7176 case SMB_SET_FILE_END_OF_FILE_INFO:
7178 status = smb_set_file_end_of_file_info(conn, req,
7186 case SMB_FILE_DISPOSITION_INFORMATION:
7187 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7190 /* JRA - We used to just ignore this on a path ?
7191 * Shouldn't this be invalid level on a pathname
7194 if (tran_call != TRANSACT2_SETFILEINFO) {
7195 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7198 status = smb_set_file_disposition_info(conn,
7206 case SMB_FILE_POSITION_INFORMATION:
7208 status = smb_file_position_information(conn,
7215 /* From tridge Samba4 :
7216 * MODE_INFORMATION in setfileinfo (I have no
7217 * idea what "mode information" on a file is - it takes a value of 0,
7218 * 2, 4 or 6. What could it be?).
7221 case SMB_FILE_MODE_INFORMATION:
7223 status = smb_file_mode_information(conn,
7230 * CIFS UNIX extensions.
7233 case SMB_SET_FILE_UNIX_BASIC:
7235 status = smb_set_file_unix_basic(conn, req,
7243 case SMB_SET_FILE_UNIX_INFO2:
7245 status = smb_set_file_unix_info2(conn, req,
7253 case SMB_SET_FILE_UNIX_LINK:
7256 /* We must have a pathname for this. */
7257 return NT_STATUS_INVALID_LEVEL;
7259 status = smb_set_file_unix_link(conn, req, pdata,
7260 total_data, smb_fname);
7264 case SMB_SET_FILE_UNIX_HLINK:
7267 /* We must have a pathname for this. */
7268 return NT_STATUS_INVALID_LEVEL;
7270 status = smb_set_file_unix_hlink(conn, req,
7276 case SMB_FILE_RENAME_INFORMATION:
7278 status = smb_file_rename_information(conn, req,
7284 #if defined(HAVE_POSIX_ACLS)
7285 case SMB_SET_POSIX_ACL:
7287 status = smb_set_posix_acl(conn,
7296 case SMB_SET_POSIX_LOCK:
7299 return NT_STATUS_INVALID_LEVEL;
7301 status = smb_set_posix_lock(conn, req,
7302 pdata, total_data, fsp);
7306 case SMB_POSIX_PATH_OPEN:
7309 /* We must have a pathname for this. */
7310 return NT_STATUS_INVALID_LEVEL;
7313 status = smb_posix_open(conn, req,
7321 case SMB_POSIX_PATH_UNLINK:
7324 /* We must have a pathname for this. */
7325 return NT_STATUS_INVALID_LEVEL;
7328 status = smb_posix_unlink(conn, req,
7336 return NT_STATUS_INVALID_LEVEL;
7339 if (!NT_STATUS_IS_OK(status)) {
7343 *ret_data_size = data_return_size;
7344 return NT_STATUS_OK;
7347 /****************************************************************************
7348 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7349 ****************************************************************************/
7351 static void call_trans2setfilepathinfo(connection_struct *conn,
7352 struct smb_request *req,
7353 unsigned int tran_call,
7354 char **pparams, int total_params,
7355 char **ppdata, int total_data,
7356 unsigned int max_data_bytes)
7358 char *params = *pparams;
7359 char *pdata = *ppdata;
7361 struct smb_filename *smb_fname = NULL;
7362 files_struct *fsp = NULL;
7363 NTSTATUS status = NT_STATUS_OK;
7364 int data_return_size = 0;
7367 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7371 if (tran_call == TRANSACT2_SETFILEINFO) {
7372 if (total_params < 4) {
7373 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7377 fsp = file_fsp(req, SVAL(params,0));
7378 /* Basic check for non-null fsp. */
7379 if (!check_fsp_open(conn, req, fsp)) {
7382 info_level = SVAL(params,2);
7384 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7386 if (!NT_STATUS_IS_OK(status)) {
7387 reply_nterror(req, status);
7391 if(fsp->is_directory || fsp->fh->fd == -1) {
7393 * This is actually a SETFILEINFO on a directory
7394 * handle (returned from an NT SMB). NT5.0 seems
7395 * to do this call. JRA.
7397 if (INFO_LEVEL_IS_UNIX(info_level)) {
7398 /* Always do lstat for UNIX calls. */
7399 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7400 DEBUG(3,("call_trans2setfilepathinfo: "
7401 "SMB_VFS_LSTAT of %s failed "
7403 smb_fname_str_dbg(smb_fname),
7405 reply_nterror(req, map_nt_error_from_unix(errno));
7409 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7410 DEBUG(3,("call_trans2setfilepathinfo: "
7411 "fileinfo of %s failed (%s)\n",
7412 smb_fname_str_dbg(smb_fname),
7414 reply_nterror(req, map_nt_error_from_unix(errno));
7418 } else if (fsp->print_file) {
7420 * Doing a DELETE_ON_CLOSE should cancel a print job.
7422 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7423 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7425 DEBUG(3,("call_trans2setfilepathinfo: "
7426 "Cancelling print job (%s)\n",
7430 send_trans2_replies(conn, req, params, 2,
7435 reply_doserror(req, ERRDOS, ERRbadpath);
7440 * Original code - this is an open file.
7442 if (!check_fsp(conn, req, fsp)) {
7446 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7447 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7448 "of fnum %d failed (%s)\n", fsp->fnum,
7450 reply_nterror(req, map_nt_error_from_unix(errno));
7458 if (total_params < 7) {
7459 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7463 info_level = SVAL(params,0);
7464 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7465 total_params - 6, STR_TERMINATE,
7467 if (!NT_STATUS_IS_OK(status)) {
7468 reply_nterror(req, status);
7472 status = filename_convert(req, conn,
7473 req->flags2 & FLAGS2_DFS_PATHNAMES,
7478 if (!NT_STATUS_IS_OK(status)) {
7479 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7480 reply_botherror(req,
7481 NT_STATUS_PATH_NOT_COVERED,
7482 ERRSRV, ERRbadpath);
7485 reply_nterror(req, status);
7489 if (INFO_LEVEL_IS_UNIX(info_level)) {
7491 * For CIFS UNIX extensions the target name may not exist.
7494 /* Always do lstat for UNIX calls. */
7495 SMB_VFS_LSTAT(conn, smb_fname);
7497 } else if (!VALID_STAT(smb_fname->st) &&
7498 SMB_VFS_STAT(conn, smb_fname)) {
7499 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7501 smb_fname_str_dbg(smb_fname),
7503 reply_nterror(req, map_nt_error_from_unix(errno));
7508 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7509 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7510 fsp ? fsp->fnum : -1, info_level,total_data));
7512 /* Realloc the parameter size */
7513 *pparams = (char *)SMB_REALLOC(*pparams,2);
7514 if (*pparams == NULL) {
7515 reply_nterror(req, NT_STATUS_NO_MEMORY);
7522 status = smbd_do_setfilepathinfo(conn, req, req,
7528 if (!NT_STATUS_IS_OK(status)) {
7529 if (open_was_deferred(req->mid)) {
7530 /* We have re-scheduled this call. */
7533 if (blocking_lock_was_deferred(req->mid)) {
7534 /* We have re-scheduled this call. */
7537 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7538 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7539 ERRSRV, ERRbadpath);
7542 if (info_level == SMB_POSIX_PATH_OPEN) {
7543 reply_openerror(req, status);
7547 reply_nterror(req, status);
7551 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7557 /****************************************************************************
7558 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7559 ****************************************************************************/
7561 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7562 char **pparams, int total_params,
7563 char **ppdata, int total_data,
7564 unsigned int max_data_bytes)
7566 struct smb_filename *smb_dname = NULL;
7567 char *params = *pparams;
7568 char *pdata = *ppdata;
7569 char *directory = NULL;
7570 NTSTATUS status = NT_STATUS_OK;
7571 struct ea_list *ea_list = NULL;
7572 TALLOC_CTX *ctx = talloc_tos();
7574 if (!CAN_WRITE(conn)) {
7575 reply_doserror(req, ERRSRV, ERRaccess);
7579 if (total_params < 5) {
7580 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7584 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7585 total_params - 4, STR_TERMINATE,
7587 if (!NT_STATUS_IS_OK(status)) {
7588 reply_nterror(req, status);
7592 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7594 status = filename_convert(ctx,
7596 req->flags2 & FLAGS2_DFS_PATHNAMES,
7602 if (!NT_STATUS_IS_OK(status)) {
7603 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7604 reply_botherror(req,
7605 NT_STATUS_PATH_NOT_COVERED,
7606 ERRSRV, ERRbadpath);
7609 reply_nterror(req, status);
7613 /* Any data in this call is an EA list. */
7614 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7615 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7620 * OS/2 workplace shell seems to send SET_EA requests of "null"
7621 * length (4 bytes containing IVAL 4).
7622 * They seem to have no effect. Bug #3212. JRA.
7625 if (total_data != 4) {
7626 if (total_data < 10) {
7627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7631 if (IVAL(pdata,0) > total_data) {
7632 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7633 IVAL(pdata,0), (unsigned int)total_data));
7634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7638 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7641 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7645 /* If total_data == 4 Windows doesn't care what values
7646 * are placed in that field, it just ignores them.
7647 * The System i QNTC IBM SMB client puts bad values here,
7648 * so ignore them. */
7650 status = create_directory(conn, req, smb_dname);
7652 if (!NT_STATUS_IS_OK(status)) {
7653 reply_nterror(req, status);
7657 /* Try and set any given EA. */
7659 status = set_ea(conn, NULL, smb_dname, ea_list);
7660 if (!NT_STATUS_IS_OK(status)) {
7661 reply_nterror(req, status);
7666 /* Realloc the parameter and data sizes */
7667 *pparams = (char *)SMB_REALLOC(*pparams,2);
7668 if(*pparams == NULL) {
7669 reply_nterror(req, NT_STATUS_NO_MEMORY);
7676 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7679 TALLOC_FREE(smb_dname);
7683 /****************************************************************************
7684 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7685 We don't actually do this - we just send a null response.
7686 ****************************************************************************/
7688 static void call_trans2findnotifyfirst(connection_struct *conn,
7689 struct smb_request *req,
7690 char **pparams, int total_params,
7691 char **ppdata, int total_data,
7692 unsigned int max_data_bytes)
7694 char *params = *pparams;
7697 if (total_params < 6) {
7698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7702 info_level = SVAL(params,4);
7703 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7705 switch (info_level) {
7710 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7714 /* Realloc the parameter and data sizes */
7715 *pparams = (char *)SMB_REALLOC(*pparams,6);
7716 if (*pparams == NULL) {
7717 reply_nterror(req, NT_STATUS_NO_MEMORY);
7722 SSVAL(params,0,fnf_handle);
7723 SSVAL(params,2,0); /* No changes */
7724 SSVAL(params,4,0); /* No EA errors */
7731 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7736 /****************************************************************************
7737 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7738 changes). Currently this does nothing.
7739 ****************************************************************************/
7741 static void call_trans2findnotifynext(connection_struct *conn,
7742 struct smb_request *req,
7743 char **pparams, int total_params,
7744 char **ppdata, int total_data,
7745 unsigned int max_data_bytes)
7747 char *params = *pparams;
7749 DEBUG(3,("call_trans2findnotifynext\n"));
7751 /* Realloc the parameter and data sizes */
7752 *pparams = (char *)SMB_REALLOC(*pparams,4);
7753 if (*pparams == NULL) {
7754 reply_nterror(req, NT_STATUS_NO_MEMORY);
7759 SSVAL(params,0,0); /* No changes */
7760 SSVAL(params,2,0); /* No EA errors */
7762 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7767 /****************************************************************************
7768 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7769 ****************************************************************************/
7771 static void call_trans2getdfsreferral(connection_struct *conn,
7772 struct smb_request *req,
7773 char **pparams, int total_params,
7774 char **ppdata, int total_data,
7775 unsigned int max_data_bytes)
7777 char *params = *pparams;
7778 char *pathname = NULL;
7780 int max_referral_level;
7781 NTSTATUS status = NT_STATUS_OK;
7782 TALLOC_CTX *ctx = talloc_tos();
7784 DEBUG(10,("call_trans2getdfsreferral\n"));
7786 if (total_params < 3) {
7787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7791 max_referral_level = SVAL(params,0);
7793 if(!lp_host_msdfs()) {
7794 reply_doserror(req, ERRDOS, ERRbadfunc);
7798 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7799 total_params - 2, STR_TERMINATE);
7801 reply_nterror(req, NT_STATUS_NOT_FOUND);
7804 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7805 ppdata,&status)) < 0) {
7806 reply_nterror(req, status);
7810 SSVAL(req->inbuf, smb_flg2,
7811 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7812 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7817 #define LMCAT_SPL 0x53
7818 #define LMFUNC_GETJOBID 0x60
7820 /****************************************************************************
7821 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7822 ****************************************************************************/
7824 static void call_trans2ioctl(connection_struct *conn,
7825 struct smb_request *req,
7826 char **pparams, int total_params,
7827 char **ppdata, int total_data,
7828 unsigned int max_data_bytes)
7830 char *pdata = *ppdata;
7831 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7833 /* check for an invalid fid before proceeding */
7836 reply_doserror(req, ERRDOS, ERRbadfid);
7840 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7841 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7842 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7843 if (*ppdata == NULL) {
7844 reply_nterror(req, NT_STATUS_NO_MEMORY);
7849 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7850 CAN ACCEPT THIS IN UNICODE. JRA. */
7852 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7853 srvstr_push(pdata, req->flags2, pdata + 2,
7854 global_myname(), 15,
7855 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7856 srvstr_push(pdata, req->flags2, pdata+18,
7857 lp_servicename(SNUM(conn)), 13,
7858 STR_ASCII|STR_TERMINATE); /* Service name */
7859 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7864 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7865 reply_doserror(req, ERRSRV, ERRerror);
7868 /****************************************************************************
7869 Reply to a SMBfindclose (stop trans2 directory search).
7870 ****************************************************************************/
7872 void reply_findclose(struct smb_request *req)
7875 struct smbd_server_connection *sconn = smbd_server_conn;
7877 START_PROFILE(SMBfindclose);
7880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7881 END_PROFILE(SMBfindclose);
7885 dptr_num = SVALS(req->vwv+0, 0);
7887 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7889 dptr_close(sconn, &dptr_num);
7891 reply_outbuf(req, 0, 0);
7893 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7895 END_PROFILE(SMBfindclose);
7899 /****************************************************************************
7900 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7901 ****************************************************************************/
7903 void reply_findnclose(struct smb_request *req)
7907 START_PROFILE(SMBfindnclose);
7910 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7911 END_PROFILE(SMBfindnclose);
7915 dptr_num = SVAL(req->vwv+0, 0);
7917 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7919 /* We never give out valid handles for a
7920 findnotifyfirst - so any dptr_num is ok here.
7923 reply_outbuf(req, 0, 0);
7925 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7927 END_PROFILE(SMBfindnclose);
7931 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7932 struct trans_state *state)
7934 if (Protocol >= PROTOCOL_NT1) {
7935 req->flags2 |= 0x40; /* IS_LONG_NAME */
7936 SSVAL(req->inbuf,smb_flg2,req->flags2);
7939 if (conn->encrypt_level == Required && !req->encrypted) {
7940 if (state->call != TRANSACT2_QFSINFO &&
7941 state->call != TRANSACT2_SETFSINFO) {
7942 DEBUG(0,("handle_trans2: encryption required "
7944 (unsigned int)state->call));
7945 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7950 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7952 /* Now we must call the relevant TRANS2 function */
7953 switch(state->call) {
7954 case TRANSACT2_OPEN:
7956 START_PROFILE(Trans2_open);
7957 call_trans2open(conn, req,
7958 &state->param, state->total_param,
7959 &state->data, state->total_data,
7960 state->max_data_return);
7961 END_PROFILE(Trans2_open);
7965 case TRANSACT2_FINDFIRST:
7967 START_PROFILE(Trans2_findfirst);
7968 call_trans2findfirst(conn, req,
7969 &state->param, state->total_param,
7970 &state->data, state->total_data,
7971 state->max_data_return);
7972 END_PROFILE(Trans2_findfirst);
7976 case TRANSACT2_FINDNEXT:
7978 START_PROFILE(Trans2_findnext);
7979 call_trans2findnext(conn, req,
7980 &state->param, state->total_param,
7981 &state->data, state->total_data,
7982 state->max_data_return);
7983 END_PROFILE(Trans2_findnext);
7987 case TRANSACT2_QFSINFO:
7989 START_PROFILE(Trans2_qfsinfo);
7990 call_trans2qfsinfo(conn, req,
7991 &state->param, state->total_param,
7992 &state->data, state->total_data,
7993 state->max_data_return);
7994 END_PROFILE(Trans2_qfsinfo);
7998 case TRANSACT2_SETFSINFO:
8000 START_PROFILE(Trans2_setfsinfo);
8001 call_trans2setfsinfo(conn, req,
8002 &state->param, state->total_param,
8003 &state->data, state->total_data,
8004 state->max_data_return);
8005 END_PROFILE(Trans2_setfsinfo);
8009 case TRANSACT2_QPATHINFO:
8010 case TRANSACT2_QFILEINFO:
8012 START_PROFILE(Trans2_qpathinfo);
8013 call_trans2qfilepathinfo(conn, req, state->call,
8014 &state->param, state->total_param,
8015 &state->data, state->total_data,
8016 state->max_data_return);
8017 END_PROFILE(Trans2_qpathinfo);
8021 case TRANSACT2_SETPATHINFO:
8022 case TRANSACT2_SETFILEINFO:
8024 START_PROFILE(Trans2_setpathinfo);
8025 call_trans2setfilepathinfo(conn, req, state->call,
8026 &state->param, state->total_param,
8027 &state->data, state->total_data,
8028 state->max_data_return);
8029 END_PROFILE(Trans2_setpathinfo);
8033 case TRANSACT2_FINDNOTIFYFIRST:
8035 START_PROFILE(Trans2_findnotifyfirst);
8036 call_trans2findnotifyfirst(conn, req,
8037 &state->param, state->total_param,
8038 &state->data, state->total_data,
8039 state->max_data_return);
8040 END_PROFILE(Trans2_findnotifyfirst);
8044 case TRANSACT2_FINDNOTIFYNEXT:
8046 START_PROFILE(Trans2_findnotifynext);
8047 call_trans2findnotifynext(conn, req,
8048 &state->param, state->total_param,
8049 &state->data, state->total_data,
8050 state->max_data_return);
8051 END_PROFILE(Trans2_findnotifynext);
8055 case TRANSACT2_MKDIR:
8057 START_PROFILE(Trans2_mkdir);
8058 call_trans2mkdir(conn, req,
8059 &state->param, state->total_param,
8060 &state->data, state->total_data,
8061 state->max_data_return);
8062 END_PROFILE(Trans2_mkdir);
8066 case TRANSACT2_GET_DFS_REFERRAL:
8068 START_PROFILE(Trans2_get_dfs_referral);
8069 call_trans2getdfsreferral(conn, req,
8070 &state->param, state->total_param,
8071 &state->data, state->total_data,
8072 state->max_data_return);
8073 END_PROFILE(Trans2_get_dfs_referral);
8077 case TRANSACT2_IOCTL:
8079 START_PROFILE(Trans2_ioctl);
8080 call_trans2ioctl(conn, req,
8081 &state->param, state->total_param,
8082 &state->data, state->total_data,
8083 state->max_data_return);
8084 END_PROFILE(Trans2_ioctl);
8089 /* Error in request */
8090 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8091 reply_doserror(req, ERRSRV,ERRerror);
8095 /****************************************************************************
8096 Reply to a SMBtrans2.
8097 ****************************************************************************/
8099 void reply_trans2(struct smb_request *req)
8101 connection_struct *conn = req->conn;
8106 unsigned int tran_call;
8107 struct trans_state *state;
8110 START_PROFILE(SMBtrans2);
8112 if (req->wct < 14) {
8113 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8114 END_PROFILE(SMBtrans2);
8118 dsoff = SVAL(req->vwv+12, 0);
8119 dscnt = SVAL(req->vwv+11, 0);
8120 psoff = SVAL(req->vwv+10, 0);
8121 pscnt = SVAL(req->vwv+9, 0);
8122 tran_call = SVAL(req->vwv+14, 0);
8124 result = allow_new_trans(conn->pending_trans, req->mid);
8125 if (!NT_STATUS_IS_OK(result)) {
8126 DEBUG(2, ("Got invalid trans2 request: %s\n",
8127 nt_errstr(result)));
8128 reply_nterror(req, result);
8129 END_PROFILE(SMBtrans2);
8134 switch (tran_call) {
8135 /* List the allowed trans2 calls on IPC$ */
8136 case TRANSACT2_OPEN:
8137 case TRANSACT2_GET_DFS_REFERRAL:
8138 case TRANSACT2_QFILEINFO:
8139 case TRANSACT2_QFSINFO:
8140 case TRANSACT2_SETFSINFO:
8143 reply_doserror(req, ERRSRV, ERRaccess);
8144 END_PROFILE(SMBtrans2);
8149 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8150 DEBUG(0, ("talloc failed\n"));
8151 reply_nterror(req, NT_STATUS_NO_MEMORY);
8152 END_PROFILE(SMBtrans2);
8156 state->cmd = SMBtrans2;
8158 state->mid = req->mid;
8159 state->vuid = req->vuid;
8160 state->setup_count = SVAL(req->vwv+13, 0);
8161 state->setup = NULL;
8162 state->total_param = SVAL(req->vwv+0, 0);
8163 state->param = NULL;
8164 state->total_data = SVAL(req->vwv+1, 0);
8166 state->max_param_return = SVAL(req->vwv+2, 0);
8167 state->max_data_return = SVAL(req->vwv+3, 0);
8168 state->max_setup_return = SVAL(req->vwv+4, 0);
8169 state->close_on_completion = BITSETW(req->vwv+5, 0);
8170 state->one_way = BITSETW(req->vwv+5, 1);
8172 state->call = tran_call;
8174 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8175 is so as a sanity check */
8176 if (state->setup_count != 1) {
8178 * Need to have rc=0 for ioctl to get job id for OS/2.
8179 * Network printing will fail if function is not successful.
8180 * Similar function in reply.c will be used if protocol
8181 * is LANMAN1.0 instead of LM1.2X002.
8182 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8183 * outbuf doesn't have to be set(only job id is used).
8185 if ( (state->setup_count == 4)
8186 && (tran_call == TRANSACT2_IOCTL)
8187 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8188 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8189 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8191 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8192 DEBUG(2,("Transaction is %d\n",tran_call));
8194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8195 END_PROFILE(SMBtrans2);
8200 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8203 if (state->total_data) {
8205 if (trans_oob(state->total_data, 0, dscnt)
8206 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8210 /* Can't use talloc here, the core routines do realloc on the
8211 * params and data. */
8212 state->data = (char *)SMB_MALLOC(state->total_data);
8213 if (state->data == NULL) {
8214 DEBUG(0,("reply_trans2: data malloc fail for %u "
8215 "bytes !\n", (unsigned int)state->total_data));
8217 reply_nterror(req, NT_STATUS_NO_MEMORY);
8218 END_PROFILE(SMBtrans2);
8222 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8225 if (state->total_param) {
8227 if (trans_oob(state->total_param, 0, pscnt)
8228 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8232 /* Can't use talloc here, the core routines do realloc on the
8233 * params and data. */
8234 state->param = (char *)SMB_MALLOC(state->total_param);
8235 if (state->param == NULL) {
8236 DEBUG(0,("reply_trans: param malloc fail for %u "
8237 "bytes !\n", (unsigned int)state->total_param));
8238 SAFE_FREE(state->data);
8240 reply_nterror(req, NT_STATUS_NO_MEMORY);
8241 END_PROFILE(SMBtrans2);
8245 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8248 state->received_data = dscnt;
8249 state->received_param = pscnt;
8251 if ((state->received_param == state->total_param) &&
8252 (state->received_data == state->total_data)) {
8254 handle_trans2(conn, req, state);
8256 SAFE_FREE(state->data);
8257 SAFE_FREE(state->param);
8259 END_PROFILE(SMBtrans2);
8263 DLIST_ADD(conn->pending_trans, state);
8265 /* We need to send an interim response then receive the rest
8266 of the parameter/data bytes */
8267 reply_outbuf(req, 0, 0);
8268 show_msg((char *)req->outbuf);
8269 END_PROFILE(SMBtrans2);
8274 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8275 SAFE_FREE(state->data);
8276 SAFE_FREE(state->param);
8278 END_PROFILE(SMBtrans2);
8279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8283 /****************************************************************************
8284 Reply to a SMBtranss2
8285 ****************************************************************************/
8287 void reply_transs2(struct smb_request *req)
8289 connection_struct *conn = req->conn;
8290 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8291 struct trans_state *state;
8293 START_PROFILE(SMBtranss2);
8295 show_msg((char *)req->inbuf);
8298 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8299 END_PROFILE(SMBtranss2);
8303 for (state = conn->pending_trans; state != NULL;
8304 state = state->next) {
8305 if (state->mid == req->mid) {
8310 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8312 END_PROFILE(SMBtranss2);
8316 /* Revise state->total_param and state->total_data in case they have
8317 changed downwards */
8319 if (SVAL(req->vwv+0, 0) < state->total_param)
8320 state->total_param = SVAL(req->vwv+0, 0);
8321 if (SVAL(req->vwv+1, 0) < state->total_data)
8322 state->total_data = SVAL(req->vwv+1, 0);
8324 pcnt = SVAL(req->vwv+2, 0);
8325 poff = SVAL(req->vwv+3, 0);
8326 pdisp = SVAL(req->vwv+4, 0);
8328 dcnt = SVAL(req->vwv+5, 0);
8329 doff = SVAL(req->vwv+6, 0);
8330 ddisp = SVAL(req->vwv+7, 0);
8332 state->received_param += pcnt;
8333 state->received_data += dcnt;
8335 if ((state->received_data > state->total_data) ||
8336 (state->received_param > state->total_param))
8340 if (trans_oob(state->total_param, pdisp, pcnt)
8341 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8344 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8348 if (trans_oob(state->total_data, ddisp, dcnt)
8349 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8352 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8355 if ((state->received_param < state->total_param) ||
8356 (state->received_data < state->total_data)) {
8357 END_PROFILE(SMBtranss2);
8361 handle_trans2(conn, req, state);
8363 DLIST_REMOVE(conn->pending_trans, state);
8364 SAFE_FREE(state->data);
8365 SAFE_FREE(state->param);
8368 END_PROFILE(SMBtranss2);
8373 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8374 DLIST_REMOVE(conn->pending_trans, state);
8375 SAFE_FREE(state->data);
8376 SAFE_FREE(state->param);
8378 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8379 END_PROFILE(SMBtranss2);