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,
1467 uint64_t *last_entry_off)
1469 char *p, *q, *pdata = *ppdata;
1471 uint64_t file_size = 0;
1472 uint64_t allocation_size = 0;
1474 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1475 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1476 time_t c_date = (time_t)0;
1478 char *last_entry_ptr;
1480 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1484 *out_of_space = false;
1486 ZERO_STRUCT(mdate_ts);
1487 ZERO_STRUCT(adate_ts);
1488 ZERO_STRUCT(create_date_ts);
1489 ZERO_STRUCT(cdate_ts);
1491 if (!(mode & aDIR)) {
1492 file_size = get_file_size_stat(&smb_fname->st);
1494 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1496 mdate_ts = smb_fname->st.st_ex_mtime;
1497 adate_ts = smb_fname->st.st_ex_atime;
1498 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1499 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1501 if (lp_dos_filetime_resolution(SNUM(conn))) {
1502 dos_filetime_timespec(&create_date_ts);
1503 dos_filetime_timespec(&mdate_ts);
1504 dos_filetime_timespec(&adate_ts);
1505 dos_filetime_timespec(&cdate_ts);
1508 create_date = convert_timespec_to_time_t(create_date_ts);
1509 mdate = convert_timespec_to_time_t(mdate_ts);
1510 adate = convert_timespec_to_time_t(adate_ts);
1511 c_date = convert_timespec_to_time_t(cdate_ts);
1513 /* align the record */
1514 off = PTR_DIFF(pdata, base_data);
1515 pad = (off + (align-1)) & ~(align-1);
1518 /* initialize padding to 0 */
1519 memset(pdata, 0, pad);
1520 space_remaining -= pad;
1529 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1531 switch (info_level) {
1532 case SMB_FIND_INFO_STANDARD:
1533 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1534 if(requires_resume_key) {
1538 srv_put_dos_date2(p,0,create_date);
1539 srv_put_dos_date2(p,4,adate);
1540 srv_put_dos_date2(p,8,mdate);
1541 SIVAL(p,12,(uint32)file_size);
1542 SIVAL(p,16,(uint32)allocation_size);
1546 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1547 p += ucs2_align(base_data, p, 0);
1549 len = srvstr_push(base_data, flags2, p,
1550 fname, PTR_DIFF(end_data, p),
1552 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1554 SCVAL(nameptr, -1, len - 2);
1556 SCVAL(nameptr, -1, 0);
1560 SCVAL(nameptr, -1, len - 1);
1562 SCVAL(nameptr, -1, 0);
1568 case SMB_FIND_EA_SIZE:
1569 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1570 if (requires_resume_key) {
1574 srv_put_dos_date2(p,0,create_date);
1575 srv_put_dos_date2(p,4,adate);
1576 srv_put_dos_date2(p,8,mdate);
1577 SIVAL(p,12,(uint32)file_size);
1578 SIVAL(p,16,(uint32)allocation_size);
1581 unsigned int ea_size = estimate_ea_size(conn, NULL,
1582 smb_fname->base_name);
1583 SIVAL(p,22,ea_size); /* Extended attributes */
1587 len = srvstr_push(base_data, flags2,
1588 p, fname, PTR_DIFF(end_data, p),
1589 STR_TERMINATE | STR_NOALIGN);
1590 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1603 SCVAL(nameptr,0,len);
1605 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1608 case SMB_FIND_EA_LIST:
1610 struct ea_list *file_list = NULL;
1613 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1617 if (requires_resume_key) {
1621 srv_put_dos_date2(p,0,create_date);
1622 srv_put_dos_date2(p,4,adate);
1623 srv_put_dos_date2(p,8,mdate);
1624 SIVAL(p,12,(uint32)file_size);
1625 SIVAL(p,16,(uint32)allocation_size);
1627 p += 22; /* p now points to the EA area. */
1629 file_list = get_ea_list_from_file(ctx, conn, NULL,
1630 smb_fname->base_name,
1632 name_list = ea_list_union(name_list, file_list, &ea_len);
1634 /* We need to determine if this entry will fit in the space available. */
1635 /* Max string size is 255 bytes. */
1636 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1637 *out_of_space = true;
1638 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1639 return False; /* Not finished - just out of space */
1642 /* Push the ea_data followed by the name. */
1643 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1645 len = srvstr_push(base_data, flags2,
1646 p + 1, fname, PTR_DIFF(end_data, p+1),
1647 STR_TERMINATE | STR_NOALIGN);
1648 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1661 SCVAL(nameptr,0,len);
1663 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1667 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1668 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1669 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1671 SIVAL(p,0,reskey); p += 4;
1672 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1673 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1674 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1675 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1676 SOFF_T(p,0,file_size); p += 8;
1677 SOFF_T(p,0,allocation_size); p += 8;
1678 SIVAL(p,0,nt_extmode); p += 4;
1679 q = p; p += 4; /* q is placeholder for name length. */
1681 unsigned int ea_size = estimate_ea_size(conn, NULL,
1682 smb_fname->base_name);
1683 SIVAL(p,0,ea_size); /* Extended attributes */
1686 /* Clear the short name buffer. This is
1687 * IMPORTANT as not doing so will trigger
1688 * a Win2k client bug. JRA.
1690 if (!was_8_3 && check_mangled_names) {
1691 char mangled_name[13]; /* mangled 8.3 name. */
1692 if (!name_to_8_3(fname,mangled_name,True,
1694 /* Error - mangle failed ! */
1695 memset(mangled_name,'\0',12);
1697 mangled_name[12] = 0;
1698 len = srvstr_push(base_data, flags2,
1699 p+2, mangled_name, 24,
1700 STR_UPPER|STR_UNICODE);
1702 memset(p + 2 + len,'\0',24 - len);
1709 len = srvstr_push(base_data, flags2, p,
1710 fname, PTR_DIFF(end_data, p),
1711 STR_TERMINATE_ASCII);
1715 len = PTR_DIFF(p, pdata);
1716 pad = (len + (align-1)) & ~(align-1);
1718 * offset to the next entry, the caller
1719 * will overwrite it for the last entry
1720 * that's why we always include the padding
1724 * set padding to zero
1727 memset(p, 0, pad - len);
1734 case SMB_FIND_FILE_DIRECTORY_INFO:
1735 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1737 SIVAL(p,0,reskey); p += 4;
1738 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1739 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1740 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1741 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1742 SOFF_T(p,0,file_size); p += 8;
1743 SOFF_T(p,0,allocation_size); p += 8;
1744 SIVAL(p,0,nt_extmode); p += 4;
1745 len = srvstr_push(base_data, flags2,
1746 p + 4, fname, PTR_DIFF(end_data, p+4),
1747 STR_TERMINATE_ASCII);
1751 len = PTR_DIFF(p, pdata);
1752 pad = (len + (align-1)) & ~(align-1);
1754 * offset to the next entry, the caller
1755 * will overwrite it for the last entry
1756 * that's why we always include the padding
1760 * set padding to zero
1763 memset(p, 0, pad - len);
1770 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1771 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1773 SIVAL(p,0,reskey); p += 4;
1774 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1775 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1776 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1777 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1778 SOFF_T(p,0,file_size); p += 8;
1779 SOFF_T(p,0,allocation_size); p += 8;
1780 SIVAL(p,0,nt_extmode); p += 4;
1781 q = p; p += 4; /* q is placeholder for name length. */
1783 unsigned int ea_size = estimate_ea_size(conn, NULL,
1784 smb_fname->base_name);
1785 SIVAL(p,0,ea_size); /* Extended attributes */
1788 len = srvstr_push(base_data, flags2, p,
1789 fname, PTR_DIFF(end_data, p),
1790 STR_TERMINATE_ASCII);
1794 len = PTR_DIFF(p, pdata);
1795 pad = (len + (align-1)) & ~(align-1);
1797 * offset to the next entry, the caller
1798 * will overwrite it for the last entry
1799 * that's why we always include the padding
1803 * set padding to zero
1806 memset(p, 0, pad - len);
1813 case SMB_FIND_FILE_NAMES_INFO:
1814 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1816 SIVAL(p,0,reskey); p += 4;
1818 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1819 acl on a dir (tridge) */
1820 len = srvstr_push(base_data, flags2, p,
1821 fname, PTR_DIFF(end_data, p),
1822 STR_TERMINATE_ASCII);
1826 len = PTR_DIFF(p, pdata);
1827 pad = (len + (align-1)) & ~(align-1);
1829 * offset to the next entry, the caller
1830 * will overwrite it for the last entry
1831 * that's why we always include the padding
1835 * set padding to zero
1838 memset(p, 0, pad - len);
1845 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1846 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1848 SIVAL(p,0,reskey); p += 4;
1849 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1850 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1851 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1852 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1853 SOFF_T(p,0,file_size); p += 8;
1854 SOFF_T(p,0,allocation_size); p += 8;
1855 SIVAL(p,0,nt_extmode); p += 4;
1856 q = p; p += 4; /* q is placeholder for name length. */
1858 unsigned int ea_size = estimate_ea_size(conn, NULL,
1859 smb_fname->base_name);
1860 SIVAL(p,0,ea_size); /* Extended attributes */
1863 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1864 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1865 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1866 len = srvstr_push(base_data, flags2, p,
1867 fname, PTR_DIFF(end_data, p),
1868 STR_TERMINATE_ASCII);
1872 len = PTR_DIFF(p, pdata);
1873 pad = (len + (align-1)) & ~(align-1);
1875 * offset to the next entry, the caller
1876 * will overwrite it for the last entry
1877 * that's why we always include the padding
1881 * set padding to zero
1884 memset(p, 0, pad - len);
1891 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1892 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1893 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1895 SIVAL(p,0,reskey); p += 4;
1896 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1897 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1898 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1899 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1900 SOFF_T(p,0,file_size); p += 8;
1901 SOFF_T(p,0,allocation_size); p += 8;
1902 SIVAL(p,0,nt_extmode); p += 4;
1903 q = p; p += 4; /* q is placeholder for name length */
1905 unsigned int ea_size = estimate_ea_size(conn, NULL,
1906 smb_fname->base_name);
1907 SIVAL(p,0,ea_size); /* Extended attributes */
1910 /* Clear the short name buffer. This is
1911 * IMPORTANT as not doing so will trigger
1912 * a Win2k client bug. JRA.
1914 if (!was_8_3 && check_mangled_names) {
1915 char mangled_name[13]; /* mangled 8.3 name. */
1916 if (!name_to_8_3(fname,mangled_name,True,
1918 /* Error - mangle failed ! */
1919 memset(mangled_name,'\0',12);
1921 mangled_name[12] = 0;
1922 len = srvstr_push(base_data, flags2,
1923 p+2, mangled_name, 24,
1924 STR_UPPER|STR_UNICODE);
1927 memset(p + 2 + len,'\0',24 - len);
1934 SSVAL(p,0,0); p += 2; /* Reserved ? */
1935 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1936 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1937 len = srvstr_push(base_data, flags2, p,
1938 fname, PTR_DIFF(end_data, p),
1939 STR_TERMINATE_ASCII);
1943 len = PTR_DIFF(p, pdata);
1944 pad = (len + (align-1)) & ~(align-1);
1946 * offset to the next entry, the caller
1947 * will overwrite it for the last entry
1948 * that's why we always include the padding
1952 * set padding to zero
1955 memset(p, 0, pad - len);
1962 /* CIFS UNIX Extension. */
1964 case SMB_FIND_FILE_UNIX:
1965 case SMB_FIND_FILE_UNIX_INFO2:
1967 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1969 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1971 if (info_level == SMB_FIND_FILE_UNIX) {
1972 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1973 p = store_file_unix_basic(conn, p,
1974 NULL, &smb_fname->st);
1975 len = srvstr_push(base_data, flags2, p,
1976 fname, PTR_DIFF(end_data, p),
1979 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1980 p = store_file_unix_basic_info2(conn, p,
1981 NULL, &smb_fname->st);
1984 len = srvstr_push(base_data, flags2, p, fname,
1985 PTR_DIFF(end_data, p), 0);
1986 SIVAL(nameptr, 0, len);
1991 len = PTR_DIFF(p, pdata);
1992 pad = (len + (align-1)) & ~(align-1);
1994 * offset to the next entry, the caller
1995 * will overwrite it for the last entry
1996 * that's why we always include the padding
2000 * set padding to zero
2003 memset(p, 0, pad - len);
2008 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2016 if (PTR_DIFF(p,pdata) > space_remaining) {
2017 *out_of_space = true;
2018 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
2019 return false; /* Not finished - just out of space */
2022 /* Setup the last entry pointer, as an offset from base_data */
2023 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2024 /* Advance the data pointer to the next slot */
2030 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2031 connection_struct *conn,
2032 struct dptr_struct *dirptr,
2034 const char *path_mask,
2037 int requires_resume_key,
2045 int space_remaining,
2047 bool *got_exact_match,
2048 int *_last_entry_off,
2049 struct ea_list *name_list)
2052 const char *mask = NULL;
2053 long prev_dirpos = 0;
2056 struct smb_filename *smb_fname = NULL;
2057 struct smbd_dirptr_lanman2_state state;
2059 uint64_t last_entry_off = 0;
2063 state.info_level = info_level;
2064 state.check_mangled_names = lp_manglednames(conn->params);
2065 state.has_wild = dptr_has_wild(dirptr);
2066 state.got_exact_match = false;
2068 *out_of_space = false;
2069 *got_exact_match = false;
2071 p = strrchr_m(path_mask,'/');
2082 ok = smbd_dirptr_get_entry(ctx,
2088 smbd_dirptr_lanman2_match_fn,
2089 smbd_dirptr_lanman2_mode_fn,
2099 *got_exact_match = state.got_exact_match;
2101 ok = smbd_marshall_dir_entry(ctx,
2106 state.check_mangled_names,
2107 requires_resume_key,
2120 TALLOC_FREE(smb_fname);
2121 if (*out_of_space) {
2122 dptr_SeekDir(dirptr, prev_dirpos);
2129 *_last_entry_off = last_entry_off;
2133 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2134 connection_struct *conn,
2135 struct dptr_struct *dirptr,
2137 const char *path_mask,
2140 int requires_resume_key,
2146 int space_remaining,
2148 bool *got_exact_match,
2149 int *last_entry_off,
2150 struct ea_list *name_list)
2152 bool resume_key = false;
2153 const uint8_t align = 4;
2154 const bool do_pad = true;
2156 if (requires_resume_key) {
2160 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2161 path_mask, dirtype, info_level,
2162 resume_key, dont_descend, ask_sharemode,
2164 ppdata, base_data, end_data,
2166 out_of_space, got_exact_match,
2167 last_entry_off, name_list);
2170 /****************************************************************************
2171 Reply to a TRANS2_FINDFIRST.
2172 ****************************************************************************/
2174 static void call_trans2findfirst(connection_struct *conn,
2175 struct smb_request *req,
2176 char **pparams, int total_params,
2177 char **ppdata, int total_data,
2178 unsigned int max_data_bytes)
2180 /* We must be careful here that we don't return more than the
2181 allowed number of data bytes. If this means returning fewer than
2182 maxentries then so be it. We assume that the redirector has
2183 enough room for the fixed number of parameter bytes it has
2185 struct smb_filename *smb_dname = NULL;
2186 char *params = *pparams;
2187 char *pdata = *ppdata;
2191 uint16 findfirst_flags;
2192 bool close_after_first;
2194 bool requires_resume_key;
2196 char *directory = NULL;
2199 int last_entry_off=0;
2203 bool finished = False;
2204 bool dont_descend = False;
2205 bool out_of_space = False;
2206 int space_remaining;
2207 bool mask_contains_wcard = False;
2208 struct ea_list *ea_list = NULL;
2209 NTSTATUS ntstatus = NT_STATUS_OK;
2210 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2211 TALLOC_CTX *ctx = talloc_tos();
2212 struct dptr_struct *dirptr = NULL;
2213 struct smbd_server_connection *sconn = smbd_server_conn;
2215 if (total_params < 13) {
2216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2220 dirtype = SVAL(params,0);
2221 maxentries = SVAL(params,2);
2222 findfirst_flags = SVAL(params,4);
2223 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2224 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2225 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2226 info_level = SVAL(params,6);
2228 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2229 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2230 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2231 info_level, max_data_bytes));
2234 /* W2K3 seems to treat zero as 1. */
2238 switch (info_level) {
2239 case SMB_FIND_INFO_STANDARD:
2240 case SMB_FIND_EA_SIZE:
2241 case SMB_FIND_EA_LIST:
2242 case SMB_FIND_FILE_DIRECTORY_INFO:
2243 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2244 case SMB_FIND_FILE_NAMES_INFO:
2245 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2246 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2247 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2249 case SMB_FIND_FILE_UNIX:
2250 case SMB_FIND_FILE_UNIX_INFO2:
2251 /* Always use filesystem for UNIX mtime query. */
2252 ask_sharemode = false;
2253 if (!lp_unix_extensions()) {
2254 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2259 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2263 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2264 params+12, total_params - 12,
2265 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2266 if (!NT_STATUS_IS_OK(ntstatus)) {
2267 reply_nterror(req, ntstatus);
2271 ntstatus = filename_convert(ctx, conn,
2272 req->flags2 & FLAGS2_DFS_PATHNAMES,
2275 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2276 &mask_contains_wcard,
2278 if (!NT_STATUS_IS_OK(ntstatus)) {
2279 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2280 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2281 ERRSRV, ERRbadpath);
2284 reply_nterror(req, ntstatus);
2288 mask = smb_dname->original_lcomp;
2290 directory = smb_dname->base_name;
2292 p = strrchr_m(directory,'/');
2294 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2295 if((directory[0] == '.') && (directory[1] == '\0')) {
2296 mask = talloc_strdup(ctx,"*");
2298 reply_nterror(req, NT_STATUS_NO_MEMORY);
2301 mask_contains_wcard = True;
2303 directory = talloc_strdup(talloc_tos(), "./");
2305 reply_nterror(req, NT_STATUS_NO_MEMORY);
2312 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2314 if (info_level == SMB_FIND_EA_LIST) {
2317 if (total_data < 4) {
2318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2322 ea_size = IVAL(pdata,0);
2323 if (ea_size != total_data) {
2324 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2325 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2330 if (!lp_ea_support(SNUM(conn))) {
2331 reply_doserror(req, ERRDOS, ERReasnotsupported);
2335 /* Pull out the list of names. */
2336 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2343 *ppdata = (char *)SMB_REALLOC(
2344 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2345 if(*ppdata == NULL ) {
2346 reply_nterror(req, NT_STATUS_NO_MEMORY);
2350 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2352 /* Realloc the params space */
2353 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2354 if (*pparams == NULL) {
2355 reply_nterror(req, NT_STATUS_NO_MEMORY);
2360 /* Save the wildcard match and attribs we are using on this directory -
2361 needed as lanman2 assumes these are being saved between calls */
2363 ntstatus = dptr_create(conn,
2369 mask_contains_wcard,
2373 if (!NT_STATUS_IS_OK(ntstatus)) {
2374 reply_nterror(req, ntstatus);
2378 dptr_num = dptr_dnum(dirptr);
2379 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2381 /* Initialize per TRANS2_FIND_FIRST operation data */
2382 dptr_init_search_op(dirptr);
2384 /* We don't need to check for VOL here as this is returned by
2385 a different TRANS2 call. */
2387 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2388 directory,lp_dontdescend(SNUM(conn))));
2389 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2390 dont_descend = True;
2393 space_remaining = max_data_bytes;
2394 out_of_space = False;
2396 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2397 bool got_exact_match = False;
2399 /* this is a heuristic to avoid seeking the dirptr except when
2400 absolutely necessary. It allows for a filename of about 40 chars */
2401 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2402 out_of_space = True;
2405 finished = !get_lanman2_dir_entry(ctx,
2409 mask,dirtype,info_level,
2410 requires_resume_key,dont_descend,
2413 space_remaining, &out_of_space,
2415 &last_entry_off, ea_list);
2418 if (finished && out_of_space)
2421 if (!finished && !out_of_space)
2425 * As an optimisation if we know we aren't looking
2426 * for a wildcard name (ie. the name matches the wildcard exactly)
2427 * then we can finish on any (first) match.
2428 * This speeds up large directory searches. JRA.
2434 /* Ensure space_remaining never goes -ve. */
2435 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2436 space_remaining = 0;
2437 out_of_space = true;
2439 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2443 /* Check if we can close the dirptr */
2444 if(close_after_first || (finished && close_if_end)) {
2445 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2446 dptr_close(sconn, &dptr_num);
2450 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2451 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2452 * the protocol level is less than NT1. Tested with smbclient. JRA.
2453 * This should fix the OS/2 client bug #2335.
2456 if(numentries == 0) {
2457 dptr_close(sconn, &dptr_num);
2458 if (Protocol < PROTOCOL_NT1) {
2459 reply_doserror(req, ERRDOS, ERRnofiles);
2462 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2463 ERRDOS, ERRbadfile);
2468 /* At this point pdata points to numentries directory entries. */
2470 /* Set up the return parameter block */
2471 SSVAL(params,0,dptr_num);
2472 SSVAL(params,2,numentries);
2473 SSVAL(params,4,finished);
2474 SSVAL(params,6,0); /* Never an EA error */
2475 SSVAL(params,8,last_entry_off);
2477 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2480 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2481 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2483 reply_nterror(req, NT_STATUS_NO_MEMORY);
2487 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2488 smb_fn_name(req->cmd),
2489 mask, directory, dirtype, numentries ) );
2492 * Force a name mangle here to ensure that the
2493 * mask as an 8.3 name is top of the mangled cache.
2494 * The reasons for this are subtle. Don't remove
2495 * this code unless you know what you are doing
2496 * (see PR#13758). JRA.
2499 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2500 char mangled_name[13];
2501 name_to_8_3(mask, mangled_name, True, conn->params);
2504 TALLOC_FREE(smb_dname);
2508 /****************************************************************************
2509 Reply to a TRANS2_FINDNEXT.
2510 ****************************************************************************/
2512 static void call_trans2findnext(connection_struct *conn,
2513 struct smb_request *req,
2514 char **pparams, int total_params,
2515 char **ppdata, int total_data,
2516 unsigned int max_data_bytes)
2518 /* We must be careful here that we don't return more than the
2519 allowed number of data bytes. If this means returning fewer than
2520 maxentries then so be it. We assume that the redirector has
2521 enough room for the fixed number of parameter bytes it has
2523 char *params = *pparams;
2524 char *pdata = *ppdata;
2530 uint16 findnext_flags;
2531 bool close_after_request;
2533 bool requires_resume_key;
2535 bool mask_contains_wcard = False;
2536 char *resume_name = NULL;
2537 const char *mask = NULL;
2538 const char *directory = NULL;
2542 int i, last_entry_off=0;
2543 bool finished = False;
2544 bool dont_descend = False;
2545 bool out_of_space = False;
2546 int space_remaining;
2547 struct ea_list *ea_list = NULL;
2548 NTSTATUS ntstatus = NT_STATUS_OK;
2549 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2550 TALLOC_CTX *ctx = talloc_tos();
2551 struct dptr_struct *dirptr;
2552 struct smbd_server_connection *sconn = smbd_server_conn;
2554 if (total_params < 13) {
2555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2559 dptr_num = SVAL(params,0);
2560 maxentries = SVAL(params,2);
2561 info_level = SVAL(params,4);
2562 resume_key = IVAL(params,6);
2563 findnext_flags = SVAL(params,10);
2564 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2565 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2566 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2567 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2569 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2571 total_params - 12, STR_TERMINATE, &ntstatus,
2572 &mask_contains_wcard);
2573 if (!NT_STATUS_IS_OK(ntstatus)) {
2574 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2575 complain (it thinks we're asking for the directory above the shared
2576 path or an invalid name). Catch this as the resume name is only compared, never used in
2577 a file access. JRA. */
2578 srvstr_pull_talloc(ctx, params, req->flags2,
2579 &resume_name, params+12,
2583 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2584 reply_nterror(req, ntstatus);
2589 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2590 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2591 resume_key = %d resume name = %s continue=%d level = %d\n",
2592 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2593 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2596 /* W2K3 seems to treat zero as 1. */
2600 switch (info_level) {
2601 case SMB_FIND_INFO_STANDARD:
2602 case SMB_FIND_EA_SIZE:
2603 case SMB_FIND_EA_LIST:
2604 case SMB_FIND_FILE_DIRECTORY_INFO:
2605 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2606 case SMB_FIND_FILE_NAMES_INFO:
2607 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2608 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2609 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2611 case SMB_FIND_FILE_UNIX:
2612 case SMB_FIND_FILE_UNIX_INFO2:
2613 /* Always use filesystem for UNIX mtime query. */
2614 ask_sharemode = false;
2615 if (!lp_unix_extensions()) {
2616 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2621 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2625 if (info_level == SMB_FIND_EA_LIST) {
2628 if (total_data < 4) {
2629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2633 ea_size = IVAL(pdata,0);
2634 if (ea_size != total_data) {
2635 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2636 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2641 if (!lp_ea_support(SNUM(conn))) {
2642 reply_doserror(req, ERRDOS, ERReasnotsupported);
2646 /* Pull out the list of names. */
2647 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2654 *ppdata = (char *)SMB_REALLOC(
2655 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2656 if(*ppdata == NULL) {
2657 reply_nterror(req, NT_STATUS_NO_MEMORY);
2662 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2664 /* Realloc the params space */
2665 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2666 if(*pparams == NULL ) {
2667 reply_nterror(req, NT_STATUS_NO_MEMORY);
2673 /* Check that the dptr is valid */
2674 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2675 reply_doserror(req, ERRDOS, ERRnofiles);
2679 directory = dptr_path(sconn, dptr_num);
2681 /* Get the wildcard mask from the dptr */
2682 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2683 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2684 reply_doserror(req, ERRDOS, ERRnofiles);
2690 /* Get the attr mask from the dptr */
2691 dirtype = dptr_attr(sconn, dptr_num);
2693 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2694 dptr_num, mask, dirtype,
2696 dptr_TellDir(dirptr)));
2698 /* Initialize per TRANS2_FIND_NEXT operation data */
2699 dptr_init_search_op(dirptr);
2701 /* We don't need to check for VOL here as this is returned by
2702 a different TRANS2 call. */
2704 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2705 directory,lp_dontdescend(SNUM(conn))));
2706 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2707 dont_descend = True;
2710 space_remaining = max_data_bytes;
2711 out_of_space = False;
2714 * Seek to the correct position. We no longer use the resume key but
2715 * depend on the last file name instead.
2718 if(*resume_name && !continue_bit) {
2721 long current_pos = 0;
2723 * Remember, name_to_8_3 is called by
2724 * get_lanman2_dir_entry(), so the resume name
2725 * could be mangled. Ensure we check the unmangled name.
2728 if (mangle_is_mangled(resume_name, conn->params)) {
2729 char *new_resume_name = NULL;
2730 mangle_lookup_name_from_8_3(ctx,
2734 if (new_resume_name) {
2735 resume_name = new_resume_name;
2740 * Fix for NT redirector problem triggered by resume key indexes
2741 * changing between directory scans. We now return a resume key of 0
2742 * and instead look for the filename to continue from (also given
2743 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2744 * findfirst/findnext (as is usual) then the directory pointer
2745 * should already be at the correct place.
2748 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2749 } /* end if resume_name && !continue_bit */
2751 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2752 bool got_exact_match = False;
2754 /* this is a heuristic to avoid seeking the dirptr except when
2755 absolutely necessary. It allows for a filename of about 40 chars */
2756 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2757 out_of_space = True;
2760 finished = !get_lanman2_dir_entry(ctx,
2764 mask,dirtype,info_level,
2765 requires_resume_key,dont_descend,
2768 space_remaining, &out_of_space,
2770 &last_entry_off, ea_list);
2773 if (finished && out_of_space)
2776 if (!finished && !out_of_space)
2780 * As an optimisation if we know we aren't looking
2781 * for a wildcard name (ie. the name matches the wildcard exactly)
2782 * then we can finish on any (first) match.
2783 * This speeds up large directory searches. JRA.
2789 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2792 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2793 smb_fn_name(req->cmd),
2794 mask, directory, dirtype, numentries ) );
2796 /* Check if we can close the dirptr */
2797 if(close_after_request || (finished && close_if_end)) {
2798 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2799 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2802 /* Set up the return parameter block */
2803 SSVAL(params,0,numentries);
2804 SSVAL(params,2,finished);
2805 SSVAL(params,4,0); /* Never an EA error */
2806 SSVAL(params,6,last_entry_off);
2808 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2814 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2816 E_md4hash(lp_servicename(SNUM(conn)),objid);
2820 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2822 SMB_ASSERT(extended_info != NULL);
2824 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2825 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2826 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2827 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2828 #ifdef SAMBA_VERSION_REVISION
2829 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2831 extended_info->samba_subversion = 0;
2832 #ifdef SAMBA_VERSION_RC_RELEASE
2833 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2835 #ifdef SAMBA_VERSION_PRE_RELEASE
2836 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2839 #ifdef SAMBA_VERSION_VENDOR_PATCH
2840 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2842 extended_info->samba_gitcommitdate = 0;
2843 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2844 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2847 memset(extended_info->samba_version_string, 0,
2848 sizeof(extended_info->samba_version_string));
2850 snprintf (extended_info->samba_version_string,
2851 sizeof(extended_info->samba_version_string),
2852 "%s", samba_version_string());
2855 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2856 TALLOC_CTX *mem_ctx,
2857 uint16_t info_level,
2859 unsigned int max_data_bytes,
2863 char *pdata, *end_data;
2864 int data_len = 0, len;
2865 const char *vname = volume_label(SNUM(conn));
2866 int snum = SNUM(conn);
2867 char *fstype = lp_fstype(SNUM(conn));
2868 uint32 additional_flags = 0;
2869 struct smb_filename *smb_fname_dot = NULL;
2874 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2875 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2876 "info level (0x%x) on IPC$.\n",
2877 (unsigned int)info_level));
2878 return NT_STATUS_ACCESS_DENIED;
2882 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2884 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2886 if (!NT_STATUS_IS_OK(status)) {
2890 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2891 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2892 TALLOC_FREE(smb_fname_dot);
2893 return map_nt_error_from_unix(errno);
2896 st = smb_fname_dot->st;
2897 TALLOC_FREE(smb_fname_dot);
2899 *ppdata = (char *)SMB_REALLOC(
2900 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2901 if (*ppdata == NULL) {
2902 return NT_STATUS_NO_MEMORY;
2906 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2907 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2909 switch (info_level) {
2910 case SMB_INFO_ALLOCATION:
2912 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2914 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2915 return map_nt_error_from_unix(errno);
2918 block_size = lp_block_size(snum);
2919 if (bsize < block_size) {
2920 uint64_t factor = block_size/bsize;
2925 if (bsize > block_size) {
2926 uint64_t factor = bsize/block_size;
2931 bytes_per_sector = 512;
2932 sectors_per_unit = bsize/bytes_per_sector;
2934 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2935 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2936 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2938 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2939 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2940 SIVAL(pdata,l1_cUnit,dsize);
2941 SIVAL(pdata,l1_cUnitAvail,dfree);
2942 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2946 case SMB_INFO_VOLUME:
2947 /* Return volume name */
2949 * Add volume serial number - hash of a combination of
2950 * the called hostname and the service name.
2952 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2954 * Win2k3 and previous mess this up by sending a name length
2955 * one byte short. I believe only older clients (OS/2 Win9x) use
2956 * this call so try fixing this by adding a terminating null to
2957 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2961 pdata+l2_vol_szVolLabel, vname,
2962 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2963 STR_NOALIGN|STR_TERMINATE);
2964 SCVAL(pdata,l2_vol_cch,len);
2965 data_len = l2_vol_szVolLabel + len;
2966 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2967 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2971 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2972 case SMB_FS_ATTRIBUTE_INFORMATION:
2974 additional_flags = 0;
2975 #if defined(HAVE_SYS_QUOTAS)
2976 additional_flags |= FILE_VOLUME_QUOTAS;
2979 if(lp_nt_acl_support(SNUM(conn))) {
2980 additional_flags |= FILE_PERSISTENT_ACLS;
2983 /* Capabilities are filled in at connection time through STATVFS call */
2984 additional_flags |= conn->fs_capabilities;
2985 additional_flags |= lp_parm_int(conn->params->service,
2986 "share", "fake_fscaps",
2989 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2990 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2991 additional_flags); /* FS ATTRIBUTES */
2993 SIVAL(pdata,4,255); /* Max filename component length */
2994 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2995 and will think we can't do long filenames */
2996 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2997 PTR_DIFF(end_data, pdata+12),
3000 data_len = 12 + len;
3003 case SMB_QUERY_FS_LABEL_INFO:
3004 case SMB_FS_LABEL_INFORMATION:
3005 len = srvstr_push(pdata, flags2, pdata+4, vname,
3006 PTR_DIFF(end_data, pdata+4), 0);
3011 case SMB_QUERY_FS_VOLUME_INFO:
3012 case SMB_FS_VOLUME_INFORMATION:
3015 * Add volume serial number - hash of a combination of
3016 * the called hostname and the service name.
3018 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3019 (str_checksum(get_local_machine_name())<<16));
3021 /* Max label len is 32 characters. */
3022 len = srvstr_push(pdata, flags2, pdata+18, vname,
3023 PTR_DIFF(end_data, pdata+18),
3025 SIVAL(pdata,12,len);
3028 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3029 (int)strlen(vname),vname, lp_servicename(snum)));
3032 case SMB_QUERY_FS_SIZE_INFO:
3033 case SMB_FS_SIZE_INFORMATION:
3035 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3037 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3038 return map_nt_error_from_unix(errno);
3040 block_size = lp_block_size(snum);
3041 if (bsize < block_size) {
3042 uint64_t factor = block_size/bsize;
3047 if (bsize > block_size) {
3048 uint64_t factor = bsize/block_size;
3053 bytes_per_sector = 512;
3054 sectors_per_unit = bsize/bytes_per_sector;
3055 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3056 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3057 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3058 SBIG_UINT(pdata,0,dsize);
3059 SBIG_UINT(pdata,8,dfree);
3060 SIVAL(pdata,16,sectors_per_unit);
3061 SIVAL(pdata,20,bytes_per_sector);
3065 case SMB_FS_FULL_SIZE_INFORMATION:
3067 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3069 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3070 return map_nt_error_from_unix(errno);
3072 block_size = lp_block_size(snum);
3073 if (bsize < block_size) {
3074 uint64_t factor = block_size/bsize;
3079 if (bsize > block_size) {
3080 uint64_t factor = bsize/block_size;
3085 bytes_per_sector = 512;
3086 sectors_per_unit = bsize/bytes_per_sector;
3087 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3088 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3089 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3090 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3091 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3092 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3093 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3094 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3098 case SMB_QUERY_FS_DEVICE_INFO:
3099 case SMB_FS_DEVICE_INFORMATION:
3101 SIVAL(pdata,0,0); /* dev type */
3102 SIVAL(pdata,4,0); /* characteristics */
3105 #ifdef HAVE_SYS_QUOTAS
3106 case SMB_FS_QUOTA_INFORMATION:
3108 * what we have to send --metze:
3110 * Unknown1: 24 NULL bytes
3111 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3112 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3113 * Quota Flags: 2 byte :
3114 * Unknown3: 6 NULL bytes
3118 * details for Quota Flags:
3120 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3121 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3122 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3123 * 0x0001 Enable Quotas: enable quota for this fs
3127 /* we need to fake up a fsp here,
3128 * because its not send in this call
3131 SMB_NTQUOTA_STRUCT quotas;
3134 ZERO_STRUCT(quotas);
3140 if (conn->server_info->utok.uid != sec_initial_uid()) {
3141 DEBUG(0,("set_user_quota: access_denied "
3142 "service [%s] user [%s]\n",
3143 lp_servicename(SNUM(conn)),
3144 conn->server_info->unix_name));
3145 return NT_STATUS_ACCESS_DENIED;
3148 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3149 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3150 return map_nt_error_from_unix(errno);
3155 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3156 lp_servicename(SNUM(conn))));
3158 /* Unknown1 24 NULL bytes*/
3159 SBIG_UINT(pdata,0,(uint64_t)0);
3160 SBIG_UINT(pdata,8,(uint64_t)0);
3161 SBIG_UINT(pdata,16,(uint64_t)0);
3163 /* Default Soft Quota 8 bytes */
3164 SBIG_UINT(pdata,24,quotas.softlim);
3166 /* Default Hard Quota 8 bytes */
3167 SBIG_UINT(pdata,32,quotas.hardlim);
3169 /* Quota flag 2 bytes */
3170 SSVAL(pdata,40,quotas.qflags);
3172 /* Unknown3 6 NULL bytes */
3178 #endif /* HAVE_SYS_QUOTAS */
3179 case SMB_FS_OBJECTID_INFORMATION:
3181 unsigned char objid[16];
3182 struct smb_extended_info extended_info;
3183 memcpy(pdata,create_volume_objectid(conn, objid),16);
3184 samba_extended_info_version (&extended_info);
3185 SIVAL(pdata,16,extended_info.samba_magic);
3186 SIVAL(pdata,20,extended_info.samba_version);
3187 SIVAL(pdata,24,extended_info.samba_subversion);
3188 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3189 memcpy(pdata+36,extended_info.samba_version_string,28);
3195 * Query the version and capabilities of the CIFS UNIX extensions
3199 case SMB_QUERY_CIFS_UNIX_INFO:
3201 bool large_write = lp_min_receive_file_size() &&
3202 !srv_is_signing_active(smbd_server_conn);
3203 bool large_read = !srv_is_signing_active(smbd_server_conn);
3204 int encrypt_caps = 0;
3206 if (!lp_unix_extensions()) {
3207 return NT_STATUS_INVALID_LEVEL;
3210 switch (conn->encrypt_level) {
3216 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3219 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3220 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3221 large_write = false;
3227 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3228 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3230 /* We have POSIX ACLs, pathname, encryption,
3231 * large read/write, and locking capability. */
3233 SBIG_UINT(pdata,4,((uint64_t)(
3234 CIFS_UNIX_POSIX_ACLS_CAP|
3235 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3236 CIFS_UNIX_FCNTL_LOCKS_CAP|
3237 CIFS_UNIX_EXTATTR_CAP|
3238 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3240 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3242 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3246 case SMB_QUERY_POSIX_FS_INFO:
3249 vfs_statvfs_struct svfs;
3251 if (!lp_unix_extensions()) {
3252 return NT_STATUS_INVALID_LEVEL;
3255 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3259 SIVAL(pdata,0,svfs.OptimalTransferSize);
3260 SIVAL(pdata,4,svfs.BlockSize);
3261 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3262 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3263 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3264 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3265 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3266 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3267 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3269 } else if (rc == EOPNOTSUPP) {
3270 return NT_STATUS_INVALID_LEVEL;
3271 #endif /* EOPNOTSUPP */
3273 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3274 return NT_STATUS_DOS(ERRSRV, ERRerror);
3279 case SMB_QUERY_POSIX_WHOAMI:
3285 if (!lp_unix_extensions()) {
3286 return NT_STATUS_INVALID_LEVEL;
3289 if (max_data_bytes < 40) {
3290 return NT_STATUS_BUFFER_TOO_SMALL;
3293 /* We ARE guest if global_sid_Builtin_Guests is
3294 * in our list of SIDs.
3296 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3297 conn->server_info->ptok)) {
3298 flags |= SMB_WHOAMI_GUEST;
3301 /* We are NOT guest if global_sid_Authenticated_Users
3302 * is in our list of SIDs.
3304 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3305 conn->server_info->ptok)) {
3306 flags &= ~SMB_WHOAMI_GUEST;
3309 /* NOTE: 8 bytes for UID/GID, irrespective of native
3310 * platform size. This matches
3311 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3313 data_len = 4 /* flags */
3320 + 4 /* pad/reserved */
3321 + (conn->server_info->utok.ngroups * 8)
3323 + (conn->server_info->ptok->num_sids *
3327 SIVAL(pdata, 0, flags);
3328 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3330 (uint64_t)conn->server_info->utok.uid);
3331 SBIG_UINT(pdata, 16,
3332 (uint64_t)conn->server_info->utok.gid);
3335 if (data_len >= max_data_bytes) {
3336 /* Potential overflow, skip the GIDs and SIDs. */
3338 SIVAL(pdata, 24, 0); /* num_groups */
3339 SIVAL(pdata, 28, 0); /* num_sids */
3340 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3341 SIVAL(pdata, 36, 0); /* reserved */
3347 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3348 SIVAL(pdata, 28, conn->server_info->num_sids);
3350 /* We walk the SID list twice, but this call is fairly
3351 * infrequent, and I don't expect that it's performance
3352 * sensitive -- jpeach
3354 for (i = 0, sid_bytes = 0;
3355 i < conn->server_info->ptok->num_sids; ++i) {
3356 sid_bytes += ndr_size_dom_sid(
3357 &conn->server_info->ptok->user_sids[i],
3362 /* SID list byte count */
3363 SIVAL(pdata, 32, sid_bytes);
3365 /* 4 bytes pad/reserved - must be zero */
3366 SIVAL(pdata, 36, 0);
3370 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3371 SBIG_UINT(pdata, data_len,
3372 (uint64_t)conn->server_info->utok.groups[i]);
3378 i < conn->server_info->ptok->num_sids; ++i) {
3379 int sid_len = ndr_size_dom_sid(
3380 &conn->server_info->ptok->user_sids[i],
3384 sid_linearize(pdata + data_len, sid_len,
3385 &conn->server_info->ptok->user_sids[i]);
3386 data_len += sid_len;
3392 case SMB_MAC_QUERY_FS_INFO:
3394 * Thursby MAC extension... ONLY on NTFS filesystems
3395 * once we do streams then we don't need this
3397 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3399 SIVAL(pdata,84,0x100); /* Don't support mac... */
3404 return NT_STATUS_INVALID_LEVEL;
3407 *ret_data_len = data_len;
3408 return NT_STATUS_OK;
3411 /****************************************************************************
3412 Reply to a TRANS2_QFSINFO (query filesystem info).
3413 ****************************************************************************/
3415 static void call_trans2qfsinfo(connection_struct *conn,
3416 struct smb_request *req,
3417 char **pparams, int total_params,
3418 char **ppdata, int total_data,
3419 unsigned int max_data_bytes)
3421 char *params = *pparams;
3422 uint16_t info_level;
3426 if (total_params < 2) {
3427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3431 info_level = SVAL(params,0);
3433 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3434 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3435 DEBUG(0,("call_trans2qfsinfo: encryption required "
3436 "and info level 0x%x sent.\n",
3437 (unsigned int)info_level));
3438 exit_server_cleanly("encryption required "
3444 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3446 status = smbd_do_qfsinfo(conn, req,
3451 if (!NT_STATUS_IS_OK(status)) {
3452 reply_nterror(req, status);
3456 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3459 DEBUG( 4, ( "%s info_level = %d\n",
3460 smb_fn_name(req->cmd), info_level) );
3465 /****************************************************************************
3466 Reply to a TRANS2_SETFSINFO (set filesystem info).
3467 ****************************************************************************/
3469 static void call_trans2setfsinfo(connection_struct *conn,
3470 struct smb_request *req,
3471 char **pparams, int total_params,
3472 char **ppdata, int total_data,
3473 unsigned int max_data_bytes)
3475 char *pdata = *ppdata;
3476 char *params = *pparams;
3479 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3482 if (total_params < 4) {
3483 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3489 info_level = SVAL(params,2);
3492 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3493 info_level != SMB_SET_CIFS_UNIX_INFO) {
3494 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3495 "info level (0x%x) on IPC$.\n",
3496 (unsigned int)info_level));
3497 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3502 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3503 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3504 DEBUG(0,("call_trans2setfsinfo: encryption required "
3505 "and info level 0x%x sent.\n",
3506 (unsigned int)info_level));
3507 exit_server_cleanly("encryption required "
3513 switch(info_level) {
3514 case SMB_SET_CIFS_UNIX_INFO:
3516 uint16 client_unix_major;
3517 uint16 client_unix_minor;
3518 uint32 client_unix_cap_low;
3519 uint32 client_unix_cap_high;
3521 if (!lp_unix_extensions()) {
3523 NT_STATUS_INVALID_LEVEL);
3527 /* There should be 12 bytes of capabilities set. */
3528 if (total_data < 8) {
3531 NT_STATUS_INVALID_PARAMETER);
3534 client_unix_major = SVAL(pdata,0);
3535 client_unix_minor = SVAL(pdata,2);
3536 client_unix_cap_low = IVAL(pdata,4);
3537 client_unix_cap_high = IVAL(pdata,8);
3538 /* Just print these values for now. */
3539 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3540 cap_low = 0x%x, cap_high = 0x%x\n",
3541 (unsigned int)client_unix_major,
3542 (unsigned int)client_unix_minor,
3543 (unsigned int)client_unix_cap_low,
3544 (unsigned int)client_unix_cap_high ));
3546 /* Here is where we must switch to posix pathname processing... */
3547 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3548 lp_set_posix_pathnames();
3549 mangle_change_to_posix();
3552 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3553 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3554 /* Client that knows how to do posix locks,
3555 * but not posix open/mkdir operations. Set a
3556 * default type for read/write checks. */
3558 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3564 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3567 size_t param_len = 0;
3568 size_t data_len = total_data;
3570 if (!lp_unix_extensions()) {
3573 NT_STATUS_INVALID_LEVEL);
3577 if (lp_smb_encrypt(SNUM(conn)) == false) {
3580 NT_STATUS_NOT_SUPPORTED);
3584 DEBUG( 4,("call_trans2setfsinfo: "
3585 "request transport encryption.\n"));
3587 status = srv_request_encryption_setup(conn,
3588 (unsigned char **)ppdata,
3590 (unsigned char **)pparams,
3593 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3594 !NT_STATUS_IS_OK(status)) {
3595 reply_nterror(req, status);
3599 send_trans2_replies(conn, req,
3606 if (NT_STATUS_IS_OK(status)) {
3607 /* Server-side transport
3608 * encryption is now *on*. */
3609 status = srv_encryption_start(conn);
3610 if (!NT_STATUS_IS_OK(status)) {
3611 exit_server_cleanly(
3612 "Failure in setting "
3613 "up encrypted transport");
3619 case SMB_FS_QUOTA_INFORMATION:
3621 files_struct *fsp = NULL;
3622 SMB_NTQUOTA_STRUCT quotas;
3624 ZERO_STRUCT(quotas);
3627 if ((conn->server_info->utok.uid != sec_initial_uid())
3628 ||!CAN_WRITE(conn)) {
3629 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3630 lp_servicename(SNUM(conn)),
3631 conn->server_info->unix_name));
3632 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3636 /* note: normaly there're 48 bytes,
3637 * but we didn't use the last 6 bytes for now
3640 fsp = file_fsp(req, SVAL(params,0));
3642 if (!check_fsp_ntquota_handle(conn, req,
3644 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3646 req, NT_STATUS_INVALID_HANDLE);
3650 if (total_data < 42) {
3651 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3655 NT_STATUS_INVALID_PARAMETER);
3659 /* unknown_1 24 NULL bytes in pdata*/
3661 /* the soft quotas 8 bytes (uint64_t)*/
3662 quotas.softlim = (uint64_t)IVAL(pdata,24);
3663 #ifdef LARGE_SMB_OFF_T
3664 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3665 #else /* LARGE_SMB_OFF_T */
3666 if ((IVAL(pdata,28) != 0)&&
3667 ((quotas.softlim != 0xFFFFFFFF)||
3668 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3669 /* more than 32 bits? */
3672 NT_STATUS_INVALID_PARAMETER);
3675 #endif /* LARGE_SMB_OFF_T */
3677 /* the hard quotas 8 bytes (uint64_t)*/
3678 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3679 #ifdef LARGE_SMB_OFF_T
3680 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3681 #else /* LARGE_SMB_OFF_T */
3682 if ((IVAL(pdata,36) != 0)&&
3683 ((quotas.hardlim != 0xFFFFFFFF)||
3684 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3685 /* more than 32 bits? */
3688 NT_STATUS_INVALID_PARAMETER);
3691 #endif /* LARGE_SMB_OFF_T */
3693 /* quota_flags 2 bytes **/
3694 quotas.qflags = SVAL(pdata,40);
3696 /* unknown_2 6 NULL bytes follow*/
3698 /* now set the quotas */
3699 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3700 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3701 reply_nterror(req, map_nt_error_from_unix(errno));
3708 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3710 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3716 * sending this reply works fine,
3717 * but I'm not sure it's the same
3718 * like windows do...
3721 reply_outbuf(req, 10, 0);
3724 #if defined(HAVE_POSIX_ACLS)
3725 /****************************************************************************
3726 Utility function to count the number of entries in a POSIX acl.
3727 ****************************************************************************/
3729 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3731 unsigned int ace_count = 0;
3732 int entry_id = SMB_ACL_FIRST_ENTRY;
3733 SMB_ACL_ENTRY_T entry;
3735 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3737 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3738 entry_id = SMB_ACL_NEXT_ENTRY;
3745 /****************************************************************************
3746 Utility function to marshall a POSIX acl into wire format.
3747 ****************************************************************************/
3749 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3751 int entry_id = SMB_ACL_FIRST_ENTRY;
3752 SMB_ACL_ENTRY_T entry;
3754 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3755 SMB_ACL_TAG_T tagtype;
3756 SMB_ACL_PERMSET_T permset;
3757 unsigned char perms = 0;
3758 unsigned int own_grp;
3761 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3762 entry_id = SMB_ACL_NEXT_ENTRY;
3765 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3766 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3770 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3771 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3775 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3776 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3777 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3779 SCVAL(pdata,1,perms);
3782 case SMB_ACL_USER_OBJ:
3783 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3784 own_grp = (unsigned int)pst->st_ex_uid;
3785 SIVAL(pdata,2,own_grp);
3790 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3792 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3795 own_grp = (unsigned int)*puid;
3796 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3797 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3798 SIVAL(pdata,2,own_grp);
3802 case SMB_ACL_GROUP_OBJ:
3803 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3804 own_grp = (unsigned int)pst->st_ex_gid;
3805 SIVAL(pdata,2,own_grp);
3810 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3812 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3815 own_grp = (unsigned int)*pgid;
3816 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3817 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3818 SIVAL(pdata,2,own_grp);
3823 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3824 SIVAL(pdata,2,0xFFFFFFFF);
3825 SIVAL(pdata,6,0xFFFFFFFF);
3828 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3829 SIVAL(pdata,2,0xFFFFFFFF);
3830 SIVAL(pdata,6,0xFFFFFFFF);
3833 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3836 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3843 /****************************************************************************
3844 Store the FILE_UNIX_BASIC info.
3845 ****************************************************************************/
3847 static char *store_file_unix_basic(connection_struct *conn,
3850 const SMB_STRUCT_STAT *psbuf)
3852 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3853 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3855 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3858 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3861 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3862 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3863 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3866 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3870 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3874 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3877 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3881 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3885 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3888 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3892 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3899 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3900 * the chflags(2) (or equivalent) flags.
3902 * XXX: this really should be behind the VFS interface. To do this, we would
3903 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3904 * Each VFS module could then implement its own mapping as appropriate for the
3905 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3907 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3911 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3915 { UF_IMMUTABLE, EXT_IMMUTABLE },
3919 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3923 { UF_HIDDEN, EXT_HIDDEN },
3926 /* Do not remove. We need to guarantee that this array has at least one
3927 * entry to build on HP-UX.
3933 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3934 uint32 *smb_fflags, uint32 *smb_fmask)
3938 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3939 *smb_fmask |= info2_flags_map[i].smb_fflag;
3940 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3941 *smb_fflags |= info2_flags_map[i].smb_fflag;
3946 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3947 const uint32 smb_fflags,
3948 const uint32 smb_fmask,
3951 uint32 max_fmask = 0;
3954 *stat_fflags = psbuf->st_ex_flags;
3956 /* For each flags requested in smb_fmask, check the state of the
3957 * corresponding flag in smb_fflags and set or clear the matching
3961 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3962 max_fmask |= info2_flags_map[i].smb_fflag;
3963 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3964 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3965 *stat_fflags |= info2_flags_map[i].stat_fflag;
3967 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3972 /* If smb_fmask is asking to set any bits that are not supported by
3973 * our flag mappings, we should fail.
3975 if ((smb_fmask & max_fmask) != smb_fmask) {
3983 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3984 * of file flags and birth (create) time.
3986 static char *store_file_unix_basic_info2(connection_struct *conn,
3989 const SMB_STRUCT_STAT *psbuf)
3991 uint32 file_flags = 0;
3992 uint32 flags_mask = 0;
3994 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3996 /* Create (birth) time 64 bit */
3997 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4000 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4001 SIVAL(pdata, 0, file_flags); /* flags */
4002 SIVAL(pdata, 4, flags_mask); /* mask */
4008 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4009 const struct stream_struct *streams,
4011 unsigned int max_data_bytes,
4012 unsigned int *data_size)
4015 unsigned int ofs = 0;
4017 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4018 unsigned int next_offset;
4020 smb_ucs2_t *namebuf;
4022 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4023 streams[i].name, &namelen) ||
4026 return NT_STATUS_INVALID_PARAMETER;
4030 * name_buf is now null-terminated, we need to marshall as not
4036 SIVAL(data, ofs+4, namelen);
4037 SOFF_T(data, ofs+8, streams[i].size);
4038 SOFF_T(data, ofs+16, streams[i].alloc_size);
4039 memcpy(data+ofs+24, namebuf, namelen);
4040 TALLOC_FREE(namebuf);
4042 next_offset = ofs + 24 + namelen;
4044 if (i == num_streams-1) {
4045 SIVAL(data, ofs, 0);
4048 unsigned int align = ndr_align_size(next_offset, 8);
4050 memset(data+next_offset, 0, align);
4051 next_offset += align;
4053 SIVAL(data, ofs, next_offset - ofs);
4062 return NT_STATUS_OK;
4065 /****************************************************************************
4066 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4067 ****************************************************************************/
4069 static void call_trans2qpipeinfo(connection_struct *conn,
4070 struct smb_request *req,
4071 unsigned int tran_call,
4072 char **pparams, int total_params,
4073 char **ppdata, int total_data,
4074 unsigned int max_data_bytes)
4076 char *params = *pparams;
4077 char *pdata = *ppdata;
4078 unsigned int data_size = 0;
4079 unsigned int param_size = 2;
4084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4088 if (total_params < 4) {
4089 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4093 fsp = file_fsp(req, SVAL(params,0));
4094 if (!fsp_is_np(fsp)) {
4095 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4099 info_level = SVAL(params,2);
4101 *pparams = (char *)SMB_REALLOC(*pparams,2);
4102 if (*pparams == NULL) {
4103 reply_nterror(req, NT_STATUS_NO_MEMORY);
4108 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4109 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4110 if (*ppdata == NULL ) {
4111 reply_nterror(req, NT_STATUS_NO_MEMORY);
4116 switch (info_level) {
4117 case SMB_FILE_STANDARD_INFORMATION:
4119 SOFF_T(pdata,0,4096LL);
4126 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4130 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4136 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4137 TALLOC_CTX *mem_ctx,
4138 uint16_t info_level,
4140 struct smb_filename *smb_fname,
4141 bool delete_pending,
4142 struct timespec write_time_ts,
4144 struct ea_list *ea_list,
4145 int lock_data_count,
4148 unsigned int max_data_bytes,
4150 unsigned int *pdata_size)
4152 char *pdata = *ppdata;
4153 char *dstart, *dend;
4154 unsigned int data_size;
4155 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4156 time_t create_time, mtime, atime, c_time;
4157 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4164 uint64_t file_size = 0;
4166 uint64_t allocation_size = 0;
4167 uint64_t file_index = 0;
4168 uint32_t access_mask = 0;
4170 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4171 return NT_STATUS_INVALID_LEVEL;
4174 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4175 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4176 info_level, max_data_bytes));
4179 mode = dos_mode_msdfs(conn, smb_fname);
4181 mode = dos_mode(conn, smb_fname);
4184 mode = FILE_ATTRIBUTE_NORMAL;
4186 nlink = psbuf->st_ex_nlink;
4188 if (nlink && (mode&aDIR)) {
4192 if ((nlink > 0) && delete_pending) {
4196 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4197 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4198 if (*ppdata == NULL) {
4199 return NT_STATUS_NO_MEMORY;
4203 dend = dstart + data_size - 1;
4205 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4206 update_stat_ex_mtime(psbuf, write_time_ts);
4209 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4210 mtime_ts = psbuf->st_ex_mtime;
4211 atime_ts = psbuf->st_ex_atime;
4212 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4214 if (lp_dos_filetime_resolution(SNUM(conn))) {
4215 dos_filetime_timespec(&create_time_ts);
4216 dos_filetime_timespec(&mtime_ts);
4217 dos_filetime_timespec(&atime_ts);
4218 dos_filetime_timespec(&ctime_ts);
4221 create_time = convert_timespec_to_time_t(create_time_ts);
4222 mtime = convert_timespec_to_time_t(mtime_ts);
4223 atime = convert_timespec_to_time_t(atime_ts);
4224 c_time = convert_timespec_to_time_t(ctime_ts);
4226 p = strrchr_m(smb_fname->base_name,'/');
4228 base_name = smb_fname->base_name;
4232 /* NT expects the name to be in an exact form of the *full*
4233 filename. See the trans2 torture test */
4234 if (ISDOT(base_name)) {
4235 dos_fname = talloc_strdup(mem_ctx, "\\");
4237 return NT_STATUS_NO_MEMORY;
4240 dos_fname = talloc_asprintf(mem_ctx,
4242 smb_fname->base_name);
4244 return NT_STATUS_NO_MEMORY;
4246 if (is_ntfs_stream_smb_fname(smb_fname)) {
4247 dos_fname = talloc_asprintf(dos_fname, "%s",
4248 smb_fname->stream_name);
4250 return NT_STATUS_NO_MEMORY;
4254 string_replace(dos_fname, '/', '\\');
4257 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4260 /* Do we have this path open ? */
4262 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4263 fsp1 = file_find_di_first(fileid);
4264 if (fsp1 && fsp1->initial_allocation_size) {
4265 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4269 if (!(mode & aDIR)) {
4270 file_size = get_file_size_stat(psbuf);
4274 pos = fsp->fh->position_information;
4278 access_mask = fsp->access_mask;
4280 /* GENERIC_EXECUTE mapping from Windows */
4281 access_mask = 0x12019F;
4284 /* This should be an index number - looks like
4287 I think this causes us to fail the IFSKIT
4288 BasicFileInformationTest. -tpot */
4289 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4290 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4292 switch (info_level) {
4293 case SMB_INFO_STANDARD:
4294 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4296 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4297 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4298 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4299 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4300 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4301 SSVAL(pdata,l1_attrFile,mode);
4304 case SMB_INFO_QUERY_EA_SIZE:
4306 unsigned int ea_size =
4307 estimate_ea_size(conn, fsp,
4308 smb_fname->base_name);
4309 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4311 srv_put_dos_date2(pdata,0,create_time);
4312 srv_put_dos_date2(pdata,4,atime);
4313 srv_put_dos_date2(pdata,8,mtime); /* write time */
4314 SIVAL(pdata,12,(uint32)file_size);
4315 SIVAL(pdata,16,(uint32)allocation_size);
4316 SSVAL(pdata,20,mode);
4317 SIVAL(pdata,22,ea_size);
4321 case SMB_INFO_IS_NAME_VALID:
4322 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4324 /* os/2 needs this ? really ?*/
4325 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4327 /* This is only reached for qpathinfo */
4331 case SMB_INFO_QUERY_EAS_FROM_LIST:
4333 size_t total_ea_len = 0;
4334 struct ea_list *ea_file_list = NULL;
4336 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4339 get_ea_list_from_file(mem_ctx, conn, fsp,
4340 smb_fname->base_name,
4342 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4344 if (!ea_list || (total_ea_len > data_size)) {
4346 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4350 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4354 case SMB_INFO_QUERY_ALL_EAS:
4356 /* We have data_size bytes to put EA's into. */
4357 size_t total_ea_len = 0;
4359 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4361 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4362 smb_fname->base_name,
4364 if (!ea_list || (total_ea_len > data_size)) {
4366 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4370 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4374 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4376 /* We have data_size bytes to put EA's into. */
4377 size_t total_ea_len = 0;
4378 struct ea_list *ea_file_list = NULL;
4380 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4382 /*TODO: add filtering and index handling */
4385 get_ea_list_from_file(mem_ctx, conn, fsp,
4386 smb_fname->base_name,
4388 if (!ea_file_list) {
4389 return NT_STATUS_NO_EAS_ON_FILE;
4392 status = fill_ea_chained_buffer(mem_ctx,
4396 conn, ea_file_list);
4397 if (!NT_STATUS_IS_OK(status)) {
4403 case SMB_FILE_BASIC_INFORMATION:
4404 case SMB_QUERY_FILE_BASIC_INFO:
4406 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4407 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4408 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4410 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4414 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4415 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4416 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4417 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4418 SIVAL(pdata,32,mode);
4420 DEBUG(5,("SMB_QFBI - "));
4421 DEBUG(5,("create: %s ", ctime(&create_time)));
4422 DEBUG(5,("access: %s ", ctime(&atime)));
4423 DEBUG(5,("write: %s ", ctime(&mtime)));
4424 DEBUG(5,("change: %s ", ctime(&c_time)));
4425 DEBUG(5,("mode: %x\n", mode));
4428 case SMB_FILE_STANDARD_INFORMATION:
4429 case SMB_QUERY_FILE_STANDARD_INFO:
4431 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4433 SOFF_T(pdata,0,allocation_size);
4434 SOFF_T(pdata,8,file_size);
4435 SIVAL(pdata,16,nlink);
4436 SCVAL(pdata,20,delete_pending?1:0);
4437 SCVAL(pdata,21,(mode&aDIR)?1:0);
4438 SSVAL(pdata,22,0); /* Padding. */
4441 case SMB_FILE_EA_INFORMATION:
4442 case SMB_QUERY_FILE_EA_INFO:
4444 unsigned int ea_size =
4445 estimate_ea_size(conn, fsp, smb_fname->base_name);
4446 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4448 SIVAL(pdata,0,ea_size);
4452 /* Get the 8.3 name - used if NT SMB was negotiated. */
4453 case SMB_QUERY_FILE_ALT_NAME_INFO:
4454 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4457 char mangled_name[13];
4458 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4459 if (!name_to_8_3(base_name,mangled_name,
4460 True,conn->params)) {
4461 return NT_STATUS_NO_MEMORY;
4463 len = srvstr_push(dstart, flags2,
4464 pdata+4, mangled_name,
4465 PTR_DIFF(dend, pdata+4),
4467 data_size = 4 + len;
4472 case SMB_QUERY_FILE_NAME_INFO:
4476 this must be *exactly* right for ACLs on mapped drives to work
4478 len = srvstr_push(dstart, flags2,
4480 PTR_DIFF(dend, pdata+4),
4482 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4483 data_size = 4 + len;
4488 case SMB_FILE_ALLOCATION_INFORMATION:
4489 case SMB_QUERY_FILE_ALLOCATION_INFO:
4490 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4492 SOFF_T(pdata,0,allocation_size);
4495 case SMB_FILE_END_OF_FILE_INFORMATION:
4496 case SMB_QUERY_FILE_END_OF_FILEINFO:
4497 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4499 SOFF_T(pdata,0,file_size);
4502 case SMB_QUERY_FILE_ALL_INFO:
4503 case SMB_FILE_ALL_INFORMATION:
4506 unsigned int ea_size =
4507 estimate_ea_size(conn, fsp, smb_fname->base_name);
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4509 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4510 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4511 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4512 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4513 SIVAL(pdata,32,mode);
4514 SIVAL(pdata,36,0); /* padding. */
4516 SOFF_T(pdata,0,allocation_size);
4517 SOFF_T(pdata,8,file_size);
4518 SIVAL(pdata,16,nlink);
4519 SCVAL(pdata,20,delete_pending);
4520 SCVAL(pdata,21,(mode&aDIR)?1:0);
4523 SIVAL(pdata,0,ea_size);
4524 pdata += 4; /* EA info */
4525 len = srvstr_push(dstart, flags2,
4527 PTR_DIFF(dend, pdata+4),
4531 data_size = PTR_DIFF(pdata,(*ppdata));
4535 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4538 unsigned int ea_size =
4539 estimate_ea_size(conn, fsp, smb_fname->base_name);
4540 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4541 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4542 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4543 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4544 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4545 SIVAL(pdata, 0x20, mode);
4546 SIVAL(pdata, 0x24, 0); /* padding. */
4547 SBVAL(pdata, 0x28, allocation_size);
4548 SBVAL(pdata, 0x30, file_size);
4549 SIVAL(pdata, 0x38, nlink);
4550 SCVAL(pdata, 0x3C, delete_pending);
4551 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4552 SSVAL(pdata, 0x3E, 0); /* padding */
4553 SBVAL(pdata, 0x40, file_index);
4554 SIVAL(pdata, 0x48, ea_size);
4555 SIVAL(pdata, 0x4C, access_mask);
4556 SBVAL(pdata, 0x50, pos);
4557 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4558 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4562 len = srvstr_push(dstart, flags2,
4564 PTR_DIFF(dend, pdata+4),
4568 data_size = PTR_DIFF(pdata,(*ppdata));
4571 case SMB_FILE_INTERNAL_INFORMATION:
4573 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4574 SBVAL(pdata, 0, file_index);
4578 case SMB_FILE_ACCESS_INFORMATION:
4579 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4580 SIVAL(pdata, 0, access_mask);
4584 case SMB_FILE_NAME_INFORMATION:
4585 /* Pathname with leading '\'. */
4588 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4589 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4590 SIVAL(pdata,0,byte_len);
4591 data_size = 4 + byte_len;
4595 case SMB_FILE_DISPOSITION_INFORMATION:
4596 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4598 SCVAL(pdata,0,delete_pending);
4601 case SMB_FILE_POSITION_INFORMATION:
4602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4604 SOFF_T(pdata,0,pos);
4607 case SMB_FILE_MODE_INFORMATION:
4608 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4609 SIVAL(pdata,0,mode);
4613 case SMB_FILE_ALIGNMENT_INFORMATION:
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4615 SIVAL(pdata,0,0); /* No alignment needed. */
4620 * NT4 server just returns "invalid query" to this - if we try
4621 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4624 /* The first statement above is false - verified using Thursby
4625 * client against NT4 -- gcolley.
4627 case SMB_QUERY_FILE_STREAM_INFO:
4628 case SMB_FILE_STREAM_INFORMATION: {
4629 unsigned int num_streams;
4630 struct stream_struct *streams;
4632 DEBUG(10,("smbd_do_qfilepathinfo: "
4633 "SMB_FILE_STREAM_INFORMATION\n"));
4635 if (is_ntfs_stream_smb_fname(smb_fname)) {
4636 return NT_STATUS_INVALID_PARAMETER;
4639 status = SMB_VFS_STREAMINFO(
4640 conn, fsp, smb_fname->base_name, talloc_tos(),
4641 &num_streams, &streams);
4643 if (!NT_STATUS_IS_OK(status)) {
4644 DEBUG(10, ("could not get stream info: %s\n",
4645 nt_errstr(status)));
4649 status = marshall_stream_info(num_streams, streams,
4650 pdata, max_data_bytes,
4653 if (!NT_STATUS_IS_OK(status)) {
4654 DEBUG(10, ("marshall_stream_info failed: %s\n",
4655 nt_errstr(status)));
4659 TALLOC_FREE(streams);
4663 case SMB_QUERY_COMPRESSION_INFO:
4664 case SMB_FILE_COMPRESSION_INFORMATION:
4665 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4666 SOFF_T(pdata,0,file_size);
4667 SIVAL(pdata,8,0); /* ??? */
4668 SIVAL(pdata,12,0); /* ??? */
4672 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4673 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4674 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4675 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4676 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4677 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4678 SOFF_T(pdata,32,allocation_size);
4679 SOFF_T(pdata,40,file_size);
4680 SIVAL(pdata,48,mode);
4681 SIVAL(pdata,52,0); /* ??? */
4685 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4686 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4687 SIVAL(pdata,0,mode);
4693 * CIFS UNIX Extensions.
4696 case SMB_QUERY_FILE_UNIX_BASIC:
4698 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4699 data_size = PTR_DIFF(pdata,(*ppdata));
4703 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4705 for (i=0; i<100; i++)
4706 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4712 case SMB_QUERY_FILE_UNIX_INFO2:
4714 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4715 data_size = PTR_DIFF(pdata,(*ppdata));
4719 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4721 for (i=0; i<100; i++)
4722 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4728 case SMB_QUERY_FILE_UNIX_LINK:
4731 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4734 return NT_STATUS_NO_MEMORY;
4737 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4739 if(!S_ISLNK(psbuf->st_ex_mode)) {
4740 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4743 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4745 len = SMB_VFS_READLINK(conn,
4746 smb_fname->base_name,
4749 return map_nt_error_from_unix(errno);
4752 len = srvstr_push(dstart, flags2,
4754 PTR_DIFF(dend, pdata),
4757 data_size = PTR_DIFF(pdata,(*ppdata));
4762 #if defined(HAVE_POSIX_ACLS)
4763 case SMB_QUERY_POSIX_ACL:
4765 SMB_ACL_T file_acl = NULL;
4766 SMB_ACL_T def_acl = NULL;
4767 uint16 num_file_acls = 0;
4768 uint16 num_def_acls = 0;
4770 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4771 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4774 SMB_VFS_SYS_ACL_GET_FILE(conn,
4775 smb_fname->base_name,
4776 SMB_ACL_TYPE_ACCESS);
4779 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4780 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4781 "not implemented on "
4782 "filesystem containing %s\n",
4783 smb_fname->base_name));
4784 return NT_STATUS_NOT_IMPLEMENTED;
4787 if (S_ISDIR(psbuf->st_ex_mode)) {
4788 if (fsp && fsp->is_directory) {
4790 SMB_VFS_SYS_ACL_GET_FILE(
4792 fsp->fsp_name->base_name,
4793 SMB_ACL_TYPE_DEFAULT);
4796 SMB_VFS_SYS_ACL_GET_FILE(
4798 smb_fname->base_name,
4799 SMB_ACL_TYPE_DEFAULT);
4801 def_acl = free_empty_sys_acl(conn, def_acl);
4804 num_file_acls = count_acl_entries(conn, file_acl);
4805 num_def_acls = count_acl_entries(conn, def_acl);
4807 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4808 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4810 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4811 SMB_POSIX_ACL_HEADER_SIZE) ));
4813 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4816 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4818 return NT_STATUS_BUFFER_TOO_SMALL;
4821 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4822 SSVAL(pdata,2,num_file_acls);
4823 SSVAL(pdata,4,num_def_acls);
4824 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4826 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4829 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4831 return NT_STATUS_INTERNAL_ERROR;
4833 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4835 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4838 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4840 return NT_STATUS_INTERNAL_ERROR;
4844 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4847 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4849 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4855 case SMB_QUERY_POSIX_LOCK:
4860 enum brl_type lock_type;
4862 /* We need an open file with a real fd for this. */
4863 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4864 return NT_STATUS_INVALID_LEVEL;
4867 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4868 return NT_STATUS_INVALID_PARAMETER;
4871 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4872 case POSIX_LOCK_TYPE_READ:
4873 lock_type = READ_LOCK;
4875 case POSIX_LOCK_TYPE_WRITE:
4876 lock_type = WRITE_LOCK;
4878 case POSIX_LOCK_TYPE_UNLOCK:
4880 /* There's no point in asking for an unlock... */
4881 return NT_STATUS_INVALID_PARAMETER;
4884 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4885 #if defined(HAVE_LONGLONG)
4886 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4887 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4888 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4889 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4890 #else /* HAVE_LONGLONG */
4891 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4892 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4893 #endif /* HAVE_LONGLONG */
4895 status = query_lock(fsp,
4902 if (ERROR_WAS_LOCK_DENIED(status)) {
4903 /* Here we need to report who has it locked... */
4904 data_size = POSIX_LOCK_DATA_SIZE;
4906 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4907 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4908 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4909 #if defined(HAVE_LONGLONG)
4910 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4911 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4912 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4913 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4914 #else /* HAVE_LONGLONG */
4915 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4916 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4917 #endif /* HAVE_LONGLONG */
4919 } else if (NT_STATUS_IS_OK(status)) {
4920 /* For success we just return a copy of what we sent
4921 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4922 data_size = POSIX_LOCK_DATA_SIZE;
4923 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4924 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4932 return NT_STATUS_INVALID_LEVEL;
4935 *pdata_size = data_size;
4936 return NT_STATUS_OK;
4939 /****************************************************************************
4940 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4941 file name or file id).
4942 ****************************************************************************/
4944 static void call_trans2qfilepathinfo(connection_struct *conn,
4945 struct smb_request *req,
4946 unsigned int tran_call,
4947 char **pparams, int total_params,
4948 char **ppdata, int total_data,
4949 unsigned int max_data_bytes)
4951 char *params = *pparams;
4952 char *pdata = *ppdata;
4954 unsigned int data_size = 0;
4955 unsigned int param_size = 2;
4956 struct smb_filename *smb_fname = NULL;
4957 bool delete_pending = False;
4958 struct timespec write_time_ts;
4959 files_struct *fsp = NULL;
4960 struct file_id fileid;
4961 struct ea_list *ea_list = NULL;
4962 int lock_data_count = 0;
4963 char *lock_data = NULL;
4964 bool ms_dfs_link = false;
4965 NTSTATUS status = NT_STATUS_OK;
4968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4972 ZERO_STRUCT(write_time_ts);
4974 if (tran_call == TRANSACT2_QFILEINFO) {
4975 if (total_params < 4) {
4976 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4981 call_trans2qpipeinfo(conn, req, tran_call,
4982 pparams, total_params,
4988 fsp = file_fsp(req, SVAL(params,0));
4989 info_level = SVAL(params,2);
4991 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4993 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4994 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4998 /* Initial check for valid fsp ptr. */
4999 if (!check_fsp_open(conn, req, fsp)) {
5003 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5005 if (!NT_STATUS_IS_OK(status)) {
5006 reply_nterror(req, status);
5010 if(fsp->fake_file_handle) {
5012 * This is actually for the QUOTA_FAKE_FILE --metze
5015 /* We know this name is ok, it's already passed the checks. */
5017 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5019 * This is actually a QFILEINFO on a directory
5020 * handle (returned from an NT SMB). NT5.0 seems
5021 * to do this call. JRA.
5024 if (INFO_LEVEL_IS_UNIX(info_level)) {
5025 /* Always do lstat for UNIX calls. */
5026 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5027 DEBUG(3,("call_trans2qfilepathinfo: "
5028 "SMB_VFS_LSTAT of %s failed "
5030 smb_fname_str_dbg(smb_fname),
5033 map_nt_error_from_unix(errno));
5036 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5037 DEBUG(3,("call_trans2qfilepathinfo: "
5038 "SMB_VFS_STAT of %s failed (%s)\n",
5039 smb_fname_str_dbg(smb_fname),
5042 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);
5050 * Original code - this is an open file.
5052 if (!check_fsp(conn, req, fsp)) {
5056 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5057 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5058 fsp->fnum, strerror(errno)));
5060 map_nt_error_from_unix(errno));
5063 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5064 get_file_infos(fileid, &delete_pending, &write_time_ts);
5071 if (total_params < 7) {
5072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5076 info_level = SVAL(params,0);
5078 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5080 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5081 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5085 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5087 STR_TERMINATE, &status);
5088 if (!NT_STATUS_IS_OK(status)) {
5089 reply_nterror(req, status);
5093 status = filename_convert(req,
5095 req->flags2 & FLAGS2_DFS_PATHNAMES,
5100 if (!NT_STATUS_IS_OK(status)) {
5101 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5102 reply_botherror(req,
5103 NT_STATUS_PATH_NOT_COVERED,
5104 ERRSRV, ERRbadpath);
5107 reply_nterror(req, status);
5111 /* If this is a stream, check if there is a delete_pending. */
5112 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5113 && is_ntfs_stream_smb_fname(smb_fname)) {
5114 struct smb_filename *smb_fname_base = NULL;
5116 /* Create an smb_filename with stream_name == NULL. */
5118 create_synthetic_smb_fname(talloc_tos(),
5119 smb_fname->base_name,
5122 if (!NT_STATUS_IS_OK(status)) {
5123 reply_nterror(req, status);
5127 if (INFO_LEVEL_IS_UNIX(info_level)) {
5128 /* Always do lstat for UNIX calls. */
5129 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5130 DEBUG(3,("call_trans2qfilepathinfo: "
5131 "SMB_VFS_LSTAT of %s failed "
5133 smb_fname_str_dbg(smb_fname_base),
5135 TALLOC_FREE(smb_fname_base);
5137 map_nt_error_from_unix(errno));
5141 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5142 DEBUG(3,("call_trans2qfilepathinfo: "
5143 "fileinfo of %s failed "
5145 smb_fname_str_dbg(smb_fname_base),
5147 TALLOC_FREE(smb_fname_base);
5149 map_nt_error_from_unix(errno));
5154 fileid = vfs_file_id_from_sbuf(conn,
5155 &smb_fname_base->st);
5156 TALLOC_FREE(smb_fname_base);
5157 get_file_infos(fileid, &delete_pending, NULL);
5158 if (delete_pending) {
5159 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5164 if (INFO_LEVEL_IS_UNIX(info_level)) {
5165 /* Always do lstat for UNIX calls. */
5166 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5167 DEBUG(3,("call_trans2qfilepathinfo: "
5168 "SMB_VFS_LSTAT of %s failed (%s)\n",
5169 smb_fname_str_dbg(smb_fname),
5172 map_nt_error_from_unix(errno));
5176 } else if (!VALID_STAT(smb_fname->st) &&
5177 SMB_VFS_STAT(conn, smb_fname) &&
5178 (info_level != SMB_INFO_IS_NAME_VALID)) {
5179 ms_dfs_link = check_msdfs_link(conn,
5180 smb_fname->base_name,
5184 DEBUG(3,("call_trans2qfilepathinfo: "
5185 "SMB_VFS_STAT of %s failed (%s)\n",
5186 smb_fname_str_dbg(smb_fname),
5189 map_nt_error_from_unix(errno));
5194 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5195 get_file_infos(fileid, &delete_pending, &write_time_ts);
5196 if (delete_pending) {
5197 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5202 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5203 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5204 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5206 /* Pull out any data sent here before we realloc. */
5207 switch (info_level) {
5208 case SMB_INFO_QUERY_EAS_FROM_LIST:
5210 /* Pull any EA list from the data portion. */
5213 if (total_data < 4) {
5215 req, NT_STATUS_INVALID_PARAMETER);
5218 ea_size = IVAL(pdata,0);
5220 if (total_data > 0 && ea_size != total_data) {
5221 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5222 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5224 req, NT_STATUS_INVALID_PARAMETER);
5228 if (!lp_ea_support(SNUM(conn))) {
5229 reply_doserror(req, ERRDOS,
5230 ERReasnotsupported);
5234 /* Pull out the list of names. */
5235 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5238 req, NT_STATUS_INVALID_PARAMETER);
5244 case SMB_QUERY_POSIX_LOCK:
5246 if (fsp == NULL || fsp->fh->fd == -1) {
5247 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5251 if (total_data != POSIX_LOCK_DATA_SIZE) {
5253 req, NT_STATUS_INVALID_PARAMETER);
5257 /* Copy the lock range data. */
5258 lock_data = (char *)TALLOC_MEMDUP(
5259 req, pdata, total_data);
5261 reply_nterror(req, NT_STATUS_NO_MEMORY);
5264 lock_data_count = total_data;
5270 *pparams = (char *)SMB_REALLOC(*pparams,2);
5271 if (*pparams == NULL) {
5272 reply_nterror(req, NT_STATUS_NO_MEMORY);
5279 * draft-leach-cifs-v1-spec-02.txt
5280 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5283 * The requested information is placed in the Data portion of the
5284 * transaction response. For the information levels greater than 0x100,
5285 * the transaction response has 1 parameter word which should be
5286 * ignored by the client.
5288 * However Windows only follows this rule for the IS_NAME_VALID call.
5290 switch (info_level) {
5291 case SMB_INFO_IS_NAME_VALID:
5296 if ((info_level & 0xFF00) == 0xFF00) {
5298 * We use levels that start with 0xFF00
5299 * internally to represent SMB2 specific levels
5301 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5305 status = smbd_do_qfilepathinfo(conn, req, info_level,
5307 delete_pending, write_time_ts,
5308 ms_dfs_link, ea_list,
5309 lock_data_count, lock_data,
5310 req->flags2, max_data_bytes,
5311 ppdata, &data_size);
5312 if (!NT_STATUS_IS_OK(status)) {
5313 reply_nterror(req, status);
5317 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5323 /****************************************************************************
5324 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5326 ****************************************************************************/
5328 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5329 connection_struct *conn,
5330 const struct smb_filename *smb_fname_old,
5331 const struct smb_filename *smb_fname_new)
5333 NTSTATUS status = NT_STATUS_OK;
5335 /* source must already exist. */
5336 if (!VALID_STAT(smb_fname_old->st)) {
5337 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5340 /* Disallow if newname already exists. */
5341 if (VALID_STAT(smb_fname_new->st)) {
5342 return NT_STATUS_OBJECT_NAME_COLLISION;
5345 /* No links from a directory. */
5346 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5347 return NT_STATUS_FILE_IS_A_DIRECTORY;
5350 /* Setting a hardlink to/from a stream isn't currently supported. */
5351 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5352 is_ntfs_stream_smb_fname(smb_fname_new)) {
5353 return NT_STATUS_INVALID_PARAMETER;
5356 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5357 smb_fname_old->base_name, smb_fname_new->base_name));
5359 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5360 smb_fname_new->base_name) != 0) {
5361 status = map_nt_error_from_unix(errno);
5362 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5363 nt_errstr(status), smb_fname_old->base_name,
5364 smb_fname_new->base_name));
5369 /****************************************************************************
5370 Deal with setting the time from any of the setfilepathinfo functions.
5371 ****************************************************************************/
5373 NTSTATUS smb_set_file_time(connection_struct *conn,
5375 const struct smb_filename *smb_fname,
5376 struct smb_file_time *ft,
5377 bool setting_write_time)
5379 struct smb_filename *smb_fname_base = NULL;
5381 FILE_NOTIFY_CHANGE_LAST_ACCESS
5382 |FILE_NOTIFY_CHANGE_LAST_WRITE
5383 |FILE_NOTIFY_CHANGE_CREATION;
5386 if (!VALID_STAT(smb_fname->st)) {
5387 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5390 /* get some defaults (no modifications) if any info is zero or -1. */
5391 if (null_timespec(ft->create_time)) {
5392 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5395 if (null_timespec(ft->atime)) {
5396 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5399 if (null_timespec(ft->mtime)) {
5400 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5403 if (!setting_write_time) {
5404 /* ft->mtime comes from change time, not write time. */
5405 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5408 /* Ensure the resolution is the correct for
5409 * what we can store on this filesystem. */
5411 round_timespec(conn->ts_res, &ft->create_time);
5412 round_timespec(conn->ts_res, &ft->ctime);
5413 round_timespec(conn->ts_res, &ft->atime);
5414 round_timespec(conn->ts_res, &ft->mtime);
5416 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5417 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5418 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5419 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5420 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5421 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5422 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5423 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5425 if (setting_write_time) {
5427 * This was a Windows setfileinfo on an open file.
5428 * NT does this a lot. We also need to
5429 * set the time here, as it can be read by
5430 * FindFirst/FindNext and with the patch for bug #2045
5431 * in smbd/fileio.c it ensures that this timestamp is
5432 * kept sticky even after a write. We save the request
5433 * away and will set it on file close and after a write. JRA.
5436 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5437 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5440 if (fsp->base_fsp) {
5441 set_sticky_write_time_fsp(fsp->base_fsp,
5444 set_sticky_write_time_fsp(fsp, ft->mtime);
5447 set_sticky_write_time_path(
5448 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5453 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5455 /* Always call ntimes on the base, even if a stream was passed in. */
5456 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5457 NULL, &smb_fname->st,
5459 if (!NT_STATUS_IS_OK(status)) {
5463 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5464 TALLOC_FREE(smb_fname_base);
5465 return map_nt_error_from_unix(errno);
5467 TALLOC_FREE(smb_fname_base);
5469 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5470 smb_fname->base_name);
5471 return NT_STATUS_OK;
5474 /****************************************************************************
5475 Deal with setting the dosmode from any of the setfilepathinfo functions.
5476 ****************************************************************************/
5478 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5479 const struct smb_filename *smb_fname,
5482 struct smb_filename *smb_fname_base = NULL;
5485 if (!VALID_STAT(smb_fname->st)) {
5486 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5489 /* Always operate on the base_name, even if a stream was passed in. */
5490 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5491 NULL, &smb_fname->st,
5493 if (!NT_STATUS_IS_OK(status)) {
5498 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5505 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5507 /* check the mode isn't different, before changing it */
5508 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5509 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5510 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5511 (unsigned int)dosmode));
5513 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5515 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5517 smb_fname_str_dbg(smb_fname_base),
5519 status = map_nt_error_from_unix(errno);
5523 status = NT_STATUS_OK;
5525 TALLOC_FREE(smb_fname_base);
5529 /****************************************************************************
5530 Deal with setting the size from any of the setfilepathinfo functions.
5531 ****************************************************************************/
5533 static NTSTATUS smb_set_file_size(connection_struct *conn,
5534 struct smb_request *req,
5536 const struct smb_filename *smb_fname,
5537 const SMB_STRUCT_STAT *psbuf,
5540 NTSTATUS status = NT_STATUS_OK;
5541 struct smb_filename *smb_fname_tmp = NULL;
5542 files_struct *new_fsp = NULL;
5544 if (!VALID_STAT(*psbuf)) {
5545 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5548 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5550 if (size == get_file_size_stat(psbuf)) {
5551 return NT_STATUS_OK;
5554 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5555 smb_fname_str_dbg(smb_fname), (double)size));
5557 if (fsp && fsp->fh->fd != -1) {
5558 /* Handle based call. */
5559 if (vfs_set_filelen(fsp, size) == -1) {
5560 return map_nt_error_from_unix(errno);
5562 trigger_write_time_update_immediate(fsp);
5563 return NT_STATUS_OK;
5566 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5567 if (!NT_STATUS_IS_OK(status)) {
5571 smb_fname_tmp->st = *psbuf;
5573 status = SMB_VFS_CREATE_FILE(
5576 0, /* root_dir_fid */
5577 smb_fname_tmp, /* fname */
5578 FILE_WRITE_ATTRIBUTES, /* access_mask */
5579 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5581 FILE_OPEN, /* create_disposition*/
5582 0, /* create_options */
5583 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5584 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5585 0, /* allocation_size */
5588 &new_fsp, /* result */
5591 TALLOC_FREE(smb_fname_tmp);
5593 if (!NT_STATUS_IS_OK(status)) {
5594 /* NB. We check for open_was_deferred in the caller. */
5598 if (vfs_set_filelen(new_fsp, size) == -1) {
5599 status = map_nt_error_from_unix(errno);
5600 close_file(req, new_fsp,NORMAL_CLOSE);
5604 trigger_write_time_update_immediate(new_fsp);
5605 close_file(req, new_fsp,NORMAL_CLOSE);
5606 return NT_STATUS_OK;
5609 /****************************************************************************
5610 Deal with SMB_INFO_SET_EA.
5611 ****************************************************************************/
5613 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5617 const struct smb_filename *smb_fname)
5619 struct ea_list *ea_list = NULL;
5620 TALLOC_CTX *ctx = NULL;
5621 NTSTATUS status = NT_STATUS_OK;
5623 if (total_data < 10) {
5625 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5626 length. They seem to have no effect. Bug #3212. JRA */
5628 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5629 /* We're done. We only get EA info in this call. */
5630 return NT_STATUS_OK;
5633 return NT_STATUS_INVALID_PARAMETER;
5636 if (IVAL(pdata,0) > total_data) {
5637 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5638 IVAL(pdata,0), (unsigned int)total_data));
5639 return NT_STATUS_INVALID_PARAMETER;
5643 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5645 return NT_STATUS_INVALID_PARAMETER;
5647 status = set_ea(conn, fsp, smb_fname, ea_list);
5652 /****************************************************************************
5653 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5654 ****************************************************************************/
5656 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5660 const struct smb_filename *smb_fname)
5662 NTSTATUS status = NT_STATUS_OK;
5663 bool delete_on_close;
5666 if (total_data < 1) {
5667 return NT_STATUS_INVALID_PARAMETER;
5671 return NT_STATUS_INVALID_HANDLE;
5674 delete_on_close = (CVAL(pdata,0) ? True : False);
5675 dosmode = dos_mode(conn, smb_fname);
5677 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5678 "delete_on_close = %u\n",
5679 smb_fname_str_dbg(smb_fname),
5680 (unsigned int)dosmode,
5681 (unsigned int)delete_on_close ));
5683 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5685 if (!NT_STATUS_IS_OK(status)) {
5689 /* The set is across all open files on this dev/inode pair. */
5690 if (!set_delete_on_close(fsp, delete_on_close,
5691 &conn->server_info->utok)) {
5692 return NT_STATUS_ACCESS_DENIED;
5694 return NT_STATUS_OK;
5697 /****************************************************************************
5698 Deal with SMB_FILE_POSITION_INFORMATION.
5699 ****************************************************************************/
5701 static NTSTATUS smb_file_position_information(connection_struct *conn,
5706 uint64_t position_information;
5708 if (total_data < 8) {
5709 return NT_STATUS_INVALID_PARAMETER;
5713 /* Ignore on pathname based set. */
5714 return NT_STATUS_OK;
5717 position_information = (uint64_t)IVAL(pdata,0);
5718 #ifdef LARGE_SMB_OFF_T
5719 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5720 #else /* LARGE_SMB_OFF_T */
5721 if (IVAL(pdata,4) != 0) {
5722 /* more than 32 bits? */
5723 return NT_STATUS_INVALID_PARAMETER;
5725 #endif /* LARGE_SMB_OFF_T */
5727 DEBUG(10,("smb_file_position_information: Set file position "
5728 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5729 (double)position_information));
5730 fsp->fh->position_information = position_information;
5731 return NT_STATUS_OK;
5734 /****************************************************************************
5735 Deal with SMB_FILE_MODE_INFORMATION.
5736 ****************************************************************************/
5738 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5744 if (total_data < 4) {
5745 return NT_STATUS_INVALID_PARAMETER;
5747 mode = IVAL(pdata,0);
5748 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5749 return NT_STATUS_INVALID_PARAMETER;
5751 return NT_STATUS_OK;
5754 /****************************************************************************
5755 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5756 ****************************************************************************/
5758 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5759 struct smb_request *req,
5762 const struct smb_filename *smb_fname)
5764 char *link_target = NULL;
5765 const char *newname = smb_fname->base_name;
5766 NTSTATUS status = NT_STATUS_OK;
5767 TALLOC_CTX *ctx = talloc_tos();
5769 /* Set a symbolic link. */
5770 /* Don't allow this if follow links is false. */
5772 if (total_data == 0) {
5773 return NT_STATUS_INVALID_PARAMETER;
5776 if (!lp_symlinks(SNUM(conn))) {
5777 return NT_STATUS_ACCESS_DENIED;
5780 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5781 total_data, STR_TERMINATE);
5784 return NT_STATUS_INVALID_PARAMETER;
5787 /* !widelinks forces the target path to be within the share. */
5788 /* This means we can interpret the target as a pathname. */
5789 if (!lp_widelinks(SNUM(conn))) {
5790 char *rel_name = NULL;
5791 char *last_dirp = NULL;
5793 if (*link_target == '/') {
5794 /* No absolute paths allowed. */
5795 return NT_STATUS_ACCESS_DENIED;
5797 rel_name = talloc_strdup(ctx,newname);
5799 return NT_STATUS_NO_MEMORY;
5801 last_dirp = strrchr_m(rel_name, '/');
5803 last_dirp[1] = '\0';
5805 rel_name = talloc_strdup(ctx,"./");
5807 return NT_STATUS_NO_MEMORY;
5810 rel_name = talloc_asprintf_append(rel_name,
5814 return NT_STATUS_NO_MEMORY;
5817 status = check_name(conn, rel_name);
5818 if (!NT_STATUS_IS_OK(status)) {
5823 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5824 newname, link_target ));
5826 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5827 return map_nt_error_from_unix(errno);
5830 return NT_STATUS_OK;
5833 /****************************************************************************
5834 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5835 ****************************************************************************/
5837 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5838 struct smb_request *req,
5839 const char *pdata, int total_data,
5840 const struct smb_filename *smb_fname_new)
5842 char *oldname = NULL;
5843 struct smb_filename *smb_fname_old = NULL;
5844 TALLOC_CTX *ctx = talloc_tos();
5845 NTSTATUS status = NT_STATUS_OK;
5847 /* Set a hard link. */
5848 if (total_data == 0) {
5849 return NT_STATUS_INVALID_PARAMETER;
5852 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5853 total_data, STR_TERMINATE, &status);
5854 if (!NT_STATUS_IS_OK(status)) {
5858 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5859 smb_fname_str_dbg(smb_fname_new), oldname));
5861 status = filename_convert(ctx,
5863 req->flags2 & FLAGS2_DFS_PATHNAMES,
5868 if (!NT_STATUS_IS_OK(status)) {
5872 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5875 /****************************************************************************
5876 Deal with SMB_FILE_RENAME_INFORMATION.
5877 ****************************************************************************/
5879 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5880 struct smb_request *req,
5884 struct smb_filename *smb_fname_src)
5889 char *newname = NULL;
5890 struct smb_filename *smb_fname_dst = NULL;
5891 bool dest_has_wcard = False;
5892 NTSTATUS status = NT_STATUS_OK;
5894 TALLOC_CTX *ctx = talloc_tos();
5896 if (total_data < 13) {
5897 return NT_STATUS_INVALID_PARAMETER;
5900 overwrite = (CVAL(pdata,0) ? True : False);
5901 root_fid = IVAL(pdata,4);
5902 len = IVAL(pdata,8);
5904 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5905 return NT_STATUS_INVALID_PARAMETER;
5908 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5911 if (!NT_STATUS_IS_OK(status)) {
5915 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5918 status = resolve_dfspath_wcard(ctx, conn,
5919 req->flags2 & FLAGS2_DFS_PATHNAMES,
5923 if (!NT_STATUS_IS_OK(status)) {
5927 /* Check the new name has no '/' characters. */
5928 if (strchr_m(newname, '/')) {
5929 return NT_STATUS_NOT_SUPPORTED;
5932 if (fsp && fsp->base_fsp) {
5933 /* newname must be a stream name. */
5934 if (newname[0] != ':') {
5935 return NT_STATUS_NOT_SUPPORTED;
5938 /* Create an smb_fname to call rename_internals_fsp() with. */
5939 status = create_synthetic_smb_fname(talloc_tos(),
5940 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5942 if (!NT_STATUS_IS_OK(status)) {
5947 * Set the original last component, since
5948 * rename_internals_fsp() requires it.
5950 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5952 if (smb_fname_dst->original_lcomp == NULL) {
5953 status = NT_STATUS_NO_MEMORY;
5959 * Build up an smb_fname_dst based on the filename passed in.
5960 * We basically just strip off the last component, and put on
5961 * the newname instead.
5963 char *base_name = NULL;
5965 /* newname must *not* be a stream name. */
5966 if (newname[0] == ':') {
5967 return NT_STATUS_NOT_SUPPORTED;
5971 * Strip off the last component (filename) of the path passed
5974 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5976 return NT_STATUS_NO_MEMORY;
5978 p = strrchr_m(base_name, '/');
5982 base_name = talloc_strdup(ctx, "./");
5984 return NT_STATUS_NO_MEMORY;
5987 /* Append the new name. */
5988 base_name = talloc_asprintf_append(base_name,
5992 return NT_STATUS_NO_MEMORY;
5995 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
5998 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6001 /* If an error we expect this to be
6002 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6004 if (!NT_STATUS_IS_OK(status)) {
6005 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6009 /* Create an smb_fname to call rename_internals_fsp() */
6010 status = create_synthetic_smb_fname(ctx,
6014 if (!NT_STATUS_IS_OK(status)) {
6021 DEBUG(10,("smb_file_rename_information: "
6022 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6023 fsp->fnum, fsp_str_dbg(fsp),
6024 smb_fname_str_dbg(smb_fname_dst)));
6025 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6028 DEBUG(10,("smb_file_rename_information: "
6029 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6030 smb_fname_str_dbg(smb_fname_src),
6031 smb_fname_str_dbg(smb_fname_dst)));
6032 status = rename_internals(ctx, conn, req, smb_fname_src,
6033 smb_fname_dst, 0, overwrite, false,
6035 FILE_WRITE_ATTRIBUTES);
6038 TALLOC_FREE(smb_fname_dst);
6042 /****************************************************************************
6043 Deal with SMB_SET_POSIX_ACL.
6044 ****************************************************************************/
6046 #if defined(HAVE_POSIX_ACLS)
6047 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6051 const struct smb_filename *smb_fname)
6053 uint16 posix_acl_version;
6054 uint16 num_file_acls;
6055 uint16 num_def_acls;
6056 bool valid_file_acls = True;
6057 bool valid_def_acls = True;
6059 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6060 return NT_STATUS_INVALID_PARAMETER;
6062 posix_acl_version = SVAL(pdata,0);
6063 num_file_acls = SVAL(pdata,2);
6064 num_def_acls = SVAL(pdata,4);
6066 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6067 valid_file_acls = False;
6071 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6072 valid_def_acls = False;
6076 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6077 return NT_STATUS_INVALID_PARAMETER;
6080 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6081 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6082 return NT_STATUS_INVALID_PARAMETER;
6085 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6086 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6087 (unsigned int)num_file_acls,
6088 (unsigned int)num_def_acls));
6090 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6091 smb_fname->base_name, num_file_acls,
6092 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6093 return map_nt_error_from_unix(errno);
6096 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6097 smb_fname->base_name, &smb_fname->st, num_def_acls,
6098 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6099 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6100 return map_nt_error_from_unix(errno);
6102 return NT_STATUS_OK;
6106 /****************************************************************************
6107 Deal with SMB_SET_POSIX_LOCK.
6108 ****************************************************************************/
6110 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6111 struct smb_request *req,
6119 bool blocking_lock = False;
6120 enum brl_type lock_type;
6122 NTSTATUS status = NT_STATUS_OK;
6124 if (fsp == NULL || fsp->fh->fd == -1) {
6125 return NT_STATUS_INVALID_HANDLE;
6128 if (total_data != POSIX_LOCK_DATA_SIZE) {
6129 return NT_STATUS_INVALID_PARAMETER;
6132 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6133 case POSIX_LOCK_TYPE_READ:
6134 lock_type = READ_LOCK;
6136 case POSIX_LOCK_TYPE_WRITE:
6137 /* Return the right POSIX-mappable error code for files opened read-only. */
6138 if (!fsp->can_write) {
6139 return NT_STATUS_INVALID_HANDLE;
6141 lock_type = WRITE_LOCK;
6143 case POSIX_LOCK_TYPE_UNLOCK:
6144 lock_type = UNLOCK_LOCK;
6147 return NT_STATUS_INVALID_PARAMETER;
6150 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6151 blocking_lock = False;
6152 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6153 blocking_lock = True;
6155 return NT_STATUS_INVALID_PARAMETER;
6158 if (!lp_blocking_locks(SNUM(conn))) {
6159 blocking_lock = False;
6162 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6163 #if defined(HAVE_LONGLONG)
6164 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6165 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6166 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6167 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6168 #else /* HAVE_LONGLONG */
6169 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6170 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6171 #endif /* HAVE_LONGLONG */
6173 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6174 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6176 (unsigned int)lock_type,
6177 (unsigned int)lock_pid,
6181 if (lock_type == UNLOCK_LOCK) {
6182 status = do_unlock(smbd_messaging_context(),
6189 uint32 block_smbpid;
6191 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6203 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6205 * A blocking lock was requested. Package up
6206 * this smb into a queued request and push it
6207 * onto the blocking lock queue.
6209 if(push_blocking_lock_request(br_lck,
6212 -1, /* infinite timeout. */
6220 TALLOC_FREE(br_lck);
6224 TALLOC_FREE(br_lck);
6230 /****************************************************************************
6231 Deal with SMB_SET_FILE_BASIC_INFO.
6232 ****************************************************************************/
6234 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6238 const struct smb_filename *smb_fname)
6240 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6241 struct smb_file_time ft;
6243 NTSTATUS status = NT_STATUS_OK;
6247 if (total_data < 36) {
6248 return NT_STATUS_INVALID_PARAMETER;
6251 /* Set the attributes */
6252 dosmode = IVAL(pdata,32);
6253 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6254 if (!NT_STATUS_IS_OK(status)) {
6259 ft.create_time = interpret_long_date(pdata);
6262 ft.atime = interpret_long_date(pdata+8);
6265 ft.mtime = interpret_long_date(pdata+16);
6268 ft.ctime = interpret_long_date(pdata+24);
6270 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6271 smb_fname_str_dbg(smb_fname)));
6273 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6277 /****************************************************************************
6278 Deal with SMB_INFO_STANDARD.
6279 ****************************************************************************/
6281 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6285 const struct smb_filename *smb_fname)
6287 struct smb_file_time ft;
6291 if (total_data < 12) {
6292 return NT_STATUS_INVALID_PARAMETER;
6296 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6298 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6300 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6302 DEBUG(10,("smb_set_info_standard: file %s\n",
6303 smb_fname_str_dbg(smb_fname)));
6305 return smb_set_file_time(conn,
6312 /****************************************************************************
6313 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6314 ****************************************************************************/
6316 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6317 struct smb_request *req,
6321 struct smb_filename *smb_fname)
6323 uint64_t allocation_size = 0;
6324 NTSTATUS status = NT_STATUS_OK;
6325 files_struct *new_fsp = NULL;
6327 if (!VALID_STAT(smb_fname->st)) {
6328 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6331 if (total_data < 8) {
6332 return NT_STATUS_INVALID_PARAMETER;
6335 allocation_size = (uint64_t)IVAL(pdata,0);
6336 #ifdef LARGE_SMB_OFF_T
6337 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6338 #else /* LARGE_SMB_OFF_T */
6339 if (IVAL(pdata,4) != 0) {
6340 /* more than 32 bits? */
6341 return NT_STATUS_INVALID_PARAMETER;
6343 #endif /* LARGE_SMB_OFF_T */
6345 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6346 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6347 (double)allocation_size));
6349 if (allocation_size) {
6350 allocation_size = smb_roundup(conn, allocation_size);
6353 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6354 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6355 (double)allocation_size));
6357 if (fsp && fsp->fh->fd != -1) {
6358 /* Open file handle. */
6359 /* Only change if needed. */
6360 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6361 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6362 return map_nt_error_from_unix(errno);
6365 /* But always update the time. */
6367 * This is equivalent to a write. Ensure it's seen immediately
6368 * if there are no pending writes.
6370 trigger_write_time_update_immediate(fsp);
6371 return NT_STATUS_OK;
6374 /* Pathname or stat or directory file. */
6375 status = SMB_VFS_CREATE_FILE(
6378 0, /* root_dir_fid */
6379 smb_fname, /* fname */
6380 FILE_WRITE_DATA, /* access_mask */
6381 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6383 FILE_OPEN, /* create_disposition*/
6384 0, /* create_options */
6385 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6386 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6387 0, /* allocation_size */
6390 &new_fsp, /* result */
6393 if (!NT_STATUS_IS_OK(status)) {
6394 /* NB. We check for open_was_deferred in the caller. */
6398 /* Only change if needed. */
6399 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6400 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6401 status = map_nt_error_from_unix(errno);
6402 close_file(req, new_fsp, NORMAL_CLOSE);
6407 /* Changing the allocation size should set the last mod time. */
6409 * This is equivalent to a write. Ensure it's seen immediately
6410 * if there are no pending writes.
6412 trigger_write_time_update_immediate(new_fsp);
6414 close_file(req, new_fsp, NORMAL_CLOSE);
6415 return NT_STATUS_OK;
6418 /****************************************************************************
6419 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6420 ****************************************************************************/
6422 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6423 struct smb_request *req,
6427 const struct smb_filename *smb_fname)
6431 if (total_data < 8) {
6432 return NT_STATUS_INVALID_PARAMETER;
6435 size = IVAL(pdata,0);
6436 #ifdef LARGE_SMB_OFF_T
6437 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6438 #else /* LARGE_SMB_OFF_T */
6439 if (IVAL(pdata,4) != 0) {
6440 /* more than 32 bits? */
6441 return NT_STATUS_INVALID_PARAMETER;
6443 #endif /* LARGE_SMB_OFF_T */
6444 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6445 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6448 return smb_set_file_size(conn, req,
6455 /****************************************************************************
6456 Allow a UNIX info mknod.
6457 ****************************************************************************/
6459 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6462 const struct smb_filename *smb_fname)
6464 uint32 file_type = IVAL(pdata,56);
6465 #if defined(HAVE_MAKEDEV)
6466 uint32 dev_major = IVAL(pdata,60);
6467 uint32 dev_minor = IVAL(pdata,68);
6469 SMB_DEV_T dev = (SMB_DEV_T)0;
6470 uint32 raw_unixmode = IVAL(pdata,84);
6474 if (total_data < 100) {
6475 return NT_STATUS_INVALID_PARAMETER;
6478 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6479 PERM_NEW_FILE, &unixmode);
6480 if (!NT_STATUS_IS_OK(status)) {
6484 #if defined(HAVE_MAKEDEV)
6485 dev = makedev(dev_major, dev_minor);
6488 switch (file_type) {
6489 #if defined(S_IFIFO)
6490 case UNIX_TYPE_FIFO:
6491 unixmode |= S_IFIFO;
6494 #if defined(S_IFSOCK)
6495 case UNIX_TYPE_SOCKET:
6496 unixmode |= S_IFSOCK;
6499 #if defined(S_IFCHR)
6500 case UNIX_TYPE_CHARDEV:
6501 unixmode |= S_IFCHR;
6504 #if defined(S_IFBLK)
6505 case UNIX_TYPE_BLKDEV:
6506 unixmode |= S_IFBLK;
6510 return NT_STATUS_INVALID_PARAMETER;
6513 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6514 "%.0f mode 0%o for file %s\n", (double)dev,
6515 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6517 /* Ok - do the mknod. */
6518 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6519 return map_nt_error_from_unix(errno);
6522 /* If any of the other "set" calls fail we
6523 * don't want to end up with a half-constructed mknod.
6526 if (lp_inherit_perms(SNUM(conn))) {
6528 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6530 return NT_STATUS_NO_MEMORY;
6532 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6534 TALLOC_FREE(parent);
6537 return NT_STATUS_OK;
6540 /****************************************************************************
6541 Deal with SMB_SET_FILE_UNIX_BASIC.
6542 ****************************************************************************/
6544 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6545 struct smb_request *req,
6549 const struct smb_filename *smb_fname)
6551 struct smb_file_time ft;
6552 uint32 raw_unixmode;
6555 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6556 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6557 NTSTATUS status = NT_STATUS_OK;
6558 bool delete_on_fail = False;
6559 enum perm_type ptype;
6560 files_struct *all_fsps = NULL;
6561 bool modify_mtime = true;
6563 SMB_STRUCT_STAT sbuf;
6567 if (total_data < 100) {
6568 return NT_STATUS_INVALID_PARAMETER;
6571 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6572 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6573 size=IVAL(pdata,0); /* first 8 Bytes are size */
6574 #ifdef LARGE_SMB_OFF_T
6575 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6576 #else /* LARGE_SMB_OFF_T */
6577 if (IVAL(pdata,4) != 0) {
6578 /* more than 32 bits? */
6579 return NT_STATUS_INVALID_PARAMETER;
6581 #endif /* LARGE_SMB_OFF_T */
6584 ft.atime = interpret_long_date(pdata+24); /* access_time */
6585 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6586 set_owner = (uid_t)IVAL(pdata,40);
6587 set_grp = (gid_t)IVAL(pdata,48);
6588 raw_unixmode = IVAL(pdata,84);
6590 if (VALID_STAT(smb_fname->st)) {
6591 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6592 ptype = PERM_EXISTING_DIR;
6594 ptype = PERM_EXISTING_FILE;
6597 ptype = PERM_NEW_FILE;
6600 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6602 if (!NT_STATUS_IS_OK(status)) {
6606 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6607 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6608 smb_fname_str_dbg(smb_fname), (double)size,
6609 (unsigned int)set_owner, (unsigned int)set_grp,
6610 (int)raw_unixmode));
6612 sbuf = smb_fname->st;
6614 if (!VALID_STAT(sbuf)) {
6615 struct smb_filename *smb_fname_tmp = NULL;
6617 * The only valid use of this is to create character and block
6618 * devices, and named pipes. This is deprecated (IMHO) and
6619 * a new info level should be used for mknod. JRA.
6622 status = smb_unix_mknod(conn,
6626 if (!NT_STATUS_IS_OK(status)) {
6630 status = copy_smb_filename(talloc_tos(), smb_fname,
6632 if (!NT_STATUS_IS_OK(status)) {
6636 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6637 status = map_nt_error_from_unix(errno);
6638 TALLOC_FREE(smb_fname_tmp);
6639 SMB_VFS_UNLINK(conn, smb_fname);
6643 sbuf = smb_fname_tmp->st;
6644 TALLOC_FREE(smb_fname_tmp);
6646 /* Ensure we don't try and change anything else. */
6647 raw_unixmode = SMB_MODE_NO_CHANGE;
6648 size = get_file_size_stat(&sbuf);
6649 ft.atime = sbuf.st_ex_atime;
6650 ft.mtime = sbuf.st_ex_mtime;
6652 * We continue here as we might want to change the
6655 delete_on_fail = True;
6659 /* Horrible backwards compatibility hack as an old server bug
6660 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6664 size = get_file_size_stat(&sbuf);
6669 * Deal with the UNIX specific mode set.
6672 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6673 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6674 "setting mode 0%o for file %s\n",
6675 (unsigned int)unixmode,
6676 smb_fname_str_dbg(smb_fname)));
6677 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6678 return map_nt_error_from_unix(errno);
6683 * Deal with the UNIX specific uid set.
6686 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6687 (sbuf.st_ex_uid != set_owner)) {
6690 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6691 "changing owner %u for path %s\n",
6692 (unsigned int)set_owner,
6693 smb_fname_str_dbg(smb_fname)));
6695 if (S_ISLNK(sbuf.st_ex_mode)) {
6696 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6697 set_owner, (gid_t)-1);
6699 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6700 set_owner, (gid_t)-1);
6704 status = map_nt_error_from_unix(errno);
6705 if (delete_on_fail) {
6706 SMB_VFS_UNLINK(conn, smb_fname);
6713 * Deal with the UNIX specific gid set.
6716 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6717 (sbuf.st_ex_gid != set_grp)) {
6718 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6719 "changing group %u for file %s\n",
6720 (unsigned int)set_owner,
6721 smb_fname_str_dbg(smb_fname)));
6722 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6724 status = map_nt_error_from_unix(errno);
6725 if (delete_on_fail) {
6726 SMB_VFS_UNLINK(conn, smb_fname);
6732 /* Deal with any size changes. */
6734 status = smb_set_file_size(conn, req,
6739 if (!NT_STATUS_IS_OK(status)) {
6743 /* Deal with any time changes. */
6744 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6745 /* No change, don't cancel anything. */
6749 id = vfs_file_id_from_sbuf(conn, &sbuf);
6750 for(all_fsps = file_find_di_first(id); all_fsps;
6751 all_fsps = file_find_di_next(all_fsps)) {
6753 * We're setting the time explicitly for UNIX.
6754 * Cancel any pending changes over all handles.
6756 all_fsps->update_write_time_on_close = false;
6757 TALLOC_FREE(all_fsps->update_write_time_event);
6761 * Override the "setting_write_time"
6762 * parameter here as it almost does what
6763 * we need. Just remember if we modified
6764 * mtime and send the notify ourselves.
6766 if (null_timespec(ft.mtime)) {
6767 modify_mtime = false;
6770 status = smb_set_file_time(conn,
6776 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6777 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6782 /****************************************************************************
6783 Deal with SMB_SET_FILE_UNIX_INFO2.
6784 ****************************************************************************/
6786 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6787 struct smb_request *req,
6791 const struct smb_filename *smb_fname)
6797 if (total_data < 116) {
6798 return NT_STATUS_INVALID_PARAMETER;
6801 /* Start by setting all the fields that are common between UNIX_BASIC
6804 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6806 if (!NT_STATUS_IS_OK(status)) {
6810 smb_fflags = IVAL(pdata, 108);
6811 smb_fmask = IVAL(pdata, 112);
6813 /* NB: We should only attempt to alter the file flags if the client
6814 * sends a non-zero mask.
6816 if (smb_fmask != 0) {
6817 int stat_fflags = 0;
6819 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6820 smb_fmask, &stat_fflags)) {
6821 /* Client asked to alter a flag we don't understand. */
6822 return NT_STATUS_INVALID_PARAMETER;
6825 if (fsp && fsp->fh->fd != -1) {
6826 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6827 return NT_STATUS_NOT_SUPPORTED;
6829 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6830 stat_fflags) != 0) {
6831 return map_nt_error_from_unix(errno);
6836 /* XXX: need to add support for changing the create_time here. You
6837 * can do this for paths on Darwin with setattrlist(2). The right way
6838 * to hook this up is probably by extending the VFS utimes interface.
6841 return NT_STATUS_OK;
6844 /****************************************************************************
6845 Create a directory with POSIX semantics.
6846 ****************************************************************************/
6848 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6849 struct smb_request *req,
6852 struct smb_filename *smb_fname,
6853 int *pdata_return_size)
6855 NTSTATUS status = NT_STATUS_OK;
6856 uint32 raw_unixmode = 0;
6857 uint32 mod_unixmode = 0;
6858 mode_t unixmode = (mode_t)0;
6859 files_struct *fsp = NULL;
6860 uint16 info_level_return = 0;
6862 char *pdata = *ppdata;
6864 if (total_data < 18) {
6865 return NT_STATUS_INVALID_PARAMETER;
6868 raw_unixmode = IVAL(pdata,8);
6869 /* Next 4 bytes are not yet defined. */
6871 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6872 PERM_NEW_DIR, &unixmode);
6873 if (!NT_STATUS_IS_OK(status)) {
6877 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6879 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6880 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6882 status = SMB_VFS_CREATE_FILE(
6885 0, /* root_dir_fid */
6886 smb_fname, /* fname */
6887 FILE_READ_ATTRIBUTES, /* access_mask */
6888 FILE_SHARE_NONE, /* share_access */
6889 FILE_CREATE, /* create_disposition*/
6890 FILE_DIRECTORY_FILE, /* create_options */
6891 mod_unixmode, /* file_attributes */
6892 0, /* oplock_request */
6893 0, /* allocation_size */
6899 if (NT_STATUS_IS_OK(status)) {
6900 close_file(req, fsp, NORMAL_CLOSE);
6903 info_level_return = SVAL(pdata,16);
6905 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6906 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6907 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6908 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6910 *pdata_return_size = 12;
6913 /* Realloc the data size */
6914 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6915 if (*ppdata == NULL) {
6916 *pdata_return_size = 0;
6917 return NT_STATUS_NO_MEMORY;
6921 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6922 SSVAL(pdata,2,0); /* No fnum. */
6923 SIVAL(pdata,4,info); /* Was directory created. */
6925 switch (info_level_return) {
6926 case SMB_QUERY_FILE_UNIX_BASIC:
6927 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6928 SSVAL(pdata,10,0); /* Padding. */
6929 store_file_unix_basic(conn, pdata + 12, fsp,
6932 case SMB_QUERY_FILE_UNIX_INFO2:
6933 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6934 SSVAL(pdata,10,0); /* Padding. */
6935 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6939 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6940 SSVAL(pdata,10,0); /* Padding. */
6947 /****************************************************************************
6948 Open/Create a file with POSIX semantics.
6949 ****************************************************************************/
6951 static NTSTATUS smb_posix_open(connection_struct *conn,
6952 struct smb_request *req,
6955 struct smb_filename *smb_fname,
6956 int *pdata_return_size)
6958 bool extended_oplock_granted = False;
6959 char *pdata = *ppdata;
6961 uint32 wire_open_mode = 0;
6962 uint32 raw_unixmode = 0;
6963 uint32 mod_unixmode = 0;
6964 uint32 create_disp = 0;
6965 uint32 access_mask = 0;
6966 uint32 create_options = 0;
6967 NTSTATUS status = NT_STATUS_OK;
6968 mode_t unixmode = (mode_t)0;
6969 files_struct *fsp = NULL;
6970 int oplock_request = 0;
6972 uint16 info_level_return = 0;
6974 if (total_data < 18) {
6975 return NT_STATUS_INVALID_PARAMETER;
6978 flags = IVAL(pdata,0);
6979 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6980 if (oplock_request) {
6981 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6984 wire_open_mode = IVAL(pdata,4);
6986 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6987 return smb_posix_mkdir(conn, req,
6994 switch (wire_open_mode & SMB_ACCMODE) {
6996 access_mask = FILE_READ_DATA;
6999 access_mask = FILE_WRITE_DATA;
7002 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7005 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7006 (unsigned int)wire_open_mode ));
7007 return NT_STATUS_INVALID_PARAMETER;
7010 wire_open_mode &= ~SMB_ACCMODE;
7012 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7013 create_disp = FILE_CREATE;
7014 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7015 create_disp = FILE_OVERWRITE_IF;
7016 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7017 create_disp = FILE_OPEN_IF;
7018 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7019 create_disp = FILE_OPEN;
7021 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7022 (unsigned int)wire_open_mode ));
7023 return NT_STATUS_INVALID_PARAMETER;
7026 raw_unixmode = IVAL(pdata,8);
7027 /* Next 4 bytes are not yet defined. */
7029 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7030 (VALID_STAT(smb_fname->st) ?
7031 PERM_EXISTING_FILE : PERM_NEW_FILE),
7034 if (!NT_STATUS_IS_OK(status)) {
7038 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7040 if (wire_open_mode & SMB_O_SYNC) {
7041 create_options |= FILE_WRITE_THROUGH;
7043 if (wire_open_mode & SMB_O_APPEND) {
7044 access_mask |= FILE_APPEND_DATA;
7046 if (wire_open_mode & SMB_O_DIRECT) {
7047 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7050 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7051 smb_fname_str_dbg(smb_fname),
7052 (unsigned int)wire_open_mode,
7053 (unsigned int)unixmode ));
7055 status = SMB_VFS_CREATE_FILE(
7058 0, /* root_dir_fid */
7059 smb_fname, /* fname */
7060 access_mask, /* access_mask */
7061 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7063 create_disp, /* create_disposition*/
7064 FILE_NON_DIRECTORY_FILE, /* create_options */
7065 mod_unixmode, /* file_attributes */
7066 oplock_request, /* oplock_request */
7067 0, /* allocation_size */
7073 if (!NT_STATUS_IS_OK(status)) {
7077 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7078 extended_oplock_granted = True;
7081 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7082 extended_oplock_granted = True;
7085 info_level_return = SVAL(pdata,16);
7087 /* Allocate the correct return size. */
7089 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7090 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7091 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7092 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7094 *pdata_return_size = 12;
7097 /* Realloc the data size */
7098 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7099 if (*ppdata == NULL) {
7100 close_file(req, fsp, ERROR_CLOSE);
7101 *pdata_return_size = 0;
7102 return NT_STATUS_NO_MEMORY;
7106 if (extended_oplock_granted) {
7107 if (flags & REQUEST_BATCH_OPLOCK) {
7108 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7110 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7112 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7113 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7115 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7118 SSVAL(pdata,2,fsp->fnum);
7119 SIVAL(pdata,4,info); /* Was file created etc. */
7121 switch (info_level_return) {
7122 case SMB_QUERY_FILE_UNIX_BASIC:
7123 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7124 SSVAL(pdata,10,0); /* padding. */
7125 store_file_unix_basic(conn, pdata + 12, fsp,
7128 case SMB_QUERY_FILE_UNIX_INFO2:
7129 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7130 SSVAL(pdata,10,0); /* padding. */
7131 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7135 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7136 SSVAL(pdata,10,0); /* padding. */
7139 return NT_STATUS_OK;
7142 /****************************************************************************
7143 Delete a file with POSIX semantics.
7144 ****************************************************************************/
7146 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7147 struct smb_request *req,
7150 struct smb_filename *smb_fname)
7152 NTSTATUS status = NT_STATUS_OK;
7153 files_struct *fsp = NULL;
7157 int create_options = 0;
7159 struct share_mode_lock *lck = NULL;
7161 if (total_data < 2) {
7162 return NT_STATUS_INVALID_PARAMETER;
7165 flags = SVAL(pdata,0);
7167 if (!VALID_STAT(smb_fname->st)) {
7168 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7171 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7172 !VALID_STAT_OF_DIR(smb_fname->st)) {
7173 return NT_STATUS_NOT_A_DIRECTORY;
7176 DEBUG(10,("smb_posix_unlink: %s %s\n",
7177 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7178 smb_fname_str_dbg(smb_fname)));
7180 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7181 create_options |= FILE_DIRECTORY_FILE;
7184 status = SMB_VFS_CREATE_FILE(
7187 0, /* root_dir_fid */
7188 smb_fname, /* fname */
7189 DELETE_ACCESS, /* access_mask */
7190 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7192 FILE_OPEN, /* create_disposition*/
7193 create_options, /* create_options */
7194 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7195 0, /* oplock_request */
7196 0, /* allocation_size */
7202 if (!NT_STATUS_IS_OK(status)) {
7207 * Don't lie to client. If we can't really delete due to
7208 * non-POSIX opens return SHARING_VIOLATION.
7211 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7214 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7215 "lock for file %s\n", fsp_str_dbg(fsp)));
7216 close_file(req, fsp, NORMAL_CLOSE);
7217 return NT_STATUS_INVALID_PARAMETER;
7221 * See if others still have the file open. If this is the case, then
7222 * don't delete. If all opens are POSIX delete we can set the delete
7223 * on close disposition.
7225 for (i=0; i<lck->num_share_modes; i++) {
7226 struct share_mode_entry *e = &lck->share_modes[i];
7227 if (is_valid_share_mode_entry(e)) {
7228 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7231 /* Fail with sharing violation. */
7232 close_file(req, fsp, NORMAL_CLOSE);
7234 return NT_STATUS_SHARING_VIOLATION;
7239 * Set the delete on close.
7241 status = smb_set_file_disposition_info(conn,
7247 if (!NT_STATUS_IS_OK(status)) {
7248 close_file(req, fsp, NORMAL_CLOSE);
7253 return close_file(req, fsp, NORMAL_CLOSE);
7256 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7257 struct smb_request *req,
7258 TALLOC_CTX *mem_ctx,
7259 uint16_t info_level,
7261 struct smb_filename *smb_fname,
7262 char **ppdata, int total_data,
7265 char *pdata = *ppdata;
7266 NTSTATUS status = NT_STATUS_OK;
7267 int data_return_size = 0;
7271 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7272 return NT_STATUS_INVALID_LEVEL;
7275 if (!CAN_WRITE(conn)) {
7276 /* Allow POSIX opens. The open path will deny
7277 * any non-readonly opens. */
7278 if (info_level != SMB_POSIX_PATH_OPEN) {
7279 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7283 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7284 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7285 fsp ? fsp->fnum : -1, info_level, total_data));
7287 switch (info_level) {
7289 case SMB_INFO_STANDARD:
7291 status = smb_set_info_standard(conn,
7299 case SMB_INFO_SET_EA:
7301 status = smb_info_set_ea(conn,
7309 case SMB_SET_FILE_BASIC_INFO:
7310 case SMB_FILE_BASIC_INFORMATION:
7312 status = smb_set_file_basic_info(conn,
7320 case SMB_FILE_ALLOCATION_INFORMATION:
7321 case SMB_SET_FILE_ALLOCATION_INFO:
7323 status = smb_set_file_allocation_info(conn, req,
7331 case SMB_FILE_END_OF_FILE_INFORMATION:
7332 case SMB_SET_FILE_END_OF_FILE_INFO:
7334 status = smb_set_file_end_of_file_info(conn, req,
7342 case SMB_FILE_DISPOSITION_INFORMATION:
7343 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7346 /* JRA - We used to just ignore this on a path ?
7347 * Shouldn't this be invalid level on a pathname
7350 if (tran_call != TRANSACT2_SETFILEINFO) {
7351 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7354 status = smb_set_file_disposition_info(conn,
7362 case SMB_FILE_POSITION_INFORMATION:
7364 status = smb_file_position_information(conn,
7371 /* From tridge Samba4 :
7372 * MODE_INFORMATION in setfileinfo (I have no
7373 * idea what "mode information" on a file is - it takes a value of 0,
7374 * 2, 4 or 6. What could it be?).
7377 case SMB_FILE_MODE_INFORMATION:
7379 status = smb_file_mode_information(conn,
7386 * CIFS UNIX extensions.
7389 case SMB_SET_FILE_UNIX_BASIC:
7391 status = smb_set_file_unix_basic(conn, req,
7399 case SMB_SET_FILE_UNIX_INFO2:
7401 status = smb_set_file_unix_info2(conn, req,
7409 case SMB_SET_FILE_UNIX_LINK:
7412 /* We must have a pathname for this. */
7413 return NT_STATUS_INVALID_LEVEL;
7415 status = smb_set_file_unix_link(conn, req, pdata,
7416 total_data, smb_fname);
7420 case SMB_SET_FILE_UNIX_HLINK:
7423 /* We must have a pathname for this. */
7424 return NT_STATUS_INVALID_LEVEL;
7426 status = smb_set_file_unix_hlink(conn, req,
7432 case SMB_FILE_RENAME_INFORMATION:
7434 status = smb_file_rename_information(conn, req,
7440 #if defined(HAVE_POSIX_ACLS)
7441 case SMB_SET_POSIX_ACL:
7443 status = smb_set_posix_acl(conn,
7452 case SMB_SET_POSIX_LOCK:
7455 return NT_STATUS_INVALID_LEVEL;
7457 status = smb_set_posix_lock(conn, req,
7458 pdata, total_data, fsp);
7462 case SMB_POSIX_PATH_OPEN:
7465 /* We must have a pathname for this. */
7466 return NT_STATUS_INVALID_LEVEL;
7469 status = smb_posix_open(conn, req,
7477 case SMB_POSIX_PATH_UNLINK:
7480 /* We must have a pathname for this. */
7481 return NT_STATUS_INVALID_LEVEL;
7484 status = smb_posix_unlink(conn, req,
7492 return NT_STATUS_INVALID_LEVEL;
7495 if (!NT_STATUS_IS_OK(status)) {
7499 *ret_data_size = data_return_size;
7500 return NT_STATUS_OK;
7503 /****************************************************************************
7504 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7505 ****************************************************************************/
7507 static void call_trans2setfilepathinfo(connection_struct *conn,
7508 struct smb_request *req,
7509 unsigned int tran_call,
7510 char **pparams, int total_params,
7511 char **ppdata, int total_data,
7512 unsigned int max_data_bytes)
7514 char *params = *pparams;
7515 char *pdata = *ppdata;
7517 struct smb_filename *smb_fname = NULL;
7518 files_struct *fsp = NULL;
7519 NTSTATUS status = NT_STATUS_OK;
7520 int data_return_size = 0;
7523 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7527 if (tran_call == TRANSACT2_SETFILEINFO) {
7528 if (total_params < 4) {
7529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7533 fsp = file_fsp(req, SVAL(params,0));
7534 /* Basic check for non-null fsp. */
7535 if (!check_fsp_open(conn, req, fsp)) {
7538 info_level = SVAL(params,2);
7540 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7542 if (!NT_STATUS_IS_OK(status)) {
7543 reply_nterror(req, status);
7547 if(fsp->is_directory || fsp->fh->fd == -1) {
7549 * This is actually a SETFILEINFO on a directory
7550 * handle (returned from an NT SMB). NT5.0 seems
7551 * to do this call. JRA.
7553 if (INFO_LEVEL_IS_UNIX(info_level)) {
7554 /* Always do lstat for UNIX calls. */
7555 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7556 DEBUG(3,("call_trans2setfilepathinfo: "
7557 "SMB_VFS_LSTAT of %s failed "
7559 smb_fname_str_dbg(smb_fname),
7561 reply_nterror(req, map_nt_error_from_unix(errno));
7565 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7566 DEBUG(3,("call_trans2setfilepathinfo: "
7567 "fileinfo of %s failed (%s)\n",
7568 smb_fname_str_dbg(smb_fname),
7570 reply_nterror(req, map_nt_error_from_unix(errno));
7574 } else if (fsp->print_file) {
7576 * Doing a DELETE_ON_CLOSE should cancel a print job.
7578 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7579 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7581 DEBUG(3,("call_trans2setfilepathinfo: "
7582 "Cancelling print job (%s)\n",
7586 send_trans2_replies(conn, req, params, 2,
7591 reply_doserror(req, ERRDOS, ERRbadpath);
7596 * Original code - this is an open file.
7598 if (!check_fsp(conn, req, fsp)) {
7602 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7603 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7604 "of fnum %d failed (%s)\n", fsp->fnum,
7606 reply_nterror(req, map_nt_error_from_unix(errno));
7614 if (total_params < 7) {
7615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7619 info_level = SVAL(params,0);
7620 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7621 total_params - 6, STR_TERMINATE,
7623 if (!NT_STATUS_IS_OK(status)) {
7624 reply_nterror(req, status);
7628 status = filename_convert(req, conn,
7629 req->flags2 & FLAGS2_DFS_PATHNAMES,
7634 if (!NT_STATUS_IS_OK(status)) {
7635 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7636 reply_botherror(req,
7637 NT_STATUS_PATH_NOT_COVERED,
7638 ERRSRV, ERRbadpath);
7641 reply_nterror(req, status);
7645 if (INFO_LEVEL_IS_UNIX(info_level)) {
7647 * For CIFS UNIX extensions the target name may not exist.
7650 /* Always do lstat for UNIX calls. */
7651 SMB_VFS_LSTAT(conn, smb_fname);
7653 } else if (!VALID_STAT(smb_fname->st) &&
7654 SMB_VFS_STAT(conn, smb_fname)) {
7655 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7657 smb_fname_str_dbg(smb_fname),
7659 reply_nterror(req, map_nt_error_from_unix(errno));
7664 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7665 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7666 fsp ? fsp->fnum : -1, info_level,total_data));
7668 /* Realloc the parameter size */
7669 *pparams = (char *)SMB_REALLOC(*pparams,2);
7670 if (*pparams == NULL) {
7671 reply_nterror(req, NT_STATUS_NO_MEMORY);
7678 status = smbd_do_setfilepathinfo(conn, req, req,
7684 if (!NT_STATUS_IS_OK(status)) {
7685 if (open_was_deferred(req->mid)) {
7686 /* We have re-scheduled this call. */
7689 if (blocking_lock_was_deferred(req->mid)) {
7690 /* We have re-scheduled this call. */
7693 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7694 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7695 ERRSRV, ERRbadpath);
7698 if (info_level == SMB_POSIX_PATH_OPEN) {
7699 reply_openerror(req, status);
7703 reply_nterror(req, status);
7707 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7713 /****************************************************************************
7714 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7715 ****************************************************************************/
7717 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7718 char **pparams, int total_params,
7719 char **ppdata, int total_data,
7720 unsigned int max_data_bytes)
7722 struct smb_filename *smb_dname = NULL;
7723 char *params = *pparams;
7724 char *pdata = *ppdata;
7725 char *directory = NULL;
7726 NTSTATUS status = NT_STATUS_OK;
7727 struct ea_list *ea_list = NULL;
7728 TALLOC_CTX *ctx = talloc_tos();
7730 if (!CAN_WRITE(conn)) {
7731 reply_doserror(req, ERRSRV, ERRaccess);
7735 if (total_params < 5) {
7736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7740 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7741 total_params - 4, STR_TERMINATE,
7743 if (!NT_STATUS_IS_OK(status)) {
7744 reply_nterror(req, status);
7748 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7750 status = filename_convert(ctx,
7752 req->flags2 & FLAGS2_DFS_PATHNAMES,
7758 if (!NT_STATUS_IS_OK(status)) {
7759 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7760 reply_botherror(req,
7761 NT_STATUS_PATH_NOT_COVERED,
7762 ERRSRV, ERRbadpath);
7765 reply_nterror(req, status);
7769 /* Any data in this call is an EA list. */
7770 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7771 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7776 * OS/2 workplace shell seems to send SET_EA requests of "null"
7777 * length (4 bytes containing IVAL 4).
7778 * They seem to have no effect. Bug #3212. JRA.
7781 if (total_data != 4) {
7782 if (total_data < 10) {
7783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7787 if (IVAL(pdata,0) > total_data) {
7788 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7789 IVAL(pdata,0), (unsigned int)total_data));
7790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7794 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7797 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7801 /* If total_data == 4 Windows doesn't care what values
7802 * are placed in that field, it just ignores them.
7803 * The System i QNTC IBM SMB client puts bad values here,
7804 * so ignore them. */
7806 status = create_directory(conn, req, smb_dname);
7808 if (!NT_STATUS_IS_OK(status)) {
7809 reply_nterror(req, status);
7813 /* Try and set any given EA. */
7815 status = set_ea(conn, NULL, smb_dname, ea_list);
7816 if (!NT_STATUS_IS_OK(status)) {
7817 reply_nterror(req, status);
7822 /* Realloc the parameter and data sizes */
7823 *pparams = (char *)SMB_REALLOC(*pparams,2);
7824 if(*pparams == NULL) {
7825 reply_nterror(req, NT_STATUS_NO_MEMORY);
7832 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7835 TALLOC_FREE(smb_dname);
7839 /****************************************************************************
7840 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7841 We don't actually do this - we just send a null response.
7842 ****************************************************************************/
7844 static void call_trans2findnotifyfirst(connection_struct *conn,
7845 struct smb_request *req,
7846 char **pparams, int total_params,
7847 char **ppdata, int total_data,
7848 unsigned int max_data_bytes)
7850 char *params = *pparams;
7853 if (total_params < 6) {
7854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7858 info_level = SVAL(params,4);
7859 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7861 switch (info_level) {
7866 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7870 /* Realloc the parameter and data sizes */
7871 *pparams = (char *)SMB_REALLOC(*pparams,6);
7872 if (*pparams == NULL) {
7873 reply_nterror(req, NT_STATUS_NO_MEMORY);
7878 SSVAL(params,0,fnf_handle);
7879 SSVAL(params,2,0); /* No changes */
7880 SSVAL(params,4,0); /* No EA errors */
7887 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7892 /****************************************************************************
7893 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7894 changes). Currently this does nothing.
7895 ****************************************************************************/
7897 static void call_trans2findnotifynext(connection_struct *conn,
7898 struct smb_request *req,
7899 char **pparams, int total_params,
7900 char **ppdata, int total_data,
7901 unsigned int max_data_bytes)
7903 char *params = *pparams;
7905 DEBUG(3,("call_trans2findnotifynext\n"));
7907 /* Realloc the parameter and data sizes */
7908 *pparams = (char *)SMB_REALLOC(*pparams,4);
7909 if (*pparams == NULL) {
7910 reply_nterror(req, NT_STATUS_NO_MEMORY);
7915 SSVAL(params,0,0); /* No changes */
7916 SSVAL(params,2,0); /* No EA errors */
7918 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7923 /****************************************************************************
7924 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7925 ****************************************************************************/
7927 static void call_trans2getdfsreferral(connection_struct *conn,
7928 struct smb_request *req,
7929 char **pparams, int total_params,
7930 char **ppdata, int total_data,
7931 unsigned int max_data_bytes)
7933 char *params = *pparams;
7934 char *pathname = NULL;
7936 int max_referral_level;
7937 NTSTATUS status = NT_STATUS_OK;
7938 TALLOC_CTX *ctx = talloc_tos();
7940 DEBUG(10,("call_trans2getdfsreferral\n"));
7942 if (total_params < 3) {
7943 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7947 max_referral_level = SVAL(params,0);
7949 if(!lp_host_msdfs()) {
7950 reply_doserror(req, ERRDOS, ERRbadfunc);
7954 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7955 total_params - 2, STR_TERMINATE);
7957 reply_nterror(req, NT_STATUS_NOT_FOUND);
7960 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7961 ppdata,&status)) < 0) {
7962 reply_nterror(req, status);
7966 SSVAL(req->inbuf, smb_flg2,
7967 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7968 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7973 #define LMCAT_SPL 0x53
7974 #define LMFUNC_GETJOBID 0x60
7976 /****************************************************************************
7977 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7978 ****************************************************************************/
7980 static void call_trans2ioctl(connection_struct *conn,
7981 struct smb_request *req,
7982 char **pparams, int total_params,
7983 char **ppdata, int total_data,
7984 unsigned int max_data_bytes)
7986 char *pdata = *ppdata;
7987 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7989 /* check for an invalid fid before proceeding */
7992 reply_doserror(req, ERRDOS, ERRbadfid);
7996 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7997 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7998 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7999 if (*ppdata == NULL) {
8000 reply_nterror(req, NT_STATUS_NO_MEMORY);
8005 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8006 CAN ACCEPT THIS IN UNICODE. JRA. */
8008 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8009 srvstr_push(pdata, req->flags2, pdata + 2,
8010 global_myname(), 15,
8011 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8012 srvstr_push(pdata, req->flags2, pdata+18,
8013 lp_servicename(SNUM(conn)), 13,
8014 STR_ASCII|STR_TERMINATE); /* Service name */
8015 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8020 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8021 reply_doserror(req, ERRSRV, ERRerror);
8024 /****************************************************************************
8025 Reply to a SMBfindclose (stop trans2 directory search).
8026 ****************************************************************************/
8028 void reply_findclose(struct smb_request *req)
8031 struct smbd_server_connection *sconn = smbd_server_conn;
8033 START_PROFILE(SMBfindclose);
8036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8037 END_PROFILE(SMBfindclose);
8041 dptr_num = SVALS(req->vwv+0, 0);
8043 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8045 dptr_close(sconn, &dptr_num);
8047 reply_outbuf(req, 0, 0);
8049 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8051 END_PROFILE(SMBfindclose);
8055 /****************************************************************************
8056 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8057 ****************************************************************************/
8059 void reply_findnclose(struct smb_request *req)
8063 START_PROFILE(SMBfindnclose);
8066 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8067 END_PROFILE(SMBfindnclose);
8071 dptr_num = SVAL(req->vwv+0, 0);
8073 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8075 /* We never give out valid handles for a
8076 findnotifyfirst - so any dptr_num is ok here.
8079 reply_outbuf(req, 0, 0);
8081 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8083 END_PROFILE(SMBfindnclose);
8087 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8088 struct trans_state *state)
8090 if (Protocol >= PROTOCOL_NT1) {
8091 req->flags2 |= 0x40; /* IS_LONG_NAME */
8092 SSVAL(req->inbuf,smb_flg2,req->flags2);
8095 if (conn->encrypt_level == Required && !req->encrypted) {
8096 if (state->call != TRANSACT2_QFSINFO &&
8097 state->call != TRANSACT2_SETFSINFO) {
8098 DEBUG(0,("handle_trans2: encryption required "
8100 (unsigned int)state->call));
8101 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8106 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8108 /* Now we must call the relevant TRANS2 function */
8109 switch(state->call) {
8110 case TRANSACT2_OPEN:
8112 START_PROFILE(Trans2_open);
8113 call_trans2open(conn, req,
8114 &state->param, state->total_param,
8115 &state->data, state->total_data,
8116 state->max_data_return);
8117 END_PROFILE(Trans2_open);
8121 case TRANSACT2_FINDFIRST:
8123 START_PROFILE(Trans2_findfirst);
8124 call_trans2findfirst(conn, req,
8125 &state->param, state->total_param,
8126 &state->data, state->total_data,
8127 state->max_data_return);
8128 END_PROFILE(Trans2_findfirst);
8132 case TRANSACT2_FINDNEXT:
8134 START_PROFILE(Trans2_findnext);
8135 call_trans2findnext(conn, req,
8136 &state->param, state->total_param,
8137 &state->data, state->total_data,
8138 state->max_data_return);
8139 END_PROFILE(Trans2_findnext);
8143 case TRANSACT2_QFSINFO:
8145 START_PROFILE(Trans2_qfsinfo);
8146 call_trans2qfsinfo(conn, req,
8147 &state->param, state->total_param,
8148 &state->data, state->total_data,
8149 state->max_data_return);
8150 END_PROFILE(Trans2_qfsinfo);
8154 case TRANSACT2_SETFSINFO:
8156 START_PROFILE(Trans2_setfsinfo);
8157 call_trans2setfsinfo(conn, req,
8158 &state->param, state->total_param,
8159 &state->data, state->total_data,
8160 state->max_data_return);
8161 END_PROFILE(Trans2_setfsinfo);
8165 case TRANSACT2_QPATHINFO:
8166 case TRANSACT2_QFILEINFO:
8168 START_PROFILE(Trans2_qpathinfo);
8169 call_trans2qfilepathinfo(conn, req, state->call,
8170 &state->param, state->total_param,
8171 &state->data, state->total_data,
8172 state->max_data_return);
8173 END_PROFILE(Trans2_qpathinfo);
8177 case TRANSACT2_SETPATHINFO:
8178 case TRANSACT2_SETFILEINFO:
8180 START_PROFILE(Trans2_setpathinfo);
8181 call_trans2setfilepathinfo(conn, req, state->call,
8182 &state->param, state->total_param,
8183 &state->data, state->total_data,
8184 state->max_data_return);
8185 END_PROFILE(Trans2_setpathinfo);
8189 case TRANSACT2_FINDNOTIFYFIRST:
8191 START_PROFILE(Trans2_findnotifyfirst);
8192 call_trans2findnotifyfirst(conn, req,
8193 &state->param, state->total_param,
8194 &state->data, state->total_data,
8195 state->max_data_return);
8196 END_PROFILE(Trans2_findnotifyfirst);
8200 case TRANSACT2_FINDNOTIFYNEXT:
8202 START_PROFILE(Trans2_findnotifynext);
8203 call_trans2findnotifynext(conn, req,
8204 &state->param, state->total_param,
8205 &state->data, state->total_data,
8206 state->max_data_return);
8207 END_PROFILE(Trans2_findnotifynext);
8211 case TRANSACT2_MKDIR:
8213 START_PROFILE(Trans2_mkdir);
8214 call_trans2mkdir(conn, req,
8215 &state->param, state->total_param,
8216 &state->data, state->total_data,
8217 state->max_data_return);
8218 END_PROFILE(Trans2_mkdir);
8222 case TRANSACT2_GET_DFS_REFERRAL:
8224 START_PROFILE(Trans2_get_dfs_referral);
8225 call_trans2getdfsreferral(conn, req,
8226 &state->param, state->total_param,
8227 &state->data, state->total_data,
8228 state->max_data_return);
8229 END_PROFILE(Trans2_get_dfs_referral);
8233 case TRANSACT2_IOCTL:
8235 START_PROFILE(Trans2_ioctl);
8236 call_trans2ioctl(conn, req,
8237 &state->param, state->total_param,
8238 &state->data, state->total_data,
8239 state->max_data_return);
8240 END_PROFILE(Trans2_ioctl);
8245 /* Error in request */
8246 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8247 reply_doserror(req, ERRSRV,ERRerror);
8251 /****************************************************************************
8252 Reply to a SMBtrans2.
8253 ****************************************************************************/
8255 void reply_trans2(struct smb_request *req)
8257 connection_struct *conn = req->conn;
8262 unsigned int tran_call;
8263 struct trans_state *state;
8266 START_PROFILE(SMBtrans2);
8268 if (req->wct < 14) {
8269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8270 END_PROFILE(SMBtrans2);
8274 dsoff = SVAL(req->vwv+12, 0);
8275 dscnt = SVAL(req->vwv+11, 0);
8276 psoff = SVAL(req->vwv+10, 0);
8277 pscnt = SVAL(req->vwv+9, 0);
8278 tran_call = SVAL(req->vwv+14, 0);
8280 result = allow_new_trans(conn->pending_trans, req->mid);
8281 if (!NT_STATUS_IS_OK(result)) {
8282 DEBUG(2, ("Got invalid trans2 request: %s\n",
8283 nt_errstr(result)));
8284 reply_nterror(req, result);
8285 END_PROFILE(SMBtrans2);
8290 switch (tran_call) {
8291 /* List the allowed trans2 calls on IPC$ */
8292 case TRANSACT2_OPEN:
8293 case TRANSACT2_GET_DFS_REFERRAL:
8294 case TRANSACT2_QFILEINFO:
8295 case TRANSACT2_QFSINFO:
8296 case TRANSACT2_SETFSINFO:
8299 reply_doserror(req, ERRSRV, ERRaccess);
8300 END_PROFILE(SMBtrans2);
8305 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8306 DEBUG(0, ("talloc failed\n"));
8307 reply_nterror(req, NT_STATUS_NO_MEMORY);
8308 END_PROFILE(SMBtrans2);
8312 state->cmd = SMBtrans2;
8314 state->mid = req->mid;
8315 state->vuid = req->vuid;
8316 state->setup_count = SVAL(req->vwv+13, 0);
8317 state->setup = NULL;
8318 state->total_param = SVAL(req->vwv+0, 0);
8319 state->param = NULL;
8320 state->total_data = SVAL(req->vwv+1, 0);
8322 state->max_param_return = SVAL(req->vwv+2, 0);
8323 state->max_data_return = SVAL(req->vwv+3, 0);
8324 state->max_setup_return = SVAL(req->vwv+4, 0);
8325 state->close_on_completion = BITSETW(req->vwv+5, 0);
8326 state->one_way = BITSETW(req->vwv+5, 1);
8328 state->call = tran_call;
8330 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8331 is so as a sanity check */
8332 if (state->setup_count != 1) {
8334 * Need to have rc=0 for ioctl to get job id for OS/2.
8335 * Network printing will fail if function is not successful.
8336 * Similar function in reply.c will be used if protocol
8337 * is LANMAN1.0 instead of LM1.2X002.
8338 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8339 * outbuf doesn't have to be set(only job id is used).
8341 if ( (state->setup_count == 4)
8342 && (tran_call == TRANSACT2_IOCTL)
8343 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8344 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8345 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8347 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8348 DEBUG(2,("Transaction is %d\n",tran_call));
8350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8351 END_PROFILE(SMBtrans2);
8356 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8359 if (state->total_data) {
8361 if (trans_oob(state->total_data, 0, dscnt)
8362 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8366 /* Can't use talloc here, the core routines do realloc on the
8367 * params and data. */
8368 state->data = (char *)SMB_MALLOC(state->total_data);
8369 if (state->data == NULL) {
8370 DEBUG(0,("reply_trans2: data malloc fail for %u "
8371 "bytes !\n", (unsigned int)state->total_data));
8373 reply_nterror(req, NT_STATUS_NO_MEMORY);
8374 END_PROFILE(SMBtrans2);
8378 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8381 if (state->total_param) {
8383 if (trans_oob(state->total_param, 0, pscnt)
8384 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8388 /* Can't use talloc here, the core routines do realloc on the
8389 * params and data. */
8390 state->param = (char *)SMB_MALLOC(state->total_param);
8391 if (state->param == NULL) {
8392 DEBUG(0,("reply_trans: param malloc fail for %u "
8393 "bytes !\n", (unsigned int)state->total_param));
8394 SAFE_FREE(state->data);
8396 reply_nterror(req, NT_STATUS_NO_MEMORY);
8397 END_PROFILE(SMBtrans2);
8401 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8404 state->received_data = dscnt;
8405 state->received_param = pscnt;
8407 if ((state->received_param == state->total_param) &&
8408 (state->received_data == state->total_data)) {
8410 handle_trans2(conn, req, state);
8412 SAFE_FREE(state->data);
8413 SAFE_FREE(state->param);
8415 END_PROFILE(SMBtrans2);
8419 DLIST_ADD(conn->pending_trans, state);
8421 /* We need to send an interim response then receive the rest
8422 of the parameter/data bytes */
8423 reply_outbuf(req, 0, 0);
8424 show_msg((char *)req->outbuf);
8425 END_PROFILE(SMBtrans2);
8430 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8431 SAFE_FREE(state->data);
8432 SAFE_FREE(state->param);
8434 END_PROFILE(SMBtrans2);
8435 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8439 /****************************************************************************
8440 Reply to a SMBtranss2
8441 ****************************************************************************/
8443 void reply_transs2(struct smb_request *req)
8445 connection_struct *conn = req->conn;
8446 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8447 struct trans_state *state;
8449 START_PROFILE(SMBtranss2);
8451 show_msg((char *)req->inbuf);
8454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8455 END_PROFILE(SMBtranss2);
8459 for (state = conn->pending_trans; state != NULL;
8460 state = state->next) {
8461 if (state->mid == req->mid) {
8466 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8467 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8468 END_PROFILE(SMBtranss2);
8472 /* Revise state->total_param and state->total_data in case they have
8473 changed downwards */
8475 if (SVAL(req->vwv+0, 0) < state->total_param)
8476 state->total_param = SVAL(req->vwv+0, 0);
8477 if (SVAL(req->vwv+1, 0) < state->total_data)
8478 state->total_data = SVAL(req->vwv+1, 0);
8480 pcnt = SVAL(req->vwv+2, 0);
8481 poff = SVAL(req->vwv+3, 0);
8482 pdisp = SVAL(req->vwv+4, 0);
8484 dcnt = SVAL(req->vwv+5, 0);
8485 doff = SVAL(req->vwv+6, 0);
8486 ddisp = SVAL(req->vwv+7, 0);
8488 state->received_param += pcnt;
8489 state->received_data += dcnt;
8491 if ((state->received_data > state->total_data) ||
8492 (state->received_param > state->total_param))
8496 if (trans_oob(state->total_param, pdisp, pcnt)
8497 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8500 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8504 if (trans_oob(state->total_data, ddisp, dcnt)
8505 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8508 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8511 if ((state->received_param < state->total_param) ||
8512 (state->received_data < state->total_data)) {
8513 END_PROFILE(SMBtranss2);
8517 handle_trans2(conn, req, state);
8519 DLIST_REMOVE(conn->pending_trans, state);
8520 SAFE_FREE(state->data);
8521 SAFE_FREE(state->param);
8524 END_PROFILE(SMBtranss2);
8529 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8530 DLIST_REMOVE(conn->pending_trans, state);
8531 SAFE_FREE(state->data);
8532 SAFE_FREE(state->param);
8534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8535 END_PROFILE(SMBtranss2);