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,
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
247 *pnum_names = num_names;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list *ea_list_head = NULL;
266 if (!lp_ea_support(SNUM(conn))) {
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
285 listp = TALLOC_P(mem_ctx, struct ea_list);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
346 if (ea_list->ea.value.length > 65535) {
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
372 unsigned int total_data_size,
373 unsigned int *ret_data_size,
374 connection_struct *conn,
375 struct ea_list *ea_list)
377 uint8_t *p = (uint8_t *)pdata;
378 uint8_t *last_start = NULL;
382 if (!lp_ea_support(SNUM(conn))) {
383 return NT_STATUS_NO_EAS_ON_FILE;
386 for (; ea_list; ea_list = ea_list->next) {
392 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
396 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
397 dos_namelen = strlen(dos_ea_name);
398 if (dos_namelen > 255 || dos_namelen == 0) {
399 return NT_STATUS_INTERNAL_ERROR;
401 if (ea_list->ea.value.length > 65535) {
402 return NT_STATUS_INTERNAL_ERROR;
405 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
408 size_t pad = 4 - (this_size % 4);
412 if (this_size > total_data_size) {
413 return NT_STATUS_INFO_LENGTH_MISMATCH;
416 /* We know we have room. */
417 SIVAL(p, 0x00, 0); /* next offset */
418 SCVAL(p, 0x04, ea_list->ea.flags);
419 SCVAL(p, 0x05, dos_namelen);
420 SSVAL(p, 0x06, ea_list->ea.value.length);
421 fstrcpy((char *)(p+0x08), dos_ea_name);
422 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
424 total_data_size -= this_size;
428 *ret_data_size = PTR_DIFF(p, pdata);
429 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
433 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
435 size_t total_ea_len = 0;
436 TALLOC_CTX *mem_ctx = NULL;
438 if (!lp_ea_support(SNUM(conn))) {
441 mem_ctx = talloc_tos();
442 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
446 /****************************************************************************
447 Ensure the EA name is case insensitive by matching any existing EA name.
448 ****************************************************************************/
450 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
453 TALLOC_CTX *mem_ctx = talloc_tos();
454 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
456 for (; ea_list; ea_list = ea_list->next) {
457 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
458 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
459 &unix_ea_name[5], ea_list->ea.name));
460 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
466 /****************************************************************************
467 Set or delete an extended attribute.
468 ****************************************************************************/
470 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
471 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 status = get_full_smb_filename(talloc_tos(), smb_fname,
482 if (!NT_STATUS_IS_OK(status)) {
486 for (;ea_list; ea_list = ea_list->next) {
488 fstring unix_ea_name;
490 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
491 fstrcat(unix_ea_name, ea_list->ea.name);
493 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
495 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
497 if (samba_private_attr_name(unix_ea_name)) {
498 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
499 return NT_STATUS_ACCESS_DENIED;
502 if (ea_list->ea.value.length == 0) {
503 /* Remove the attribute. */
504 if (fsp && (fsp->fh->fd != -1)) {
505 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
506 unix_ea_name, fsp->fsp_name));
507 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
509 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
510 unix_ea_name, fname));
511 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
514 /* Removing a non existent attribute always succeeds. */
515 if (ret == -1 && errno == ENOATTR) {
516 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
522 if (fsp && (fsp->fh->fd != -1)) {
523 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
524 unix_ea_name, fsp->fsp_name));
525 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
526 ea_list->ea.value.data, ea_list->ea.value.length, 0);
528 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
529 unix_ea_name, fname));
530 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
531 ea_list->ea.value.data, ea_list->ea.value.length, 0);
537 if (errno == ENOTSUP) {
538 return NT_STATUS_EAS_NOT_SUPPORTED;
541 return map_nt_error_from_unix(errno);
547 /****************************************************************************
548 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
549 ****************************************************************************/
551 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
553 struct ea_list *ea_list_head = NULL;
554 size_t converted_size, offset = 0;
556 while (offset + 2 < data_size) {
557 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
558 unsigned int namelen = CVAL(pdata,offset);
560 offset++; /* Go past the namelen byte. */
562 /* integer wrap paranioa. */
563 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
564 (offset > data_size) || (namelen > data_size) ||
565 (offset + namelen >= data_size)) {
568 /* Ensure the name is null terminated. */
569 if (pdata[offset + namelen] != '\0') {
572 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
574 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
575 "failed: %s", strerror(errno)));
581 offset += (namelen + 1); /* Go past the name + terminating zero. */
582 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
583 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
589 /****************************************************************************
590 Read one EA list entry from the buffer.
591 ****************************************************************************/
593 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
595 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
597 unsigned int namelen;
598 size_t converted_size;
608 eal->ea.flags = CVAL(pdata,0);
609 namelen = CVAL(pdata,1);
610 val_len = SVAL(pdata,2);
612 if (4 + namelen + 1 + val_len > data_size) {
616 /* Ensure the name is null terminated. */
617 if (pdata[namelen + 4] != '\0') {
620 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
621 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
628 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
629 if (!eal->ea.value.data) {
633 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
635 /* Ensure we're null terminated just in case we print the value. */
636 eal->ea.value.data[val_len] = '\0';
637 /* But don't count the null. */
638 eal->ea.value.length--;
641 *pbytes_used = 4 + namelen + 1 + val_len;
644 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
645 dump_data(10, eal->ea.value.data, eal->ea.value.length);
650 /****************************************************************************
651 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
652 ****************************************************************************/
654 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
656 struct ea_list *ea_list_head = NULL;
658 size_t bytes_used = 0;
660 while (offset < data_size) {
661 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
667 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
668 offset += bytes_used;
674 /****************************************************************************
675 Count the total EA size needed.
676 ****************************************************************************/
678 static size_t ea_list_size(struct ea_list *ealist)
681 struct ea_list *listp;
684 for (listp = ealist; listp; listp = listp->next) {
685 push_ascii_fstring(dos_ea_name, listp->ea.name);
686 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
688 /* Add on 4 for total length. */
696 /****************************************************************************
697 Return a union of EA's from a file list and a list of names.
698 The TALLOC context for the two lists *MUST* be identical as we steal
699 memory from one list to add to another. JRA.
700 ****************************************************************************/
702 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
704 struct ea_list *nlistp, *flistp;
706 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
707 for (flistp = file_list; flistp; flistp = flistp->next) {
708 if (strequal(nlistp->ea.name, flistp->ea.name)) {
714 /* Copy the data from this entry. */
715 nlistp->ea.flags = flistp->ea.flags;
716 nlistp->ea.value = flistp->ea.value;
719 nlistp->ea.flags = 0;
720 ZERO_STRUCT(nlistp->ea.value);
724 *total_ea_len = ea_list_size(name_list);
728 /****************************************************************************
729 Send the required number of replies back.
730 We assume all fields other than the data fields are
731 set correctly for the type of call.
732 HACK ! Always assumes smb_setup field is zero.
733 ****************************************************************************/
735 void send_trans2_replies(connection_struct *conn,
736 struct smb_request *req,
743 /* As we are using a protocol > LANMAN1 then the max_send
744 variable must have been set in the sessetupX call.
745 This takes precedence over the max_xmit field in the
746 global struct. These different max_xmit variables should
747 be merged as this is now too confusing */
749 int data_to_send = datasize;
750 int params_to_send = paramsize;
752 const char *pp = params;
753 const char *pd = pdata;
754 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
755 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
756 int data_alignment_offset = 0;
757 bool overflow = False;
758 struct smbd_server_connection *sconn = smbd_server_conn;
759 int max_send = sconn->smb1.sessions.max_send;
761 /* Modify the data_to_send and datasize and set the error if
762 we're trying to send more than max_data_bytes. We still send
763 the part of the packet(s) that fit. Strange, but needed
766 if (max_data_bytes > 0 && datasize > max_data_bytes) {
767 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
768 max_data_bytes, datasize ));
769 datasize = data_to_send = max_data_bytes;
773 /* If there genuinely are no parameters or data to send just send the empty packet */
775 if(params_to_send == 0 && data_to_send == 0) {
776 reply_outbuf(req, 10, 0);
777 show_msg((char *)req->outbuf);
778 if (!srv_send_smb(smbd_server_fd(),
781 IS_CONN_ENCRYPTED(conn),
783 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
785 TALLOC_FREE(req->outbuf);
789 /* When sending params and data ensure that both are nicely aligned */
790 /* Only do this alignment when there is also data to send - else
791 can cause NT redirector problems. */
793 if (((params_to_send % 4) != 0) && (data_to_send != 0))
794 data_alignment_offset = 4 - (params_to_send % 4);
796 /* Space is bufsize minus Netbios over TCP header minus SMB header */
797 /* The alignment_offset is to align the param bytes on an even byte
798 boundary. NT 4.0 Beta needs this to work correctly. */
800 useable_space = max_send - (smb_size
803 + data_alignment_offset);
805 if (useable_space < 0) {
806 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
807 "= %d!!!", useable_space));
808 exit_server_cleanly("send_trans2_replies: Not enough space");
811 while (params_to_send || data_to_send) {
812 /* Calculate whether we will totally or partially fill this packet */
814 total_sent_thistime = params_to_send + data_to_send;
816 /* We can never send more than useable_space */
818 * Note that 'useable_space' does not include the alignment offsets,
819 * but we must include the alignment offsets in the calculation of
820 * the length of the data we send over the wire, as the alignment offsets
821 * are sent here. Fix from Marc_Jacobsen@hp.com.
824 total_sent_thistime = MIN(total_sent_thistime, useable_space);
826 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
827 + data_alignment_offset);
830 * We might have SMBtrans2s in req which was transferred to
831 * the outbuf, fix that.
833 SCVAL(req->outbuf, smb_com, SMBtrans2);
835 /* Set total params and data to be sent */
836 SSVAL(req->outbuf,smb_tprcnt,paramsize);
837 SSVAL(req->outbuf,smb_tdrcnt,datasize);
839 /* Calculate how many parameters and data we can fit into
840 * this packet. Parameters get precedence
843 params_sent_thistime = MIN(params_to_send,useable_space);
844 data_sent_thistime = useable_space - params_sent_thistime;
845 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
847 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
849 /* smb_proff is the offset from the start of the SMB header to the
850 parameter bytes, however the first 4 bytes of outbuf are
851 the Netbios over TCP header. Thus use smb_base() to subtract
852 them from the calculation */
854 SSVAL(req->outbuf,smb_proff,
855 ((smb_buf(req->outbuf)+alignment_offset)
856 - smb_base(req->outbuf)));
858 if(params_sent_thistime == 0)
859 SSVAL(req->outbuf,smb_prdisp,0);
861 /* Absolute displacement of param bytes sent in this packet */
862 SSVAL(req->outbuf,smb_prdisp,pp - params);
864 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
865 if(data_sent_thistime == 0) {
866 SSVAL(req->outbuf,smb_droff,0);
867 SSVAL(req->outbuf,smb_drdisp, 0);
869 /* The offset of the data bytes is the offset of the
870 parameter bytes plus the number of parameters being sent this time */
871 SSVAL(req->outbuf, smb_droff,
872 ((smb_buf(req->outbuf)+alignment_offset)
873 - smb_base(req->outbuf))
874 + params_sent_thistime + data_alignment_offset);
875 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
878 /* Initialize the padding for alignment */
880 if (alignment_offset != 0) {
881 memset(smb_buf(req->outbuf), 0, alignment_offset);
884 /* Copy the param bytes into the packet */
886 if(params_sent_thistime) {
887 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
888 params_sent_thistime);
891 /* Copy in the data bytes */
892 if(data_sent_thistime) {
893 if (data_alignment_offset != 0) {
894 memset((smb_buf(req->outbuf)+alignment_offset+
895 params_sent_thistime), 0,
896 data_alignment_offset);
898 memcpy(smb_buf(req->outbuf)+alignment_offset
899 +params_sent_thistime+data_alignment_offset,
900 pd,data_sent_thistime);
903 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
904 params_sent_thistime, data_sent_thistime, useable_space));
905 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
906 params_to_send, data_to_send, paramsize, datasize));
909 error_packet_set((char *)req->outbuf,
910 ERRDOS,ERRbufferoverflow,
911 STATUS_BUFFER_OVERFLOW,
915 /* Send the packet */
916 show_msg((char *)req->outbuf);
917 if (!srv_send_smb(smbd_server_fd(),
920 IS_CONN_ENCRYPTED(conn),
922 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
924 TALLOC_FREE(req->outbuf);
926 pp += params_sent_thistime;
927 pd += data_sent_thistime;
929 params_to_send -= params_sent_thistime;
930 data_to_send -= data_sent_thistime;
933 if(params_to_send < 0 || data_to_send < 0) {
934 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
935 params_to_send, data_to_send));
943 /****************************************************************************
944 Reply to a TRANSACT2_OPEN.
945 ****************************************************************************/
947 static void call_trans2open(connection_struct *conn,
948 struct smb_request *req,
949 char **pparams, int total_params,
950 char **ppdata, int total_data,
951 unsigned int max_data_bytes)
953 struct smb_filename *smb_fname = NULL;
954 char *params = *pparams;
955 char *pdata = *ppdata;
960 bool return_additional_info;
973 struct ea_list *ea_list = NULL;
978 uint32 create_disposition;
979 uint32 create_options = 0;
980 TALLOC_CTX *ctx = talloc_tos();
983 * Ensure we have enough parameters to perform the operation.
986 if (total_params < 29) {
987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
991 flags = SVAL(params, 0);
992 deny_mode = SVAL(params, 2);
993 open_attr = SVAL(params,6);
994 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
995 if (oplock_request) {
996 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1000 return_additional_info = BITSETW(params,0);
1001 open_sattr = SVAL(params, 4);
1002 open_time = make_unix_date3(params+8);
1004 open_ofun = SVAL(params,12);
1005 open_size = IVAL(params,14);
1006 pname = ¶ms[28];
1009 reply_doserror(req, ERRSRV, ERRaccess);
1013 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1014 total_params - 28, STR_TERMINATE,
1016 if (!NT_STATUS_IS_OK(status)) {
1017 reply_nterror(req, status);
1021 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1022 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1023 (unsigned int)open_ofun, open_size));
1025 status = filename_convert(ctx,
1027 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->base_name, deny_mode,
1051 &create_disposition,
1053 reply_doserror(req, ERRDOS, ERRbadaccess);
1057 /* Any data in this call is an EA list. */
1058 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1059 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1063 if (total_data != 4) {
1064 if (total_data < 10) {
1065 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1069 if (IVAL(pdata,0) > total_data) {
1070 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1071 IVAL(pdata,0), (unsigned int)total_data));
1072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1076 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1082 } else if (IVAL(pdata,0) != 4) {
1083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1087 status = SMB_VFS_CREATE_FILE(
1090 0, /* root_dir_fid */
1091 smb_fname, /* fname */
1092 access_mask, /* access_mask */
1093 share_mode, /* share_access */
1094 create_disposition, /* create_disposition*/
1095 create_options, /* create_options */
1096 open_attr, /* file_attributes */
1097 oplock_request, /* oplock_request */
1098 open_size, /* allocation_size */
1100 ea_list, /* ea_list */
1102 &smb_action); /* psbuf */
1104 if (!NT_STATUS_IS_OK(status)) {
1105 if (open_was_deferred(req->mid)) {
1106 /* We have re-scheduled this call. */
1109 reply_openerror(req, status);
1113 size = get_file_size_stat(&smb_fname->st);
1114 fattr = dos_mode(conn, smb_fname);
1115 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1116 inode = smb_fname->st.st_ex_ino;
1118 close_file(req, fsp, ERROR_CLOSE);
1119 reply_doserror(req, ERRDOS,ERRnoaccess);
1123 /* Realloc the size of parameters and data we will return */
1124 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1125 if(*pparams == NULL ) {
1126 reply_nterror(req, NT_STATUS_NO_MEMORY);
1131 SSVAL(params,0,fsp->fnum);
1132 SSVAL(params,2,fattr);
1133 srv_put_dos_date2(params,4, mtime);
1134 SIVAL(params,8, (uint32)size);
1135 SSVAL(params,12,deny_mode);
1136 SSVAL(params,14,0); /* open_type - file or directory. */
1137 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1139 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1140 smb_action |= EXTENDED_OPLOCK_GRANTED;
1143 SSVAL(params,18,smb_action);
1146 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1148 SIVAL(params,20,inode);
1149 SSVAL(params,24,0); /* Padding. */
1151 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1152 SIVAL(params, 26, ea_size);
1154 SIVAL(params, 26, 0);
1157 /* Send the required number of replies */
1158 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1160 TALLOC_FREE(smb_fname);
1163 /*********************************************************
1164 Routine to check if a given string matches exactly.
1165 as a special case a mask of "." does NOT match. That
1166 is required for correct wildcard semantics
1167 Case can be significant or not.
1168 **********************************************************/
1170 static bool exact_match(connection_struct *conn,
1174 if (mask[0] == '.' && mask[1] == 0)
1176 if (dptr_has_wild(conn->dirptr)) {
1179 if (conn->case_sensitive)
1180 return strcmp(str,mask)==0;
1182 return StrCaseCmp(str,mask) == 0;
1185 /****************************************************************************
1186 Return the filetype for UNIX extensions.
1187 ****************************************************************************/
1189 static uint32 unix_filetype(mode_t mode)
1192 return UNIX_TYPE_FILE;
1193 else if(S_ISDIR(mode))
1194 return UNIX_TYPE_DIR;
1196 else if(S_ISLNK(mode))
1197 return UNIX_TYPE_SYMLINK;
1200 else if(S_ISCHR(mode))
1201 return UNIX_TYPE_CHARDEV;
1204 else if(S_ISBLK(mode))
1205 return UNIX_TYPE_BLKDEV;
1208 else if(S_ISFIFO(mode))
1209 return UNIX_TYPE_FIFO;
1212 else if(S_ISSOCK(mode))
1213 return UNIX_TYPE_SOCKET;
1216 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1217 return UNIX_TYPE_UNKNOWN;
1220 /****************************************************************************
1221 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1222 ****************************************************************************/
1224 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1226 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1227 const SMB_STRUCT_STAT *psbuf,
1229 enum perm_type ptype,
1234 if (perms == SMB_MODE_NO_CHANGE) {
1235 if (!VALID_STAT(*psbuf)) {
1236 return NT_STATUS_INVALID_PARAMETER;
1238 *ret_perms = psbuf->st_ex_mode;
1239 return NT_STATUS_OK;
1243 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1244 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1245 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1246 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1247 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1248 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1249 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1250 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1251 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1253 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1256 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1259 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1264 /* Apply mode mask */
1265 ret &= lp_create_mask(SNUM(conn));
1266 /* Add in force bits */
1267 ret |= lp_force_create_mode(SNUM(conn));
1270 ret &= lp_dir_mask(SNUM(conn));
1271 /* Add in force bits */
1272 ret |= lp_force_dir_mode(SNUM(conn));
1274 case PERM_EXISTING_FILE:
1275 /* Apply mode mask */
1276 ret &= lp_security_mask(SNUM(conn));
1277 /* Add in force bits */
1278 ret |= lp_force_security_mode(SNUM(conn));
1280 case PERM_EXISTING_DIR:
1281 /* Apply mode mask */
1282 ret &= lp_dir_security_mask(SNUM(conn));
1283 /* Add in force bits */
1284 ret |= lp_force_dir_security_mode(SNUM(conn));
1289 return NT_STATUS_OK;
1292 /****************************************************************************
1293 Needed to show the msdfs symlinks as directories. Modifies psbuf
1294 to be a directory if it's a msdfs link.
1295 ****************************************************************************/
1297 static bool check_msdfs_link(connection_struct *conn,
1298 const char *pathname,
1299 SMB_STRUCT_STAT *psbuf)
1301 int saved_errno = errno;
1302 if(lp_host_msdfs() &&
1303 lp_msdfs_root(SNUM(conn)) &&
1304 is_msdfs_link(conn, pathname, psbuf)) {
1306 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1309 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1310 errno = saved_errno;
1313 errno = saved_errno;
1318 /****************************************************************************
1319 Get a level dependent lanman2 dir entry.
1320 ****************************************************************************/
1322 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1323 connection_struct *conn,
1325 const char *path_mask,
1328 int requires_resume_key,
1334 int space_remaining,
1336 bool *got_exact_match,
1337 int *last_entry_off,
1338 struct ea_list *name_list)
1342 SMB_STRUCT_STAT sbuf;
1343 const char *mask = NULL;
1344 char *pathreal = NULL;
1346 char *p, *q, *pdata = *ppdata;
1350 SMB_OFF_T file_size = 0;
1351 uint64_t allocation_size = 0;
1353 struct timespec mdate_ts, adate_ts, create_date_ts;
1354 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1356 char *last_entry_ptr;
1358 uint32 nt_extmode; /* Used for NT connections instead of mode */
1359 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1360 bool check_mangled_names = lp_manglednames(conn->params);
1361 char mangled_name[13]; /* mangled 8.3 name. */
1363 *out_of_space = False;
1364 *got_exact_match = False;
1366 ZERO_STRUCT(mdate_ts);
1367 ZERO_STRUCT(adate_ts);
1368 ZERO_STRUCT(create_date_ts);
1370 if (!conn->dirptr) {
1374 p = strrchr_m(path_mask,'/');
1377 mask = talloc_strdup(ctx,"*.*");
1387 bool ms_dfs_link = False;
1389 /* Needed if we run out of space */
1390 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1391 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1394 * Due to bugs in NT client redirectors we are not using
1395 * resume keys any more - set them to zero.
1396 * Check out the related comments in findfirst/findnext.
1402 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1403 (long)conn->dirptr,curr_dirpos));
1410 * fname may get mangled, dname is never mangled.
1411 * Whenever we're accessing the filesystem we use
1412 * pathreal which is composed from dname.
1418 /* Mangle fname if it's an illegal name. */
1419 if (mangle_must_mangle(dname,conn->params)) {
1420 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1422 continue; /* Error - couldn't mangle. */
1424 fname = talloc_strdup(ctx, mangled_name);
1430 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1431 got_match = mask_match(fname, mask, conn->case_sensitive);
1434 if(!got_match && check_mangled_names &&
1435 !mangle_is_8_3(fname, False, conn->params)) {
1437 * It turns out that NT matches wildcards against
1438 * both long *and* short names. This may explain some
1439 * of the wildcard wierdness from old DOS clients
1440 * that some people have been seeing.... JRA.
1442 /* Force the mangling into 8.3. */
1443 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1445 continue; /* Error - couldn't mangle. */
1448 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1449 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1454 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1455 struct smb_filename *smb_fname = NULL;
1458 if (dont_descend && !isdots) {
1465 pathreal = talloc_asprintf(ctx,
1470 pathreal = talloc_asprintf(ctx,
1481 /* A dirent from dptr_ReadDirName isn't a stream. */
1482 status = create_synthetic_smb_fname(ctx, pathreal,
1485 if (!NT_STATUS_IS_OK(status)) {
1490 if (INFO_LEVEL_IS_UNIX(info_level)) {
1491 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
1492 DEBUG(5,("get_lanman2_dir_entry: "
1493 "Couldn't lstat [%s] (%s)\n",
1494 smb_fname_str_dbg(smb_fname),
1496 TALLOC_FREE(smb_fname);
1497 TALLOC_FREE(pathreal);
1501 } else if (!VALID_STAT(smb_fname->st) &&
1502 SMB_VFS_STAT(conn, smb_fname) != 0) {
1503 /* Needed to show the msdfs symlinks as
1507 check_msdfs_link(conn,
1508 smb_fname->base_name,
1511 DEBUG(5,("get_lanman2_dir_entry: "
1512 "Couldn't stat [%s] (%s)\n",
1513 smb_fname_str_dbg(smb_fname),
1515 TALLOC_FREE(smb_fname);
1516 TALLOC_FREE(pathreal);
1523 mode = dos_mode_msdfs(conn, smb_fname);
1525 mode = dos_mode(conn, smb_fname);
1528 if (!dir_check_ftype(conn,mode,dirtype)) {
1529 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1530 TALLOC_FREE(smb_fname);
1531 TALLOC_FREE(pathreal);
1536 if (!(mode & aDIR)) {
1537 file_size = get_file_size_stat(&smb_fname->st);
1540 SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1542 if (ask_sharemode) {
1543 struct timespec write_time_ts;
1544 struct file_id fileid;
1546 ZERO_STRUCT(write_time_ts);
1547 fileid = vfs_file_id_from_sbuf(conn,
1549 get_file_infos(fileid, NULL, &write_time_ts);
1550 if (!null_timespec(write_time_ts)) {
1551 update_stat_ex_mtime(&smb_fname->st,
1556 mdate_ts = smb_fname->st.st_ex_mtime;
1557 adate_ts = smb_fname->st.st_ex_atime;
1558 create_date_ts = smb_fname->st.st_ex_btime;
1560 if (lp_dos_filetime_resolution(SNUM(conn))) {
1561 dos_filetime_timespec(&create_date_ts);
1562 dos_filetime_timespec(&mdate_ts);
1563 dos_filetime_timespec(&adate_ts);
1566 create_date = convert_timespec_to_time_t(create_date_ts);
1567 mdate = convert_timespec_to_time_t(mdate_ts);
1568 adate = convert_timespec_to_time_t(adate_ts);
1570 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1571 smb_fname_str_dbg(smb_fname), fname));
1575 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1576 sbuf = smb_fname->st;
1578 TALLOC_FREE(smb_fname);
1588 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1590 switch (info_level) {
1591 case SMB_FIND_INFO_STANDARD:
1592 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1593 if(requires_resume_key) {
1597 srv_put_dos_date2(p,0,create_date);
1598 srv_put_dos_date2(p,4,adate);
1599 srv_put_dos_date2(p,8,mdate);
1600 SIVAL(p,12,(uint32)file_size);
1601 SIVAL(p,16,(uint32)allocation_size);
1605 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1606 p += ucs2_align(base_data, p, 0);
1608 len = srvstr_push(base_data, flags2, p,
1609 fname, PTR_DIFF(end_data, p),
1611 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1613 SCVAL(nameptr, -1, len - 2);
1615 SCVAL(nameptr, -1, 0);
1619 SCVAL(nameptr, -1, len - 1);
1621 SCVAL(nameptr, -1, 0);
1627 case SMB_FIND_EA_SIZE:
1628 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1629 if(requires_resume_key) {
1633 srv_put_dos_date2(p,0,create_date);
1634 srv_put_dos_date2(p,4,adate);
1635 srv_put_dos_date2(p,8,mdate);
1636 SIVAL(p,12,(uint32)file_size);
1637 SIVAL(p,16,(uint32)allocation_size);
1640 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1641 SIVAL(p,22,ea_size); /* Extended attributes */
1645 len = srvstr_push(base_data, flags2,
1646 p, fname, PTR_DIFF(end_data, p),
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.. */
1666 case SMB_FIND_EA_LIST:
1668 struct ea_list *file_list = NULL;
1671 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1675 if(requires_resume_key) {
1679 srv_put_dos_date2(p,0,create_date);
1680 srv_put_dos_date2(p,4,adate);
1681 srv_put_dos_date2(p,8,mdate);
1682 SIVAL(p,12,(uint32)file_size);
1683 SIVAL(p,16,(uint32)allocation_size);
1685 p += 22; /* p now points to the EA area. */
1687 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1688 name_list = ea_list_union(name_list, file_list, &ea_len);
1690 /* We need to determine if this entry will fit in the space available. */
1691 /* Max string size is 255 bytes. */
1692 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1693 /* Move the dirptr back to prev_dirpos */
1694 dptr_SeekDir(conn->dirptr, prev_dirpos);
1695 *out_of_space = True;
1696 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1697 return False; /* Not finished - just out of space */
1700 /* Push the ea_data followed by the name. */
1701 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1703 len = srvstr_push(base_data, flags2,
1704 p + 1, fname, PTR_DIFF(end_data, p+1),
1705 STR_TERMINATE | STR_NOALIGN);
1706 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1719 SCVAL(nameptr,0,len);
1721 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1725 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1726 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1727 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1729 SIVAL(p,0,reskey); p += 4;
1730 put_long_date_timespec(p,create_date_ts); p += 8;
1731 put_long_date_timespec(p,adate_ts); p += 8;
1732 put_long_date_timespec(p,mdate_ts); p += 8;
1733 put_long_date_timespec(p,mdate_ts); p += 8;
1734 SOFF_T(p,0,file_size); p += 8;
1735 SOFF_T(p,0,allocation_size); p += 8;
1736 SIVAL(p,0,nt_extmode); p += 4;
1737 q = p; p += 4; /* q is placeholder for name length. */
1739 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1740 SIVAL(p,0,ea_size); /* Extended attributes */
1743 /* Clear the short name buffer. This is
1744 * IMPORTANT as not doing so will trigger
1745 * a Win2k client bug. JRA.
1747 if (!was_8_3 && check_mangled_names) {
1748 if (!name_to_8_3(fname,mangled_name,True,
1750 /* Error - mangle failed ! */
1751 memset(mangled_name,'\0',12);
1753 mangled_name[12] = 0;
1754 len = srvstr_push(base_data, flags2,
1755 p+2, mangled_name, 24,
1756 STR_UPPER|STR_UNICODE);
1758 memset(p + 2 + len,'\0',24 - len);
1765 len = srvstr_push(base_data, flags2, p,
1766 fname, PTR_DIFF(end_data, p),
1767 STR_TERMINATE_ASCII);
1770 SIVAL(p,0,0); /* Ensure any padding is null. */
1771 len = PTR_DIFF(p, pdata);
1772 len = (len + 3) & ~3;
1777 case SMB_FIND_FILE_DIRECTORY_INFO:
1778 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1780 SIVAL(p,0,reskey); p += 4;
1781 put_long_date_timespec(p,create_date_ts); p += 8;
1782 put_long_date_timespec(p,adate_ts); p += 8;
1783 put_long_date_timespec(p,mdate_ts); p += 8;
1784 put_long_date_timespec(p,mdate_ts); p += 8;
1785 SOFF_T(p,0,file_size); p += 8;
1786 SOFF_T(p,0,allocation_size); p += 8;
1787 SIVAL(p,0,nt_extmode); p += 4;
1788 len = srvstr_push(base_data, flags2,
1789 p + 4, fname, PTR_DIFF(end_data, p+4),
1790 STR_TERMINATE_ASCII);
1793 SIVAL(p,0,0); /* Ensure any padding is null. */
1794 len = PTR_DIFF(p, pdata);
1795 len = (len + 3) & ~3;
1800 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1801 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1803 SIVAL(p,0,reskey); p += 4;
1804 put_long_date_timespec(p,create_date_ts); p += 8;
1805 put_long_date_timespec(p,adate_ts); p += 8;
1806 put_long_date_timespec(p,mdate_ts); p += 8;
1807 put_long_date_timespec(p,mdate_ts); p += 8;
1808 SOFF_T(p,0,file_size); p += 8;
1809 SOFF_T(p,0,allocation_size); p += 8;
1810 SIVAL(p,0,nt_extmode); p += 4;
1811 q = p; p += 4; /* q is placeholder for name length. */
1813 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1814 SIVAL(p,0,ea_size); /* Extended attributes */
1817 len = srvstr_push(base_data, flags2, p,
1818 fname, PTR_DIFF(end_data, p),
1819 STR_TERMINATE_ASCII);
1823 SIVAL(p,0,0); /* Ensure any padding is null. */
1824 len = PTR_DIFF(p, pdata);
1825 len = (len + 3) & ~3;
1830 case SMB_FIND_FILE_NAMES_INFO:
1831 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1833 SIVAL(p,0,reskey); p += 4;
1835 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1836 acl on a dir (tridge) */
1837 len = srvstr_push(base_data, flags2, p,
1838 fname, PTR_DIFF(end_data, p),
1839 STR_TERMINATE_ASCII);
1842 SIVAL(p,0,0); /* Ensure any padding is null. */
1843 len = PTR_DIFF(p, pdata);
1844 len = (len + 3) & ~3;
1849 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1850 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1852 SIVAL(p,0,reskey); p += 4;
1853 put_long_date_timespec(p,create_date_ts); p += 8;
1854 put_long_date_timespec(p,adate_ts); p += 8;
1855 put_long_date_timespec(p,mdate_ts); p += 8;
1856 put_long_date_timespec(p,mdate_ts); p += 8;
1857 SOFF_T(p,0,file_size); p += 8;
1858 SOFF_T(p,0,allocation_size); p += 8;
1859 SIVAL(p,0,nt_extmode); p += 4;
1860 q = p; p += 4; /* q is placeholder for name length. */
1862 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1863 SIVAL(p,0,ea_size); /* Extended attributes */
1866 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1867 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1868 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1869 len = srvstr_push(base_data, flags2, p,
1870 fname, PTR_DIFF(end_data, p),
1871 STR_TERMINATE_ASCII);
1874 SIVAL(p,0,0); /* Ensure any padding is null. */
1875 len = PTR_DIFF(p, pdata);
1876 len = (len + 3) & ~3;
1881 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1882 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1883 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1885 SIVAL(p,0,reskey); p += 4;
1886 put_long_date_timespec(p,create_date_ts); p += 8;
1887 put_long_date_timespec(p,adate_ts); p += 8;
1888 put_long_date_timespec(p,mdate_ts); p += 8;
1889 put_long_date_timespec(p,mdate_ts); p += 8;
1890 SOFF_T(p,0,file_size); p += 8;
1891 SOFF_T(p,0,allocation_size); p += 8;
1892 SIVAL(p,0,nt_extmode); p += 4;
1893 q = p; p += 4; /* q is placeholder for name length */
1895 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1896 SIVAL(p,0,ea_size); /* Extended attributes */
1899 /* Clear the short name buffer. This is
1900 * IMPORTANT as not doing so will trigger
1901 * a Win2k client bug. JRA.
1903 if (!was_8_3 && check_mangled_names) {
1904 if (!name_to_8_3(fname,mangled_name,True,
1906 /* Error - mangle failed ! */
1907 memset(mangled_name,'\0',12);
1909 mangled_name[12] = 0;
1910 len = srvstr_push(base_data, flags2,
1911 p+2, mangled_name, 24,
1912 STR_UPPER|STR_UNICODE);
1915 memset(p + 2 + len,'\0',24 - len);
1922 SSVAL(p,0,0); p += 2; /* Reserved ? */
1923 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1924 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1925 len = srvstr_push(base_data, flags2, p,
1926 fname, PTR_DIFF(end_data, p),
1927 STR_TERMINATE_ASCII);
1930 SIVAL(p,0,0); /* Ensure any padding is null. */
1931 len = PTR_DIFF(p, pdata);
1932 len = (len + 3) & ~3;
1937 /* CIFS UNIX Extension. */
1939 case SMB_FIND_FILE_UNIX:
1940 case SMB_FIND_FILE_UNIX_INFO2:
1942 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1944 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1946 if (info_level == SMB_FIND_FILE_UNIX) {
1947 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1948 p = store_file_unix_basic(conn, p,
1950 len = srvstr_push(base_data, flags2, p,
1951 fname, PTR_DIFF(end_data, p),
1954 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1955 p = store_file_unix_basic_info2(conn, p,
1959 len = srvstr_push(base_data, flags2, p, fname,
1960 PTR_DIFF(end_data, p), 0);
1961 SIVAL(nameptr, 0, len);
1965 SIVAL(p,0,0); /* Ensure any padding is null. */
1967 len = PTR_DIFF(p, pdata);
1968 len = (len + 3) & ~3;
1969 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1971 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1981 if (PTR_DIFF(p,pdata) > space_remaining) {
1982 /* Move the dirptr back to prev_dirpos */
1983 dptr_SeekDir(conn->dirptr, prev_dirpos);
1984 *out_of_space = True;
1985 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1986 return False; /* Not finished - just out of space */
1989 /* Setup the last entry pointer, as an offset from base_data */
1990 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1991 /* Advance the data pointer to the next slot */
1997 /****************************************************************************
1998 Reply to a TRANS2_FINDFIRST.
1999 ****************************************************************************/
2001 static void call_trans2findfirst(connection_struct *conn,
2002 struct smb_request *req,
2003 char **pparams, int total_params,
2004 char **ppdata, int total_data,
2005 unsigned int max_data_bytes)
2007 /* We must be careful here that we don't return more than the
2008 allowed number of data bytes. If this means returning fewer than
2009 maxentries then so be it. We assume that the redirector has
2010 enough room for the fixed number of parameter bytes it has
2012 struct smb_filename *smb_dname = NULL;
2013 char *params = *pparams;
2014 char *pdata = *ppdata;
2018 uint16 findfirst_flags;
2019 bool close_after_first;
2021 bool requires_resume_key;
2023 char *directory = NULL;
2026 int last_entry_off=0;
2030 bool finished = False;
2031 bool dont_descend = False;
2032 bool out_of_space = False;
2033 int space_remaining;
2034 bool mask_contains_wcard = False;
2035 struct ea_list *ea_list = NULL;
2036 NTSTATUS ntstatus = NT_STATUS_OK;
2037 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2038 TALLOC_CTX *ctx = talloc_tos();
2040 if (total_params < 13) {
2041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2045 dirtype = SVAL(params,0);
2046 maxentries = SVAL(params,2);
2047 findfirst_flags = SVAL(params,4);
2048 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2049 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2050 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2051 info_level = SVAL(params,6);
2053 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2054 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2055 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2056 info_level, max_data_bytes));
2059 /* W2K3 seems to treat zero as 1. */
2063 switch (info_level) {
2064 case SMB_FIND_INFO_STANDARD:
2065 case SMB_FIND_EA_SIZE:
2066 case SMB_FIND_EA_LIST:
2067 case SMB_FIND_FILE_DIRECTORY_INFO:
2068 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2069 case SMB_FIND_FILE_NAMES_INFO:
2070 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2071 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2072 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2074 case SMB_FIND_FILE_UNIX:
2075 case SMB_FIND_FILE_UNIX_INFO2:
2076 /* Always use filesystem for UNIX mtime query. */
2077 ask_sharemode = false;
2078 if (!lp_unix_extensions()) {
2079 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2084 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2088 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2089 params+12, total_params - 12,
2090 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2091 if (!NT_STATUS_IS_OK(ntstatus)) {
2092 reply_nterror(req, ntstatus);
2096 ntstatus = resolve_dfspath_wcard(ctx, conn,
2097 req->flags2 & FLAGS2_DFS_PATHNAMES,
2100 &mask_contains_wcard);
2101 if (!NT_STATUS_IS_OK(ntstatus)) {
2102 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2103 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2104 ERRSRV, ERRbadpath);
2107 reply_nterror(req, ntstatus);
2111 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2112 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2113 if (!NT_STATUS_IS_OK(ntstatus)) {
2114 reply_nterror(req, ntstatus);
2118 mask = smb_dname->original_lcomp;
2120 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2121 TALLOC_FREE(smb_dname);
2122 if (!NT_STATUS_IS_OK(ntstatus)) {
2123 reply_nterror(req, ntstatus);
2127 ntstatus = check_name(conn, directory);
2128 if (!NT_STATUS_IS_OK(ntstatus)) {
2129 reply_nterror(req, ntstatus);
2133 p = strrchr_m(directory,'/');
2135 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2136 if((directory[0] == '.') && (directory[1] == '\0')) {
2137 mask = talloc_strdup(ctx,"*");
2139 reply_nterror(req, NT_STATUS_NO_MEMORY);
2142 mask_contains_wcard = True;
2144 directory = talloc_strdup(talloc_tos(), "./");
2146 reply_nterror(req, NT_STATUS_NO_MEMORY);
2153 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2155 if (info_level == SMB_FIND_EA_LIST) {
2158 if (total_data < 4) {
2159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2163 ea_size = IVAL(pdata,0);
2164 if (ea_size != total_data) {
2165 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2166 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2171 if (!lp_ea_support(SNUM(conn))) {
2172 reply_doserror(req, ERRDOS, ERReasnotsupported);
2176 /* Pull out the list of names. */
2177 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2184 *ppdata = (char *)SMB_REALLOC(
2185 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2186 if(*ppdata == NULL ) {
2187 reply_nterror(req, NT_STATUS_NO_MEMORY);
2191 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2193 /* Realloc the params space */
2194 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2195 if (*pparams == NULL) {
2196 reply_nterror(req, NT_STATUS_NO_MEMORY);
2201 /* Save the wildcard match and attribs we are using on this directory -
2202 needed as lanman2 assumes these are being saved between calls */
2204 ntstatus = dptr_create(conn,
2210 mask_contains_wcard,
2214 if (!NT_STATUS_IS_OK(ntstatus)) {
2215 reply_nterror(req, ntstatus);
2219 dptr_num = dptr_dnum(conn->dirptr);
2220 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2222 /* Initialize per TRANS2_FIND_FIRST operation data */
2223 dptr_init_search_op(conn->dirptr);
2225 /* We don't need to check for VOL here as this is returned by
2226 a different TRANS2 call. */
2228 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2229 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2230 dont_descend = True;
2233 space_remaining = max_data_bytes;
2234 out_of_space = False;
2236 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2237 bool got_exact_match = False;
2239 /* this is a heuristic to avoid seeking the dirptr except when
2240 absolutely necessary. It allows for a filename of about 40 chars */
2241 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2242 out_of_space = True;
2245 finished = !get_lanman2_dir_entry(ctx,
2248 mask,dirtype,info_level,
2249 requires_resume_key,dont_descend,
2252 space_remaining, &out_of_space,
2254 &last_entry_off, ea_list);
2257 if (finished && out_of_space)
2260 if (!finished && !out_of_space)
2264 * As an optimisation if we know we aren't looking
2265 * for a wildcard name (ie. the name matches the wildcard exactly)
2266 * then we can finish on any (first) match.
2267 * This speeds up large directory searches. JRA.
2273 /* Ensure space_remaining never goes -ve. */
2274 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2275 space_remaining = 0;
2276 out_of_space = true;
2278 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2282 /* Check if we can close the dirptr */
2283 if(close_after_first || (finished && close_if_end)) {
2284 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2285 dptr_close(&dptr_num);
2289 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2290 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2291 * the protocol level is less than NT1. Tested with smbclient. JRA.
2292 * This should fix the OS/2 client bug #2335.
2295 if(numentries == 0) {
2296 dptr_close(&dptr_num);
2297 if (Protocol < PROTOCOL_NT1) {
2298 reply_doserror(req, ERRDOS, ERRnofiles);
2301 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2302 ERRDOS, ERRbadfile);
2307 /* At this point pdata points to numentries directory entries. */
2309 /* Set up the return parameter block */
2310 SSVAL(params,0,dptr_num);
2311 SSVAL(params,2,numentries);
2312 SSVAL(params,4,finished);
2313 SSVAL(params,6,0); /* Never an EA error */
2314 SSVAL(params,8,last_entry_off);
2316 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2319 if ((! *directory) && dptr_path(dptr_num)) {
2320 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2322 reply_nterror(req, NT_STATUS_NO_MEMORY);
2326 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2327 smb_fn_name(req->cmd),
2328 mask, directory, dirtype, numentries ) );
2331 * Force a name mangle here to ensure that the
2332 * mask as an 8.3 name is top of the mangled cache.
2333 * The reasons for this are subtle. Don't remove
2334 * this code unless you know what you are doing
2335 * (see PR#13758). JRA.
2338 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2339 char mangled_name[13];
2340 name_to_8_3(mask, mangled_name, True, conn->params);
2346 /****************************************************************************
2347 Reply to a TRANS2_FINDNEXT.
2348 ****************************************************************************/
2350 static void call_trans2findnext(connection_struct *conn,
2351 struct smb_request *req,
2352 char **pparams, int total_params,
2353 char **ppdata, int total_data,
2354 unsigned int max_data_bytes)
2356 /* We must be careful here that we don't return more than the
2357 allowed number of data bytes. If this means returning fewer than
2358 maxentries then so be it. We assume that the redirector has
2359 enough room for the fixed number of parameter bytes it has
2361 char *params = *pparams;
2362 char *pdata = *ppdata;
2368 uint16 findnext_flags;
2369 bool close_after_request;
2371 bool requires_resume_key;
2373 bool mask_contains_wcard = False;
2374 char *resume_name = NULL;
2375 const char *mask = NULL;
2376 const char *directory = NULL;
2380 int i, last_entry_off=0;
2381 bool finished = False;
2382 bool dont_descend = False;
2383 bool out_of_space = False;
2384 int space_remaining;
2385 struct ea_list *ea_list = NULL;
2386 NTSTATUS ntstatus = NT_STATUS_OK;
2387 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2388 TALLOC_CTX *ctx = talloc_tos();
2390 if (total_params < 13) {
2391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2395 dptr_num = SVAL(params,0);
2396 maxentries = SVAL(params,2);
2397 info_level = SVAL(params,4);
2398 resume_key = IVAL(params,6);
2399 findnext_flags = SVAL(params,10);
2400 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2401 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2402 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2403 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2405 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2407 total_params - 12, STR_TERMINATE, &ntstatus,
2408 &mask_contains_wcard);
2409 if (!NT_STATUS_IS_OK(ntstatus)) {
2410 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2411 complain (it thinks we're asking for the directory above the shared
2412 path or an invalid name). Catch this as the resume name is only compared, never used in
2413 a file access. JRA. */
2414 srvstr_pull_talloc(ctx, params, req->flags2,
2415 &resume_name, params+12,
2419 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2420 reply_nterror(req, ntstatus);
2425 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2426 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2427 resume_key = %d resume name = %s continue=%d level = %d\n",
2428 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2429 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2432 /* W2K3 seems to treat zero as 1. */
2436 switch (info_level) {
2437 case SMB_FIND_INFO_STANDARD:
2438 case SMB_FIND_EA_SIZE:
2439 case SMB_FIND_EA_LIST:
2440 case SMB_FIND_FILE_DIRECTORY_INFO:
2441 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2442 case SMB_FIND_FILE_NAMES_INFO:
2443 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2444 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2445 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2447 case SMB_FIND_FILE_UNIX:
2448 case SMB_FIND_FILE_UNIX_INFO2:
2449 /* Always use filesystem for UNIX mtime query. */
2450 ask_sharemode = false;
2451 if (!lp_unix_extensions()) {
2452 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2457 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2461 if (info_level == SMB_FIND_EA_LIST) {
2464 if (total_data < 4) {
2465 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2469 ea_size = IVAL(pdata,0);
2470 if (ea_size != total_data) {
2471 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2472 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2477 if (!lp_ea_support(SNUM(conn))) {
2478 reply_doserror(req, ERRDOS, ERReasnotsupported);
2482 /* Pull out the list of names. */
2483 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2490 *ppdata = (char *)SMB_REALLOC(
2491 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2492 if(*ppdata == NULL) {
2493 reply_nterror(req, NT_STATUS_NO_MEMORY);
2498 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2500 /* Realloc the params space */
2501 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2502 if(*pparams == NULL ) {
2503 reply_nterror(req, NT_STATUS_NO_MEMORY);
2509 /* Check that the dptr is valid */
2510 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2511 reply_doserror(req, ERRDOS, ERRnofiles);
2515 string_set(&conn->dirpath,dptr_path(dptr_num));
2517 /* Get the wildcard mask from the dptr */
2518 if((p = dptr_wcard(dptr_num))== NULL) {
2519 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2520 reply_doserror(req, ERRDOS, ERRnofiles);
2525 directory = conn->dirpath;
2527 /* Get the attr mask from the dptr */
2528 dirtype = dptr_attr(dptr_num);
2530 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2531 dptr_num, mask, dirtype,
2533 dptr_TellDir(conn->dirptr)));
2535 /* Initialize per TRANS2_FIND_NEXT operation data */
2536 dptr_init_search_op(conn->dirptr);
2538 /* We don't need to check for VOL here as this is returned by
2539 a different TRANS2 call. */
2541 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2542 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2543 dont_descend = True;
2546 space_remaining = max_data_bytes;
2547 out_of_space = False;
2550 * Seek to the correct position. We no longer use the resume key but
2551 * depend on the last file name instead.
2554 if(*resume_name && !continue_bit) {
2557 long current_pos = 0;
2559 * Remember, name_to_8_3 is called by
2560 * get_lanman2_dir_entry(), so the resume name
2561 * could be mangled. Ensure we check the unmangled name.
2564 if (mangle_is_mangled(resume_name, conn->params)) {
2565 char *new_resume_name = NULL;
2566 mangle_lookup_name_from_8_3(ctx,
2570 if (new_resume_name) {
2571 resume_name = new_resume_name;
2576 * Fix for NT redirector problem triggered by resume key indexes
2577 * changing between directory scans. We now return a resume key of 0
2578 * and instead look for the filename to continue from (also given
2579 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2580 * findfirst/findnext (as is usual) then the directory pointer
2581 * should already be at the correct place.
2584 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2585 } /* end if resume_name && !continue_bit */
2587 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2588 bool got_exact_match = False;
2590 /* this is a heuristic to avoid seeking the dirptr except when
2591 absolutely necessary. It allows for a filename of about 40 chars */
2592 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2593 out_of_space = True;
2596 finished = !get_lanman2_dir_entry(ctx,
2599 mask,dirtype,info_level,
2600 requires_resume_key,dont_descend,
2603 space_remaining, &out_of_space,
2605 &last_entry_off, ea_list);
2608 if (finished && out_of_space)
2611 if (!finished && !out_of_space)
2615 * As an optimisation if we know we aren't looking
2616 * for a wildcard name (ie. the name matches the wildcard exactly)
2617 * then we can finish on any (first) match.
2618 * This speeds up large directory searches. JRA.
2624 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2627 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2628 smb_fn_name(req->cmd),
2629 mask, directory, dirtype, numentries ) );
2631 /* Check if we can close the dirptr */
2632 if(close_after_request || (finished && close_if_end)) {
2633 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2634 dptr_close(&dptr_num); /* This frees up the saved mask */
2637 /* Set up the return parameter block */
2638 SSVAL(params,0,numentries);
2639 SSVAL(params,2,finished);
2640 SSVAL(params,4,0); /* Never an EA error */
2641 SSVAL(params,6,last_entry_off);
2643 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2649 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2651 E_md4hash(lp_servicename(SNUM(conn)),objid);
2655 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2657 SMB_ASSERT(extended_info != NULL);
2659 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2660 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2661 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2662 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2663 #ifdef SAMBA_VERSION_REVISION
2664 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2666 extended_info->samba_subversion = 0;
2667 #ifdef SAMBA_VERSION_RC_RELEASE
2668 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2670 #ifdef SAMBA_VERSION_PRE_RELEASE
2671 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2674 #ifdef SAMBA_VERSION_VENDOR_PATCH
2675 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2677 extended_info->samba_gitcommitdate = 0;
2678 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2679 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2682 memset(extended_info->samba_version_string, 0,
2683 sizeof(extended_info->samba_version_string));
2685 snprintf (extended_info->samba_version_string,
2686 sizeof(extended_info->samba_version_string),
2687 "%s", samba_version_string());
2690 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2691 TALLOC_CTX *mem_ctx,
2692 uint16_t info_level,
2695 unsigned int max_data_bytes,
2699 char *pdata, *end_data;
2700 int data_len = 0, len;
2701 const char *vname = volume_label(SNUM(conn));
2702 int snum = SNUM(conn);
2703 char *fstype = lp_fstype(SNUM(conn));
2704 uint32 additional_flags = 0;
2707 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2708 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2709 "info level (0x%x) on IPC$.\n",
2710 (unsigned int)info_level));
2711 return NT_STATUS_ACCESS_DENIED;
2715 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2717 *ppdata = (char *)SMB_REALLOC(
2718 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2719 if (*ppdata == NULL) {
2720 return NT_STATUS_NO_MEMORY;
2724 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2725 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2727 switch (info_level) {
2728 case SMB_INFO_ALLOCATION:
2730 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2732 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2733 return map_nt_error_from_unix(errno);
2736 block_size = lp_block_size(snum);
2737 if (bsize < block_size) {
2738 uint64_t factor = block_size/bsize;
2743 if (bsize > block_size) {
2744 uint64_t factor = bsize/block_size;
2749 bytes_per_sector = 512;
2750 sectors_per_unit = bsize/bytes_per_sector;
2752 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2753 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2754 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2756 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2757 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2758 SIVAL(pdata,l1_cUnit,dsize);
2759 SIVAL(pdata,l1_cUnitAvail,dfree);
2760 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2764 case SMB_INFO_VOLUME:
2765 /* Return volume name */
2767 * Add volume serial number - hash of a combination of
2768 * the called hostname and the service name.
2770 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2772 * Win2k3 and previous mess this up by sending a name length
2773 * one byte short. I believe only older clients (OS/2 Win9x) use
2774 * this call so try fixing this by adding a terminating null to
2775 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2779 pdata+l2_vol_szVolLabel, vname,
2780 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2781 STR_NOALIGN|STR_TERMINATE);
2782 SCVAL(pdata,l2_vol_cch,len);
2783 data_len = l2_vol_szVolLabel + len;
2784 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2785 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2789 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2790 case SMB_FS_ATTRIBUTE_INFORMATION:
2792 additional_flags = 0;
2793 #if defined(HAVE_SYS_QUOTAS)
2794 additional_flags |= FILE_VOLUME_QUOTAS;
2797 if(lp_nt_acl_support(SNUM(conn))) {
2798 additional_flags |= FILE_PERSISTENT_ACLS;
2801 /* Capabilities are filled in at connection time through STATVFS call */
2802 additional_flags |= conn->fs_capabilities;
2804 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2805 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2806 additional_flags); /* FS ATTRIBUTES */
2808 SIVAL(pdata,4,255); /* Max filename component length */
2809 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2810 and will think we can't do long filenames */
2811 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2812 PTR_DIFF(end_data, pdata+12),
2815 data_len = 12 + len;
2818 case SMB_QUERY_FS_LABEL_INFO:
2819 case SMB_FS_LABEL_INFORMATION:
2820 len = srvstr_push(pdata, flags2, pdata+4, vname,
2821 PTR_DIFF(end_data, pdata+4), 0);
2826 case SMB_QUERY_FS_VOLUME_INFO:
2827 case SMB_FS_VOLUME_INFORMATION:
2830 * Add volume serial number - hash of a combination of
2831 * the called hostname and the service name.
2833 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2834 (str_checksum(get_local_machine_name())<<16));
2836 /* Max label len is 32 characters. */
2837 len = srvstr_push(pdata, flags2, pdata+18, vname,
2838 PTR_DIFF(end_data, pdata+18),
2840 SIVAL(pdata,12,len);
2843 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2844 (int)strlen(vname),vname, lp_servicename(snum)));
2847 case SMB_QUERY_FS_SIZE_INFO:
2848 case SMB_FS_SIZE_INFORMATION:
2850 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2852 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2853 return map_nt_error_from_unix(errno);
2855 block_size = lp_block_size(snum);
2856 if (bsize < block_size) {
2857 uint64_t factor = block_size/bsize;
2862 if (bsize > block_size) {
2863 uint64_t factor = bsize/block_size;
2868 bytes_per_sector = 512;
2869 sectors_per_unit = bsize/bytes_per_sector;
2870 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2871 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2872 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2873 SBIG_UINT(pdata,0,dsize);
2874 SBIG_UINT(pdata,8,dfree);
2875 SIVAL(pdata,16,sectors_per_unit);
2876 SIVAL(pdata,20,bytes_per_sector);
2880 case SMB_FS_FULL_SIZE_INFORMATION:
2882 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2884 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2885 return map_nt_error_from_unix(errno);
2887 block_size = lp_block_size(snum);
2888 if (bsize < block_size) {
2889 uint64_t factor = block_size/bsize;
2894 if (bsize > block_size) {
2895 uint64_t factor = bsize/block_size;
2900 bytes_per_sector = 512;
2901 sectors_per_unit = bsize/bytes_per_sector;
2902 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2903 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2904 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2905 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2906 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2907 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2908 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2909 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2913 case SMB_QUERY_FS_DEVICE_INFO:
2914 case SMB_FS_DEVICE_INFORMATION:
2916 SIVAL(pdata,0,0); /* dev type */
2917 SIVAL(pdata,4,0); /* characteristics */
2920 #ifdef HAVE_SYS_QUOTAS
2921 case SMB_FS_QUOTA_INFORMATION:
2923 * what we have to send --metze:
2925 * Unknown1: 24 NULL bytes
2926 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2927 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2928 * Quota Flags: 2 byte :
2929 * Unknown3: 6 NULL bytes
2933 * details for Quota Flags:
2935 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2936 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2937 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2938 * 0x0001 Enable Quotas: enable quota for this fs
2942 /* we need to fake up a fsp here,
2943 * because its not send in this call
2946 SMB_NTQUOTA_STRUCT quotas;
2949 ZERO_STRUCT(quotas);
2955 if (conn->server_info->utok.uid != sec_initial_uid()) {
2956 DEBUG(0,("set_user_quota: access_denied "
2957 "service [%s] user [%s]\n",
2958 lp_servicename(SNUM(conn)),
2959 conn->server_info->unix_name));
2960 return NT_STATUS_ACCESS_DENIED;
2963 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2964 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2965 return map_nt_error_from_unix(errno);
2970 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2971 lp_servicename(SNUM(conn))));
2973 /* Unknown1 24 NULL bytes*/
2974 SBIG_UINT(pdata,0,(uint64_t)0);
2975 SBIG_UINT(pdata,8,(uint64_t)0);
2976 SBIG_UINT(pdata,16,(uint64_t)0);
2978 /* Default Soft Quota 8 bytes */
2979 SBIG_UINT(pdata,24,quotas.softlim);
2981 /* Default Hard Quota 8 bytes */
2982 SBIG_UINT(pdata,32,quotas.hardlim);
2984 /* Quota flag 2 bytes */
2985 SSVAL(pdata,40,quotas.qflags);
2987 /* Unknown3 6 NULL bytes */
2993 #endif /* HAVE_SYS_QUOTAS */
2994 case SMB_FS_OBJECTID_INFORMATION:
2996 unsigned char objid[16];
2997 struct smb_extended_info extended_info;
2998 memcpy(pdata,create_volume_objectid(conn, objid),16);
2999 samba_extended_info_version (&extended_info);
3000 SIVAL(pdata,16,extended_info.samba_magic);
3001 SIVAL(pdata,20,extended_info.samba_version);
3002 SIVAL(pdata,24,extended_info.samba_subversion);
3003 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3004 memcpy(pdata+36,extended_info.samba_version_string,28);
3010 * Query the version and capabilities of the CIFS UNIX extensions
3014 case SMB_QUERY_CIFS_UNIX_INFO:
3016 bool large_write = lp_min_receive_file_size() &&
3017 !srv_is_signing_active(smbd_server_conn);
3018 bool large_read = !srv_is_signing_active(smbd_server_conn);
3019 int encrypt_caps = 0;
3021 if (!lp_unix_extensions()) {
3022 return NT_STATUS_INVALID_LEVEL;
3025 switch (conn->encrypt_level) {
3031 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3034 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3035 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3036 large_write = false;
3042 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3043 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3045 /* We have POSIX ACLs, pathname, encryption,
3046 * large read/write, and locking capability. */
3048 SBIG_UINT(pdata,4,((uint64_t)(
3049 CIFS_UNIX_POSIX_ACLS_CAP|
3050 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3051 CIFS_UNIX_FCNTL_LOCKS_CAP|
3052 CIFS_UNIX_EXTATTR_CAP|
3053 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3055 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3057 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3061 case SMB_QUERY_POSIX_FS_INFO:
3064 vfs_statvfs_struct svfs;
3066 if (!lp_unix_extensions()) {
3067 return NT_STATUS_INVALID_LEVEL;
3070 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3074 SIVAL(pdata,0,svfs.OptimalTransferSize);
3075 SIVAL(pdata,4,svfs.BlockSize);
3076 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3077 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3078 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3079 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3080 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3081 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3082 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3084 } else if (rc == EOPNOTSUPP) {
3085 return NT_STATUS_INVALID_LEVEL;
3086 #endif /* EOPNOTSUPP */
3088 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3089 return NT_STATUS_DOS(ERRSRV, ERRerror);
3094 case SMB_QUERY_POSIX_WHOAMI:
3100 if (!lp_unix_extensions()) {
3101 return NT_STATUS_INVALID_LEVEL;
3104 if (max_data_bytes < 40) {
3105 return NT_STATUS_BUFFER_TOO_SMALL;
3108 /* We ARE guest if global_sid_Builtin_Guests is
3109 * in our list of SIDs.
3111 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3112 conn->server_info->ptok)) {
3113 flags |= SMB_WHOAMI_GUEST;
3116 /* We are NOT guest if global_sid_Authenticated_Users
3117 * is in our list of SIDs.
3119 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3120 conn->server_info->ptok)) {
3121 flags &= ~SMB_WHOAMI_GUEST;
3124 /* NOTE: 8 bytes for UID/GID, irrespective of native
3125 * platform size. This matches
3126 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3128 data_len = 4 /* flags */
3135 + 4 /* pad/reserved */
3136 + (conn->server_info->utok.ngroups * 8)
3138 + (conn->server_info->ptok->num_sids *
3142 SIVAL(pdata, 0, flags);
3143 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3145 (uint64_t)conn->server_info->utok.uid);
3146 SBIG_UINT(pdata, 16,
3147 (uint64_t)conn->server_info->utok.gid);
3150 if (data_len >= max_data_bytes) {
3151 /* Potential overflow, skip the GIDs and SIDs. */
3153 SIVAL(pdata, 24, 0); /* num_groups */
3154 SIVAL(pdata, 28, 0); /* num_sids */
3155 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3156 SIVAL(pdata, 36, 0); /* reserved */
3162 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3163 SIVAL(pdata, 28, conn->server_info->num_sids);
3165 /* We walk the SID list twice, but this call is fairly
3166 * infrequent, and I don't expect that it's performance
3167 * sensitive -- jpeach
3169 for (i = 0, sid_bytes = 0;
3170 i < conn->server_info->ptok->num_sids; ++i) {
3171 sid_bytes += ndr_size_dom_sid(
3172 &conn->server_info->ptok->user_sids[i],
3177 /* SID list byte count */
3178 SIVAL(pdata, 32, sid_bytes);
3180 /* 4 bytes pad/reserved - must be zero */
3181 SIVAL(pdata, 36, 0);
3185 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3186 SBIG_UINT(pdata, data_len,
3187 (uint64_t)conn->server_info->utok.groups[i]);
3193 i < conn->server_info->ptok->num_sids; ++i) {
3194 int sid_len = ndr_size_dom_sid(
3195 &conn->server_info->ptok->user_sids[i],
3199 sid_linearize(pdata + data_len, sid_len,
3200 &conn->server_info->ptok->user_sids[i]);
3201 data_len += sid_len;
3207 case SMB_MAC_QUERY_FS_INFO:
3209 * Thursby MAC extension... ONLY on NTFS filesystems
3210 * once we do streams then we don't need this
3212 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3214 SIVAL(pdata,84,0x100); /* Don't support mac... */
3219 return NT_STATUS_INVALID_LEVEL;
3222 *ret_data_len = data_len;
3223 return NT_STATUS_OK;
3226 /****************************************************************************
3227 Reply to a TRANS2_QFSINFO (query filesystem info).
3228 ****************************************************************************/
3230 static void call_trans2qfsinfo(connection_struct *conn,
3231 struct smb_request *req,
3232 char **pparams, int total_params,
3233 char **ppdata, int total_data,
3234 unsigned int max_data_bytes)
3236 char *params = *pparams;
3237 uint16_t info_level;
3242 if (total_params < 2) {
3243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3247 info_level = SVAL(params,0);
3249 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3250 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3251 DEBUG(0,("call_trans2qfsinfo: encryption required "
3252 "and info level 0x%x sent.\n",
3253 (unsigned int)info_level));
3254 exit_server_cleanly("encryption required "
3260 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3262 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
3263 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
3264 reply_doserror(req, ERRSRV, ERRinvdevice);
3268 status = smbd_do_qfsinfo(conn, req,
3273 if (!NT_STATUS_IS_OK(status)) {
3274 reply_nterror(req, status);
3278 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3281 DEBUG( 4, ( "%s info_level = %d\n",
3282 smb_fn_name(req->cmd), info_level) );
3287 /****************************************************************************
3288 Reply to a TRANS2_SETFSINFO (set filesystem info).
3289 ****************************************************************************/
3291 static void call_trans2setfsinfo(connection_struct *conn,
3292 struct smb_request *req,
3293 char **pparams, int total_params,
3294 char **ppdata, int total_data,
3295 unsigned int max_data_bytes)
3297 char *pdata = *ppdata;
3298 char *params = *pparams;
3301 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3304 if (total_params < 4) {
3305 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3311 info_level = SVAL(params,2);
3314 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3315 info_level != SMB_SET_CIFS_UNIX_INFO) {
3316 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3317 "info level (0x%x) on IPC$.\n",
3318 (unsigned int)info_level));
3319 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3324 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3325 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3326 DEBUG(0,("call_trans2setfsinfo: encryption required "
3327 "and info level 0x%x sent.\n",
3328 (unsigned int)info_level));
3329 exit_server_cleanly("encryption required "
3335 switch(info_level) {
3336 case SMB_SET_CIFS_UNIX_INFO:
3338 uint16 client_unix_major;
3339 uint16 client_unix_minor;
3340 uint32 client_unix_cap_low;
3341 uint32 client_unix_cap_high;
3343 if (!lp_unix_extensions()) {
3345 NT_STATUS_INVALID_LEVEL);
3349 /* There should be 12 bytes of capabilities set. */
3350 if (total_data < 8) {
3353 NT_STATUS_INVALID_PARAMETER);
3356 client_unix_major = SVAL(pdata,0);
3357 client_unix_minor = SVAL(pdata,2);
3358 client_unix_cap_low = IVAL(pdata,4);
3359 client_unix_cap_high = IVAL(pdata,8);
3360 /* Just print these values for now. */
3361 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3362 cap_low = 0x%x, cap_high = 0x%x\n",
3363 (unsigned int)client_unix_major,
3364 (unsigned int)client_unix_minor,
3365 (unsigned int)client_unix_cap_low,
3366 (unsigned int)client_unix_cap_high ));
3368 /* Here is where we must switch to posix pathname processing... */
3369 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3370 lp_set_posix_pathnames();
3371 mangle_change_to_posix();
3374 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3375 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3376 /* Client that knows how to do posix locks,
3377 * but not posix open/mkdir operations. Set a
3378 * default type for read/write checks. */
3380 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3386 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3389 size_t param_len = 0;
3390 size_t data_len = total_data;
3392 if (!lp_unix_extensions()) {
3395 NT_STATUS_INVALID_LEVEL);
3399 if (lp_smb_encrypt(SNUM(conn)) == false) {
3402 NT_STATUS_NOT_SUPPORTED);
3406 DEBUG( 4,("call_trans2setfsinfo: "
3407 "request transport encryption.\n"));
3409 status = srv_request_encryption_setup(conn,
3410 (unsigned char **)ppdata,
3412 (unsigned char **)pparams,
3415 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3416 !NT_STATUS_IS_OK(status)) {
3417 reply_nterror(req, status);
3421 send_trans2_replies(conn, req,
3428 if (NT_STATUS_IS_OK(status)) {
3429 /* Server-side transport
3430 * encryption is now *on*. */
3431 status = srv_encryption_start(conn);
3432 if (!NT_STATUS_IS_OK(status)) {
3433 exit_server_cleanly(
3434 "Failure in setting "
3435 "up encrypted transport");
3441 case SMB_FS_QUOTA_INFORMATION:
3443 files_struct *fsp = NULL;
3444 SMB_NTQUOTA_STRUCT quotas;
3446 ZERO_STRUCT(quotas);
3449 if ((conn->server_info->utok.uid != sec_initial_uid())
3450 ||!CAN_WRITE(conn)) {
3451 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3452 lp_servicename(SNUM(conn)),
3453 conn->server_info->unix_name));
3454 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3458 /* note: normaly there're 48 bytes,
3459 * but we didn't use the last 6 bytes for now
3462 fsp = file_fsp(req, SVAL(params,0));
3464 if (!check_fsp_ntquota_handle(conn, req,
3466 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3468 req, NT_STATUS_INVALID_HANDLE);
3472 if (total_data < 42) {
3473 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3477 NT_STATUS_INVALID_PARAMETER);
3481 /* unknown_1 24 NULL bytes in pdata*/
3483 /* the soft quotas 8 bytes (uint64_t)*/
3484 quotas.softlim = (uint64_t)IVAL(pdata,24);
3485 #ifdef LARGE_SMB_OFF_T
3486 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3487 #else /* LARGE_SMB_OFF_T */
3488 if ((IVAL(pdata,28) != 0)&&
3489 ((quotas.softlim != 0xFFFFFFFF)||
3490 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3491 /* more than 32 bits? */
3494 NT_STATUS_INVALID_PARAMETER);
3497 #endif /* LARGE_SMB_OFF_T */
3499 /* the hard quotas 8 bytes (uint64_t)*/
3500 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3501 #ifdef LARGE_SMB_OFF_T
3502 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3503 #else /* LARGE_SMB_OFF_T */
3504 if ((IVAL(pdata,36) != 0)&&
3505 ((quotas.hardlim != 0xFFFFFFFF)||
3506 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3507 /* more than 32 bits? */
3510 NT_STATUS_INVALID_PARAMETER);
3513 #endif /* LARGE_SMB_OFF_T */
3515 /* quota_flags 2 bytes **/
3516 quotas.qflags = SVAL(pdata,40);
3518 /* unknown_2 6 NULL bytes follow*/
3520 /* now set the quotas */
3521 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3522 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3523 reply_nterror(req, map_nt_error_from_unix(errno));
3530 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3532 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3538 * sending this reply works fine,
3539 * but I'm not sure it's the same
3540 * like windows do...
3543 reply_outbuf(req, 10, 0);
3546 #if defined(HAVE_POSIX_ACLS)
3547 /****************************************************************************
3548 Utility function to count the number of entries in a POSIX acl.
3549 ****************************************************************************/
3551 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3553 unsigned int ace_count = 0;
3554 int entry_id = SMB_ACL_FIRST_ENTRY;
3555 SMB_ACL_ENTRY_T entry;
3557 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3559 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3560 entry_id = SMB_ACL_NEXT_ENTRY;
3567 /****************************************************************************
3568 Utility function to marshall a POSIX acl into wire format.
3569 ****************************************************************************/
3571 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3573 int entry_id = SMB_ACL_FIRST_ENTRY;
3574 SMB_ACL_ENTRY_T entry;
3576 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3577 SMB_ACL_TAG_T tagtype;
3578 SMB_ACL_PERMSET_T permset;
3579 unsigned char perms = 0;
3580 unsigned int own_grp;
3583 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3584 entry_id = SMB_ACL_NEXT_ENTRY;
3587 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3588 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3592 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3593 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3597 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3598 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3599 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3601 SCVAL(pdata,1,perms);
3604 case SMB_ACL_USER_OBJ:
3605 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3606 own_grp = (unsigned int)pst->st_ex_uid;
3607 SIVAL(pdata,2,own_grp);
3612 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3614 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3617 own_grp = (unsigned int)*puid;
3618 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3619 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3620 SIVAL(pdata,2,own_grp);
3624 case SMB_ACL_GROUP_OBJ:
3625 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3626 own_grp = (unsigned int)pst->st_ex_gid;
3627 SIVAL(pdata,2,own_grp);
3632 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3634 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3637 own_grp = (unsigned int)*pgid;
3638 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3639 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3640 SIVAL(pdata,2,own_grp);
3645 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3646 SIVAL(pdata,2,0xFFFFFFFF);
3647 SIVAL(pdata,6,0xFFFFFFFF);
3650 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3651 SIVAL(pdata,2,0xFFFFFFFF);
3652 SIVAL(pdata,6,0xFFFFFFFF);
3655 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3658 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3665 /****************************************************************************
3666 Store the FILE_UNIX_BASIC info.
3667 ****************************************************************************/
3669 static char *store_file_unix_basic(connection_struct *conn,
3672 const SMB_STRUCT_STAT *psbuf)
3674 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3675 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3677 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3680 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3683 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3684 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3685 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3688 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3692 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3696 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3699 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3703 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3707 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3710 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3714 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3721 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3722 * the chflags(2) (or equivalent) flags.
3724 * XXX: this really should be behind the VFS interface. To do this, we would
3725 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3726 * Each VFS module could then implement its own mapping as appropriate for the
3727 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3729 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3733 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3737 { UF_IMMUTABLE, EXT_IMMUTABLE },
3741 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3745 { UF_HIDDEN, EXT_HIDDEN },
3748 /* Do not remove. We need to guarantee that this array has at least one
3749 * entry to build on HP-UX.
3755 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3756 uint32 *smb_fflags, uint32 *smb_fmask)
3760 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3761 *smb_fmask |= info2_flags_map[i].smb_fflag;
3762 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3763 *smb_fflags |= info2_flags_map[i].smb_fflag;
3768 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3769 const uint32 smb_fflags,
3770 const uint32 smb_fmask,
3773 uint32 max_fmask = 0;
3776 *stat_fflags = psbuf->st_ex_flags;
3778 /* For each flags requested in smb_fmask, check the state of the
3779 * corresponding flag in smb_fflags and set or clear the matching
3783 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3784 max_fmask |= info2_flags_map[i].smb_fflag;
3785 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3786 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3787 *stat_fflags |= info2_flags_map[i].stat_fflag;
3789 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3794 /* If smb_fmask is asking to set any bits that are not supported by
3795 * our flag mappings, we should fail.
3797 if ((smb_fmask & max_fmask) != smb_fmask) {
3805 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3806 * of file flags and birth (create) time.
3808 static char *store_file_unix_basic_info2(connection_struct *conn,
3811 const SMB_STRUCT_STAT *psbuf)
3813 uint32 file_flags = 0;
3814 uint32 flags_mask = 0;
3816 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3818 /* Create (birth) time 64 bit */
3819 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3822 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3823 SIVAL(pdata, 0, file_flags); /* flags */
3824 SIVAL(pdata, 4, flags_mask); /* mask */
3830 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3831 const struct stream_struct *streams,
3833 unsigned int max_data_bytes,
3834 unsigned int *data_size)
3837 unsigned int ofs = 0;
3839 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3840 unsigned int next_offset;
3842 smb_ucs2_t *namebuf;
3844 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3845 streams[i].name, &namelen) ||
3848 return NT_STATUS_INVALID_PARAMETER;
3852 * name_buf is now null-terminated, we need to marshall as not
3858 SIVAL(data, ofs+4, namelen);
3859 SOFF_T(data, ofs+8, streams[i].size);
3860 SOFF_T(data, ofs+16, streams[i].alloc_size);
3861 memcpy(data+ofs+24, namebuf, namelen);
3862 TALLOC_FREE(namebuf);
3864 next_offset = ofs + 24 + namelen;
3866 if (i == num_streams-1) {
3867 SIVAL(data, ofs, 0);
3870 unsigned int align = ndr_align_size(next_offset, 8);
3872 memset(data+next_offset, 0, align);
3873 next_offset += align;
3875 SIVAL(data, ofs, next_offset - ofs);
3884 return NT_STATUS_OK;
3887 /****************************************************************************
3888 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3889 ****************************************************************************/
3891 static void call_trans2qpipeinfo(connection_struct *conn,
3892 struct smb_request *req,
3893 unsigned int tran_call,
3894 char **pparams, int total_params,
3895 char **ppdata, int total_data,
3896 unsigned int max_data_bytes)
3898 char *params = *pparams;
3899 char *pdata = *ppdata;
3900 unsigned int data_size = 0;
3901 unsigned int param_size = 2;
3906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3910 if (total_params < 4) {
3911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3915 fsp = file_fsp(req, SVAL(params,0));
3916 if (!fsp_is_np(fsp)) {
3917 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3921 info_level = SVAL(params,2);
3923 *pparams = (char *)SMB_REALLOC(*pparams,2);
3924 if (*pparams == NULL) {
3925 reply_nterror(req, NT_STATUS_NO_MEMORY);
3930 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3931 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3932 if (*ppdata == NULL ) {
3933 reply_nterror(req, NT_STATUS_NO_MEMORY);
3938 switch (info_level) {
3939 case SMB_FILE_STANDARD_INFORMATION:
3941 SOFF_T(pdata,0,4096LL);
3948 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3952 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3958 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3959 TALLOC_CTX *mem_ctx,
3960 uint16_t info_level,
3962 const struct smb_filename *smb_fname,
3963 bool delete_pending,
3964 struct timespec write_time_ts,
3966 struct ea_list *ea_list,
3967 int lock_data_count,
3970 unsigned int max_data_bytes,
3972 unsigned int *pdata_size)
3974 char *pdata = *ppdata;
3975 char *dstart, *dend;
3976 unsigned int data_size;
3977 struct timespec create_time_ts, mtime_ts, atime_ts;
3978 time_t create_time, mtime, atime;
3979 SMB_STRUCT_STAT sbuf;
3987 uint64_t file_size = 0;
3989 uint64_t allocation_size = 0;
3990 uint64_t file_index = 0;
3991 uint32_t access_mask = 0;
3993 sbuf = smb_fname->st;
3995 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3996 return NT_STATUS_INVALID_LEVEL;
3999 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
4000 if (!NT_STATUS_IS_OK(status)) {
4004 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4005 fname, fsp ? fsp->fnum : -1, info_level, max_data_bytes));
4008 mode = dos_mode_msdfs(conn, smb_fname);
4010 mode = dos_mode(conn, smb_fname);
4013 mode = FILE_ATTRIBUTE_NORMAL;
4015 nlink = sbuf.st_ex_nlink;
4017 if (nlink && (mode&aDIR)) {
4021 if ((nlink > 0) && delete_pending) {
4025 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4026 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4027 if (*ppdata == NULL) {
4028 return NT_STATUS_NO_MEMORY;
4032 dend = dstart + data_size - 1;
4034 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4035 update_stat_ex_mtime(&sbuf, write_time_ts);
4038 create_time_ts = sbuf.st_ex_btime;
4039 mtime_ts = sbuf.st_ex_mtime;
4040 atime_ts = sbuf.st_ex_atime;
4042 if (lp_dos_filetime_resolution(SNUM(conn))) {
4043 dos_filetime_timespec(&create_time_ts);
4044 dos_filetime_timespec(&mtime_ts);
4045 dos_filetime_timespec(&atime_ts);
4048 create_time = convert_timespec_to_time_t(create_time_ts);
4049 mtime = convert_timespec_to_time_t(mtime_ts);
4050 atime = convert_timespec_to_time_t(atime_ts);
4052 p = strrchr_m(smb_fname->base_name,'/');
4054 base_name = smb_fname->base_name;
4058 /* NT expects the name to be in an exact form of the *full*
4059 filename. See the trans2 torture test */
4060 if (ISDOT(base_name)) {
4061 dos_fname = talloc_strdup(mem_ctx, "\\");
4063 return NT_STATUS_NO_MEMORY;
4066 dos_fname = talloc_asprintf(mem_ctx,
4070 return NT_STATUS_NO_MEMORY;
4072 string_replace(dos_fname, '/', '\\');
4075 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4078 /* Do we have this path open ? */
4080 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4081 fsp1 = file_find_di_first(fileid);
4082 if (fsp1 && fsp1->initial_allocation_size) {
4083 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4087 if (!(mode & aDIR)) {
4088 file_size = get_file_size_stat(&sbuf);
4092 pos = fsp->fh->position_information;
4096 access_mask = fsp->access_mask;
4098 /* GENERIC_EXECUTE mapping from Windows */
4099 access_mask = 0x12019F;
4102 /* This should be an index number - looks like
4105 I think this causes us to fail the IFSKIT
4106 BasicFileInformationTest. -tpot */
4107 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4108 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4110 switch (info_level) {
4111 case SMB_INFO_STANDARD:
4112 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4114 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4115 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4116 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4117 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4118 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4119 SSVAL(pdata,l1_attrFile,mode);
4122 case SMB_INFO_QUERY_EA_SIZE:
4124 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4125 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4127 srv_put_dos_date2(pdata,0,create_time);
4128 srv_put_dos_date2(pdata,4,atime);
4129 srv_put_dos_date2(pdata,8,mtime); /* write time */
4130 SIVAL(pdata,12,(uint32)file_size);
4131 SIVAL(pdata,16,(uint32)allocation_size);
4132 SSVAL(pdata,20,mode);
4133 SIVAL(pdata,22,ea_size);
4137 case SMB_INFO_IS_NAME_VALID:
4138 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4140 /* os/2 needs this ? really ?*/
4141 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4143 /* This is only reached for qpathinfo */
4147 case SMB_INFO_QUERY_EAS_FROM_LIST:
4149 size_t total_ea_len = 0;
4150 struct ea_list *ea_file_list = NULL;
4152 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4154 ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4155 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4157 if (!ea_list || (total_ea_len > data_size)) {
4159 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4163 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4167 case SMB_INFO_QUERY_ALL_EAS:
4169 /* We have data_size bytes to put EA's into. */
4170 size_t total_ea_len = 0;
4172 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4174 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4175 if (!ea_list || (total_ea_len > data_size)) {
4177 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4181 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4185 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4187 /* We have data_size bytes to put EA's into. */
4188 size_t total_ea_len = 0;
4189 struct ea_list *ea_file_list = NULL;
4191 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4193 /*TODO: add filtering and index handling */
4195 ea_file_list = get_ea_list_from_file(mem_ctx,
4199 if (!ea_file_list) {
4200 return NT_STATUS_NO_EAS_ON_FILE;
4203 status = fill_ea_chained_buffer(mem_ctx,
4207 conn, ea_file_list);
4208 if (!NT_STATUS_IS_OK(status)) {
4214 case SMB_FILE_BASIC_INFORMATION:
4215 case SMB_QUERY_FILE_BASIC_INFO:
4217 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4218 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4219 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4221 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4225 put_long_date_timespec(pdata,create_time_ts);
4226 put_long_date_timespec(pdata+8,atime_ts);
4227 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4228 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4229 SIVAL(pdata,32,mode);
4231 DEBUG(5,("SMB_QFBI - "));
4232 DEBUG(5,("create: %s ", ctime(&create_time)));
4233 DEBUG(5,("access: %s ", ctime(&atime)));
4234 DEBUG(5,("write: %s ", ctime(&mtime)));
4235 DEBUG(5,("change: %s ", ctime(&mtime)));
4236 DEBUG(5,("mode: %x\n", mode));
4239 case SMB_FILE_STANDARD_INFORMATION:
4240 case SMB_QUERY_FILE_STANDARD_INFO:
4242 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4244 SOFF_T(pdata,0,allocation_size);
4245 SOFF_T(pdata,8,file_size);
4246 SIVAL(pdata,16,nlink);
4247 SCVAL(pdata,20,delete_pending?1:0);
4248 SCVAL(pdata,21,(mode&aDIR)?1:0);
4249 SSVAL(pdata,22,0); /* Padding. */
4252 case SMB_FILE_EA_INFORMATION:
4253 case SMB_QUERY_FILE_EA_INFO:
4255 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4256 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4258 SIVAL(pdata,0,ea_size);
4262 /* Get the 8.3 name - used if NT SMB was negotiated. */
4263 case SMB_QUERY_FILE_ALT_NAME_INFO:
4264 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4267 char mangled_name[13];
4268 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4269 if (!name_to_8_3(base_name,mangled_name,
4270 True,conn->params)) {
4271 return NT_STATUS_NO_MEMORY;
4273 len = srvstr_push(dstart, flags2,
4274 pdata+4, mangled_name,
4275 PTR_DIFF(dend, pdata+4),
4277 data_size = 4 + len;
4282 case SMB_QUERY_FILE_NAME_INFO:
4286 this must be *exactly* right for ACLs on mapped drives to work
4288 len = srvstr_push(dstart, flags2,
4290 PTR_DIFF(dend, pdata+4),
4292 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4293 data_size = 4 + len;
4298 case SMB_FILE_ALLOCATION_INFORMATION:
4299 case SMB_QUERY_FILE_ALLOCATION_INFO:
4300 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4302 SOFF_T(pdata,0,allocation_size);
4305 case SMB_FILE_END_OF_FILE_INFORMATION:
4306 case SMB_QUERY_FILE_END_OF_FILEINFO:
4307 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4309 SOFF_T(pdata,0,file_size);
4312 case SMB_QUERY_FILE_ALL_INFO:
4313 case SMB_FILE_ALL_INFORMATION:
4316 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4317 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4318 put_long_date_timespec(pdata,create_time_ts);
4319 put_long_date_timespec(pdata+8,atime_ts);
4320 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4321 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4322 SIVAL(pdata,32,mode);
4323 SIVAL(pdata,36,0); /* padding. */
4325 SOFF_T(pdata,0,allocation_size);
4326 SOFF_T(pdata,8,file_size);
4327 SIVAL(pdata,16,nlink);
4328 SCVAL(pdata,20,delete_pending);
4329 SCVAL(pdata,21,(mode&aDIR)?1:0);
4332 SIVAL(pdata,0,ea_size);
4333 pdata += 4; /* EA info */
4334 len = srvstr_push(dstart, flags2,
4336 PTR_DIFF(dend, pdata+4),
4340 data_size = PTR_DIFF(pdata,(*ppdata));
4344 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4347 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4348 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4349 put_long_date_timespec(pdata+0x00,create_time_ts);
4350 put_long_date_timespec(pdata+0x08,atime_ts);
4351 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4352 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4353 SIVAL(pdata, 0x20, mode);
4354 SIVAL(pdata, 0x24, 0); /* padding. */
4355 SBVAL(pdata, 0x28, allocation_size);
4356 SBVAL(pdata, 0x30, file_size);
4357 SIVAL(pdata, 0x38, nlink);
4358 SCVAL(pdata, 0x3C, delete_pending);
4359 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4360 SSVAL(pdata, 0x3E, 0); /* padding */
4361 SBVAL(pdata, 0x40, file_index);
4362 SIVAL(pdata, 0x48, ea_size);
4363 SIVAL(pdata, 0x4C, access_mask);
4364 SBVAL(pdata, 0x50, pos);
4365 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4366 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4370 len = srvstr_push(dstart, flags2,
4372 PTR_DIFF(dend, pdata+4),
4376 data_size = PTR_DIFF(pdata,(*ppdata));
4379 case SMB_FILE_INTERNAL_INFORMATION:
4381 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4382 SBVAL(pdata, 0, file_index);
4386 case SMB_FILE_ACCESS_INFORMATION:
4387 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4388 SIVAL(pdata, 0, access_mask);
4392 case SMB_FILE_NAME_INFORMATION:
4393 /* Pathname with leading '\'. */
4396 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4397 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4398 SIVAL(pdata,0,byte_len);
4399 data_size = 4 + byte_len;
4403 case SMB_FILE_DISPOSITION_INFORMATION:
4404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4406 SCVAL(pdata,0,delete_pending);
4409 case SMB_FILE_POSITION_INFORMATION:
4410 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4412 SOFF_T(pdata,0,pos);
4415 case SMB_FILE_MODE_INFORMATION:
4416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4417 SIVAL(pdata,0,mode);
4421 case SMB_FILE_ALIGNMENT_INFORMATION:
4422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4423 SIVAL(pdata,0,0); /* No alignment needed. */
4428 * NT4 server just returns "invalid query" to this - if we try
4429 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4432 /* The first statement above is false - verified using Thursby
4433 * client against NT4 -- gcolley.
4435 case SMB_QUERY_FILE_STREAM_INFO:
4436 case SMB_FILE_STREAM_INFORMATION: {
4437 unsigned int num_streams;
4438 struct stream_struct *streams;
4440 DEBUG(10,("smbd_do_qfilepathinfo: "
4441 "SMB_FILE_STREAM_INFORMATION\n"));
4443 status = SMB_VFS_STREAMINFO(
4444 conn, fsp, fname, talloc_tos(),
4445 &num_streams, &streams);
4447 if (!NT_STATUS_IS_OK(status)) {
4448 DEBUG(10, ("could not get stream info: %s\n",
4449 nt_errstr(status)));
4453 status = marshall_stream_info(num_streams, streams,
4454 pdata, max_data_bytes,
4457 if (!NT_STATUS_IS_OK(status)) {
4458 DEBUG(10, ("marshall_stream_info failed: %s\n",
4459 nt_errstr(status)));
4463 TALLOC_FREE(streams);
4467 case SMB_QUERY_COMPRESSION_INFO:
4468 case SMB_FILE_COMPRESSION_INFORMATION:
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4470 SOFF_T(pdata,0,file_size);
4471 SIVAL(pdata,8,0); /* ??? */
4472 SIVAL(pdata,12,0); /* ??? */
4476 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4477 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4478 put_long_date_timespec(pdata,create_time_ts);
4479 put_long_date_timespec(pdata+8,atime_ts);
4480 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4481 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4482 SOFF_T(pdata,32,allocation_size);
4483 SOFF_T(pdata,40,file_size);
4484 SIVAL(pdata,48,mode);
4485 SIVAL(pdata,52,0); /* ??? */
4489 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4490 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4491 SIVAL(pdata,0,mode);
4497 * CIFS UNIX Extensions.
4500 case SMB_QUERY_FILE_UNIX_BASIC:
4502 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4503 data_size = PTR_DIFF(pdata,(*ppdata));
4507 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4509 for (i=0; i<100; i++)
4510 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4516 case SMB_QUERY_FILE_UNIX_INFO2:
4518 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4519 data_size = PTR_DIFF(pdata,(*ppdata));
4523 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4525 for (i=0; i<100; i++)
4526 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4532 case SMB_QUERY_FILE_UNIX_LINK:
4535 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4538 return NT_STATUS_NO_MEMORY;
4541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4543 if(!S_ISLNK(sbuf.st_ex_mode)) {
4544 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4547 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4549 len = SMB_VFS_READLINK(conn,fname,
4552 return map_nt_error_from_unix(errno);
4555 len = srvstr_push(dstart, flags2,
4557 PTR_DIFF(dend, pdata),
4560 data_size = PTR_DIFF(pdata,(*ppdata));
4565 #if defined(HAVE_POSIX_ACLS)
4566 case SMB_QUERY_POSIX_ACL:
4568 SMB_ACL_T file_acl = NULL;
4569 SMB_ACL_T def_acl = NULL;
4570 uint16 num_file_acls = 0;
4571 uint16 num_def_acls = 0;
4573 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4574 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4576 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4579 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4580 DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4582 return NT_STATUS_NOT_IMPLEMENTED;
4585 if (S_ISDIR(sbuf.st_ex_mode)) {
4586 if (fsp && fsp->is_directory) {
4587 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4589 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4591 def_acl = free_empty_sys_acl(conn, def_acl);
4594 num_file_acls = count_acl_entries(conn, file_acl);
4595 num_def_acls = count_acl_entries(conn, def_acl);
4597 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4598 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4600 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4601 SMB_POSIX_ACL_HEADER_SIZE) ));
4603 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4606 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4608 return NT_STATUS_BUFFER_TOO_SMALL;
4611 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4612 SSVAL(pdata,2,num_file_acls);
4613 SSVAL(pdata,4,num_def_acls);
4614 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4616 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4619 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4621 return NT_STATUS_INTERNAL_ERROR;
4623 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4625 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4628 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4630 return NT_STATUS_INTERNAL_ERROR;
4634 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4637 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4639 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4645 case SMB_QUERY_POSIX_LOCK:
4650 enum brl_type lock_type;
4652 /* We need an open file with a real fd for this. */
4653 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4654 return NT_STATUS_INVALID_LEVEL;
4657 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4658 return NT_STATUS_INVALID_PARAMETER;
4661 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4662 case POSIX_LOCK_TYPE_READ:
4663 lock_type = READ_LOCK;
4665 case POSIX_LOCK_TYPE_WRITE:
4666 lock_type = WRITE_LOCK;
4668 case POSIX_LOCK_TYPE_UNLOCK:
4670 /* There's no point in asking for an unlock... */
4671 return NT_STATUS_INVALID_PARAMETER;
4674 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4675 #if defined(HAVE_LONGLONG)
4676 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4677 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4678 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4679 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4680 #else /* HAVE_LONGLONG */
4681 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4682 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4683 #endif /* HAVE_LONGLONG */
4685 status = query_lock(fsp,
4692 if (ERROR_WAS_LOCK_DENIED(status)) {
4693 /* Here we need to report who has it locked... */
4694 data_size = POSIX_LOCK_DATA_SIZE;
4696 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4697 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4698 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4699 #if defined(HAVE_LONGLONG)
4700 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4701 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4702 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4703 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4704 #else /* HAVE_LONGLONG */
4705 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4706 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4707 #endif /* HAVE_LONGLONG */
4709 } else if (NT_STATUS_IS_OK(status)) {
4710 /* For success we just return a copy of what we sent
4711 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4712 data_size = POSIX_LOCK_DATA_SIZE;
4713 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4714 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4722 return NT_STATUS_INVALID_LEVEL;
4725 *pdata_size = data_size;
4726 return NT_STATUS_OK;
4729 /****************************************************************************
4730 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4731 file name or file id).
4732 ****************************************************************************/
4734 static void call_trans2qfilepathinfo(connection_struct *conn,
4735 struct smb_request *req,
4736 unsigned int tran_call,
4737 char **pparams, int total_params,
4738 char **ppdata, int total_data,
4739 unsigned int max_data_bytes)
4741 char *params = *pparams;
4742 char *pdata = *ppdata;
4744 unsigned int data_size = 0;
4745 unsigned int param_size = 2;
4747 struct smb_filename *smb_fname = NULL;
4748 bool delete_pending = False;
4749 struct timespec write_time_ts;
4750 files_struct *fsp = NULL;
4751 struct file_id fileid;
4752 struct ea_list *ea_list = NULL;
4753 int lock_data_count = 0;
4754 char *lock_data = NULL;
4755 bool ms_dfs_link = false;
4756 NTSTATUS status = NT_STATUS_OK;
4759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4763 ZERO_STRUCT(write_time_ts);
4765 if (tran_call == TRANSACT2_QFILEINFO) {
4766 if (total_params < 4) {
4767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4772 call_trans2qpipeinfo(conn, req, tran_call,
4773 pparams, total_params,
4779 fsp = file_fsp(req, SVAL(params,0));
4780 info_level = SVAL(params,2);
4782 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4784 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4785 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4789 /* Initial check for valid fsp ptr. */
4790 if (!check_fsp_open(conn, req, fsp)) {
4794 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
4796 reply_nterror(req, NT_STATUS_NO_MEMORY);
4800 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
4802 if (!NT_STATUS_IS_OK(status)) {
4803 reply_nterror(req, status);
4807 if(fsp->fake_file_handle) {
4809 * This is actually for the QUOTA_FAKE_FILE --metze
4812 /* We know this name is ok, it's already passed the checks. */
4814 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4816 * This is actually a QFILEINFO on a directory
4817 * handle (returned from an NT SMB). NT5.0 seems
4818 * to do this call. JRA.
4821 if (INFO_LEVEL_IS_UNIX(info_level)) {
4822 /* Always do lstat for UNIX calls. */
4823 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4824 DEBUG(3,("call_trans2qfilepathinfo: "
4825 "SMB_VFS_LSTAT of %s failed "
4827 smb_fname_str_dbg(smb_fname),
4830 map_nt_error_from_unix(errno));
4833 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4834 DEBUG(3,("call_trans2qfilepathinfo: "
4835 "SMB_VFS_STAT of %s failed (%s)\n",
4836 smb_fname_str_dbg(smb_fname),
4839 map_nt_error_from_unix(errno));
4843 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4844 get_file_infos(fileid, &delete_pending, &write_time_ts);
4847 * Original code - this is an open file.
4849 if (!check_fsp(conn, req, fsp)) {
4853 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4854 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4855 fsp->fnum, strerror(errno)));
4857 map_nt_error_from_unix(errno));
4860 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4861 get_file_infos(fileid, &delete_pending, &write_time_ts);
4866 if (total_params < 7) {
4867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4871 info_level = SVAL(params,0);
4873 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4875 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4876 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4880 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4882 STR_TERMINATE, &status);
4883 if (!NT_STATUS_IS_OK(status)) {
4884 reply_nterror(req, status);
4888 status = filename_convert(req,
4890 req->flags2 & FLAGS2_DFS_PATHNAMES,
4894 if (!NT_STATUS_IS_OK(status)) {
4895 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4896 reply_botherror(req,
4897 NT_STATUS_PATH_NOT_COVERED,
4898 ERRSRV, ERRbadpath);
4901 reply_nterror(req, status);
4905 /* If this is a stream, check if there is a delete_pending. */
4906 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4907 && is_ntfs_stream_smb_fname(smb_fname)) {
4908 struct smb_filename *smb_fname_base = NULL;
4910 /* Create an smb_filename with stream_name == NULL. */
4912 create_synthetic_smb_fname(talloc_tos(),
4913 smb_fname->base_name,
4916 if (!NT_STATUS_IS_OK(status)) {
4917 reply_nterror(req, status);
4921 if (INFO_LEVEL_IS_UNIX(info_level)) {
4922 /* Always do lstat for UNIX calls. */
4923 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4924 DEBUG(3,("call_trans2qfilepathinfo: "
4925 "SMB_VFS_LSTAT of %s failed "
4927 smb_fname_str_dbg(smb_fname_base),
4929 TALLOC_FREE(smb_fname_base);
4931 map_nt_error_from_unix(errno));
4935 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4936 DEBUG(3,("call_trans2qfilepathinfo: "
4937 "fileinfo of %s failed "
4939 smb_fname_str_dbg(smb_fname_base),
4941 TALLOC_FREE(smb_fname_base);
4943 map_nt_error_from_unix(errno));
4948 fileid = vfs_file_id_from_sbuf(conn,
4949 &smb_fname_base->st);
4950 TALLOC_FREE(smb_fname_base);
4951 get_file_infos(fileid, &delete_pending, NULL);
4952 if (delete_pending) {
4953 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4958 if (INFO_LEVEL_IS_UNIX(info_level)) {
4959 /* Always do lstat for UNIX calls. */
4960 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4961 DEBUG(3,("call_trans2qfilepathinfo: "
4962 "SMB_VFS_LSTAT of %s failed (%s)\n",
4963 smb_fname_str_dbg(smb_fname),
4966 map_nt_error_from_unix(errno));
4970 } else if (!VALID_STAT(smb_fname->st) &&
4971 SMB_VFS_STAT(conn, smb_fname) &&
4972 (info_level != SMB_INFO_IS_NAME_VALID)) {
4973 ms_dfs_link = check_msdfs_link(conn, fname,
4977 DEBUG(3,("call_trans2qfilepathinfo: "
4978 "SMB_VFS_STAT of %s failed (%s)\n",
4979 smb_fname_str_dbg(smb_fname),
4982 map_nt_error_from_unix(errno));
4987 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4988 get_file_infos(fileid, &delete_pending, &write_time_ts);
4989 if (delete_pending) {
4990 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4995 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4996 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4998 /* Pull out any data sent here before we realloc. */
4999 switch (info_level) {
5000 case SMB_INFO_QUERY_EAS_FROM_LIST:
5002 /* Pull any EA list from the data portion. */
5005 if (total_data < 4) {
5007 req, NT_STATUS_INVALID_PARAMETER);
5010 ea_size = IVAL(pdata,0);
5012 if (total_data > 0 && ea_size != total_data) {
5013 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5014 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5016 req, NT_STATUS_INVALID_PARAMETER);
5020 if (!lp_ea_support(SNUM(conn))) {
5021 reply_doserror(req, ERRDOS,
5022 ERReasnotsupported);
5026 /* Pull out the list of names. */
5027 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5030 req, NT_STATUS_INVALID_PARAMETER);
5036 case SMB_QUERY_POSIX_LOCK:
5038 if (fsp == NULL || fsp->fh->fd == -1) {
5039 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5043 if (total_data != POSIX_LOCK_DATA_SIZE) {
5045 req, NT_STATUS_INVALID_PARAMETER);
5049 /* Copy the lock range data. */
5050 lock_data = (char *)TALLOC_MEMDUP(
5051 req, pdata, total_data);
5053 reply_nterror(req, NT_STATUS_NO_MEMORY);
5056 lock_data_count = total_data;
5062 *pparams = (char *)SMB_REALLOC(*pparams,2);
5063 if (*pparams == NULL) {
5064 reply_nterror(req, NT_STATUS_NO_MEMORY);
5071 * draft-leach-cifs-v1-spec-02.txt
5072 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5075 * The requested information is placed in the Data portion of the
5076 * transaction response. For the information levels greater than 0x100,
5077 * the transaction response has 1 parameter word which should be
5078 * ignored by the client.
5080 * However Windows only follows this rule for the IS_NAME_VALID call.
5082 switch (info_level) {
5083 case SMB_INFO_IS_NAME_VALID:
5088 if ((info_level & 0xFF00) == 0xFF00) {
5090 * We use levels that start with 0xFF00
5091 * internally to represent SMB2 specific levels
5093 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5097 status = smbd_do_qfilepathinfo(conn, req, info_level,
5099 delete_pending, write_time_ts,
5100 ms_dfs_link, ea_list,
5101 lock_data_count, lock_data,
5102 req->flags2, max_data_bytes,
5103 ppdata, &data_size);
5104 if (!NT_STATUS_IS_OK(status)) {
5105 reply_nterror(req, status);
5109 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5115 /****************************************************************************
5116 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5118 ****************************************************************************/
5120 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5121 connection_struct *conn,
5122 const struct smb_filename *smb_fname_old,
5123 const struct smb_filename *smb_fname_new)
5125 char *oldname = NULL;
5126 char *newname = NULL;
5127 NTSTATUS status = NT_STATUS_OK;
5129 /* source must already exist. */
5130 if (!VALID_STAT(smb_fname_old->st)) {
5131 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5134 /* Disallow if newname already exists. */
5135 if (VALID_STAT(smb_fname_new->st)) {
5136 return NT_STATUS_OBJECT_NAME_COLLISION;
5139 /* No links from a directory. */
5140 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5141 return NT_STATUS_FILE_IS_A_DIRECTORY;
5144 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
5145 if (!NT_STATUS_IS_OK(status)) {
5148 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
5149 if (!NT_STATUS_IS_OK(status)) {
5153 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
5155 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
5156 status = map_nt_error_from_unix(errno);
5157 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5158 nt_errstr(status), newname, oldname));
5161 TALLOC_FREE(newname);
5162 TALLOC_FREE(oldname);
5166 /****************************************************************************
5167 Deal with setting the time from any of the setfilepathinfo functions.
5168 ****************************************************************************/
5170 NTSTATUS smb_set_file_time(connection_struct *conn,
5172 const struct smb_filename *smb_fname,
5173 struct smb_file_time *ft,
5174 bool setting_write_time)
5176 struct smb_filename *smb_fname_base = NULL;
5178 FILE_NOTIFY_CHANGE_LAST_ACCESS
5179 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5182 if (!VALID_STAT(smb_fname->st)) {
5183 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5186 /* get some defaults (no modifications) if any info is zero or -1. */
5187 if (null_timespec(ft->atime)) {
5188 ft->atime= smb_fname->st.st_ex_atime;
5189 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5192 if (null_timespec(ft->mtime)) {
5193 ft->mtime = smb_fname->st.st_ex_mtime;
5194 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5197 if (!setting_write_time) {
5198 /* ft->mtime comes from change time, not write time. */
5199 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5202 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5203 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5204 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5205 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5206 if (!null_timespec(ft->create_time)) {
5207 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5208 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5212 * Try and set the times of this file if
5213 * they are different from the current values.
5217 struct timespec mts = smb_fname->st.st_ex_mtime;
5218 struct timespec ats = smb_fname->st.st_ex_atime;
5219 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5220 (timespec_compare(&ft->mtime, &mts) == 0)) {
5221 return NT_STATUS_OK;
5225 if (setting_write_time) {
5227 * This was a Windows setfileinfo on an open file.
5228 * NT does this a lot. We also need to
5229 * set the time here, as it can be read by
5230 * FindFirst/FindNext and with the patch for bug #2045
5231 * in smbd/fileio.c it ensures that this timestamp is
5232 * kept sticky even after a write. We save the request
5233 * away and will set it on file close and after a write. JRA.
5236 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5237 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5240 if (fsp->base_fsp) {
5241 set_sticky_write_time_fsp(fsp->base_fsp,
5244 set_sticky_write_time_fsp(fsp, ft->mtime);
5247 set_sticky_write_time_path(
5248 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5253 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5255 /* Always call ntimes on the base, even if a stream was passed in. */
5256 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5257 NULL, &smb_fname->st,
5259 if (!NT_STATUS_IS_OK(status)) {
5263 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5264 TALLOC_FREE(smb_fname_base);
5265 return map_nt_error_from_unix(errno);
5267 TALLOC_FREE(smb_fname_base);
5269 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5270 smb_fname->base_name);
5271 return NT_STATUS_OK;
5274 /****************************************************************************
5275 Deal with setting the dosmode from any of the setfilepathinfo functions.
5276 ****************************************************************************/
5278 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5279 const struct smb_filename *smb_fname,
5282 struct smb_filename *smb_fname_base = NULL;
5285 if (!VALID_STAT(smb_fname->st)) {
5286 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5289 /* Always operate on the base_name, even if a stream was passed in. */
5290 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5291 NULL, &smb_fname->st,
5293 if (!NT_STATUS_IS_OK(status)) {
5298 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5305 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5307 /* check the mode isn't different, before changing it */
5308 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5309 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5310 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5311 (unsigned int)dosmode));
5313 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5315 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5317 smb_fname_str_dbg(smb_fname_base),
5319 status = map_nt_error_from_unix(errno);
5323 status = NT_STATUS_OK;
5325 TALLOC_FREE(smb_fname_base);
5329 /****************************************************************************
5330 Deal with setting the size from any of the setfilepathinfo functions.
5331 ****************************************************************************/
5333 static NTSTATUS smb_set_file_size(connection_struct *conn,
5334 struct smb_request *req,
5336 const struct smb_filename *smb_fname,
5337 const SMB_STRUCT_STAT *psbuf,
5340 NTSTATUS status = NT_STATUS_OK;
5341 struct smb_filename *smb_fname_tmp = NULL;
5342 files_struct *new_fsp = NULL;
5344 if (!VALID_STAT(*psbuf)) {
5345 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5348 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5350 if (size == get_file_size_stat(psbuf)) {
5351 return NT_STATUS_OK;
5354 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5355 smb_fname_str_dbg(smb_fname), (double)size));
5357 if (fsp && fsp->fh->fd != -1) {
5358 /* Handle based call. */
5359 if (vfs_set_filelen(fsp, size) == -1) {
5360 return map_nt_error_from_unix(errno);
5362 trigger_write_time_update_immediate(fsp);
5363 return NT_STATUS_OK;
5366 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5367 if (!NT_STATUS_IS_OK(status)) {
5371 smb_fname_tmp->st = *psbuf;
5373 status = SMB_VFS_CREATE_FILE(
5376 0, /* root_dir_fid */
5377 smb_fname_tmp, /* fname */
5378 FILE_WRITE_ATTRIBUTES, /* access_mask */
5379 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5381 FILE_OPEN, /* create_disposition*/
5382 0, /* create_options */
5383 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5384 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5385 0, /* allocation_size */
5388 &new_fsp, /* result */
5391 TALLOC_FREE(smb_fname_tmp);
5393 if (!NT_STATUS_IS_OK(status)) {
5394 /* NB. We check for open_was_deferred in the caller. */
5398 if (vfs_set_filelen(new_fsp, size) == -1) {
5399 status = map_nt_error_from_unix(errno);
5400 close_file(req, new_fsp,NORMAL_CLOSE);
5404 trigger_write_time_update_immediate(new_fsp);
5405 close_file(req, new_fsp,NORMAL_CLOSE);
5406 return NT_STATUS_OK;
5409 /****************************************************************************
5410 Deal with SMB_INFO_SET_EA.
5411 ****************************************************************************/
5413 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5417 const struct smb_filename *smb_fname)
5419 struct ea_list *ea_list = NULL;
5420 TALLOC_CTX *ctx = NULL;
5421 NTSTATUS status = NT_STATUS_OK;
5423 if (total_data < 10) {
5425 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5426 length. They seem to have no effect. Bug #3212. JRA */
5428 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5429 /* We're done. We only get EA info in this call. */
5430 return NT_STATUS_OK;
5433 return NT_STATUS_INVALID_PARAMETER;
5436 if (IVAL(pdata,0) > total_data) {
5437 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5438 IVAL(pdata,0), (unsigned int)total_data));
5439 return NT_STATUS_INVALID_PARAMETER;
5443 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5445 return NT_STATUS_INVALID_PARAMETER;
5447 status = set_ea(conn, fsp, smb_fname, ea_list);
5452 /****************************************************************************
5453 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5454 ****************************************************************************/
5456 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5460 const struct smb_filename *smb_fname)
5462 NTSTATUS status = NT_STATUS_OK;
5463 bool delete_on_close;
5466 if (total_data < 1) {
5467 return NT_STATUS_INVALID_PARAMETER;
5471 return NT_STATUS_INVALID_HANDLE;
5474 delete_on_close = (CVAL(pdata,0) ? True : False);
5475 dosmode = dos_mode(conn, smb_fname);
5477 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5478 "delete_on_close = %u\n",
5479 smb_fname_str_dbg(smb_fname),
5480 (unsigned int)dosmode,
5481 (unsigned int)delete_on_close ));
5483 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5485 if (!NT_STATUS_IS_OK(status)) {
5489 /* The set is across all open files on this dev/inode pair. */
5490 if (!set_delete_on_close(fsp, delete_on_close,
5491 &conn->server_info->utok)) {
5492 return NT_STATUS_ACCESS_DENIED;
5494 return NT_STATUS_OK;
5497 /****************************************************************************
5498 Deal with SMB_FILE_POSITION_INFORMATION.
5499 ****************************************************************************/
5501 static NTSTATUS smb_file_position_information(connection_struct *conn,
5506 uint64_t position_information;
5508 if (total_data < 8) {
5509 return NT_STATUS_INVALID_PARAMETER;
5513 /* Ignore on pathname based set. */
5514 return NT_STATUS_OK;
5517 position_information = (uint64_t)IVAL(pdata,0);
5518 #ifdef LARGE_SMB_OFF_T
5519 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5520 #else /* LARGE_SMB_OFF_T */
5521 if (IVAL(pdata,4) != 0) {
5522 /* more than 32 bits? */
5523 return NT_STATUS_INVALID_PARAMETER;
5525 #endif /* LARGE_SMB_OFF_T */
5527 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5528 fsp->fsp_name, (double)position_information ));
5529 fsp->fh->position_information = position_information;
5530 return NT_STATUS_OK;
5533 /****************************************************************************
5534 Deal with SMB_FILE_MODE_INFORMATION.
5535 ****************************************************************************/
5537 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5543 if (total_data < 4) {
5544 return NT_STATUS_INVALID_PARAMETER;
5546 mode = IVAL(pdata,0);
5547 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5548 return NT_STATUS_INVALID_PARAMETER;
5550 return NT_STATUS_OK;
5553 /****************************************************************************
5554 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5555 ****************************************************************************/
5557 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5558 struct smb_request *req,
5563 char *link_target = NULL;
5564 const char *newname = fname;
5565 NTSTATUS status = NT_STATUS_OK;
5566 TALLOC_CTX *ctx = talloc_tos();
5568 /* Set a symbolic link. */
5569 /* Don't allow this if follow links is false. */
5571 if (total_data == 0) {
5572 return NT_STATUS_INVALID_PARAMETER;
5575 if (!lp_symlinks(SNUM(conn))) {
5576 return NT_STATUS_ACCESS_DENIED;
5579 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5580 total_data, STR_TERMINATE);
5583 return NT_STATUS_INVALID_PARAMETER;
5586 /* !widelinks forces the target path to be within the share. */
5587 /* This means we can interpret the target as a pathname. */
5588 if (!lp_widelinks(SNUM(conn))) {
5589 char *rel_name = NULL;
5590 char *last_dirp = NULL;
5592 if (*link_target == '/') {
5593 /* No absolute paths allowed. */
5594 return NT_STATUS_ACCESS_DENIED;
5596 rel_name = talloc_strdup(ctx,newname);
5598 return NT_STATUS_NO_MEMORY;
5600 last_dirp = strrchr_m(rel_name, '/');
5602 last_dirp[1] = '\0';
5604 rel_name = talloc_strdup(ctx,"./");
5606 return NT_STATUS_NO_MEMORY;
5609 rel_name = talloc_asprintf_append(rel_name,
5613 return NT_STATUS_NO_MEMORY;
5616 status = check_name(conn, rel_name);
5617 if (!NT_STATUS_IS_OK(status)) {
5622 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5623 newname, link_target ));
5625 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5626 return map_nt_error_from_unix(errno);
5629 return NT_STATUS_OK;
5632 /****************************************************************************
5633 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5634 ****************************************************************************/
5636 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5637 struct smb_request *req,
5638 const char *pdata, int total_data,
5639 const struct smb_filename *smb_fname_new)
5641 char *oldname = NULL;
5642 struct smb_filename *smb_fname_old = NULL;
5643 TALLOC_CTX *ctx = talloc_tos();
5644 NTSTATUS status = NT_STATUS_OK;
5646 /* Set a hard link. */
5647 if (total_data == 0) {
5648 return NT_STATUS_INVALID_PARAMETER;
5651 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5652 total_data, STR_TERMINATE, &status);
5653 if (!NT_STATUS_IS_OK(status)) {
5657 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5658 smb_fname_str_dbg(smb_fname_new), oldname));
5660 status = filename_convert(ctx,
5662 req->flags2 & FLAGS2_DFS_PATHNAMES,
5666 if (!NT_STATUS_IS_OK(status)) {
5670 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5673 /****************************************************************************
5674 Deal with SMB_FILE_RENAME_INFORMATION.
5675 ****************************************************************************/
5677 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5678 struct smb_request *req,
5687 char *newname = NULL;
5688 char *base_name = NULL;
5689 struct smb_filename *smb_fname = NULL;
5690 bool dest_has_wcard = False;
5691 NTSTATUS status = NT_STATUS_OK;
5693 TALLOC_CTX *ctx = talloc_tos();
5695 if (total_data < 13) {
5696 return NT_STATUS_INVALID_PARAMETER;
5699 overwrite = (CVAL(pdata,0) ? True : False);
5700 root_fid = IVAL(pdata,4);
5701 len = IVAL(pdata,8);
5703 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5704 return NT_STATUS_INVALID_PARAMETER;
5707 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5710 if (!NT_STATUS_IS_OK(status)) {
5714 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5717 status = resolve_dfspath_wcard(ctx, conn,
5718 req->flags2 & FLAGS2_DFS_PATHNAMES,
5722 if (!NT_STATUS_IS_OK(status)) {
5726 /* Check the new name has no '/' characters. */
5727 if (strchr_m(newname, '/')) {
5728 return NT_STATUS_NOT_SUPPORTED;
5731 if (fsp && fsp->base_fsp) {
5732 /* newname must be a stream name. */
5733 if (newname[0] != ':') {
5734 return NT_STATUS_NOT_SUPPORTED;
5737 /* Create an smb_fname to call rename_internals_fsp() with. */
5738 status = create_synthetic_smb_fname(talloc_tos(),
5739 fsp->base_fsp->fsp_name,
5740 newname, NULL, &smb_fname);
5741 if (!NT_STATUS_IS_OK(status)) {
5746 * Set the original last component, since
5747 * rename_internals_fsp() requires it.
5749 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5750 if (smb_fname->original_lcomp == NULL) {
5751 status = NT_STATUS_NO_MEMORY;
5755 /* Create a char * to call rename_internals() with. */
5756 base_name = talloc_asprintf(ctx, "%s%s",
5757 fsp->base_fsp->fsp_name,
5760 status = NT_STATUS_NO_MEMORY;
5764 /* newname must *not* be a stream name. */
5765 if (newname[0] == ':') {
5766 return NT_STATUS_NOT_SUPPORTED;
5769 /* Create the base directory. */
5770 base_name = talloc_strdup(ctx, fname);
5772 return NT_STATUS_NO_MEMORY;
5774 p = strrchr_m(base_name, '/');
5778 base_name = talloc_strdup(ctx, "./");
5780 return NT_STATUS_NO_MEMORY;
5783 /* Append the new name. */
5784 base_name = talloc_asprintf_append(base_name,
5788 return NT_STATUS_NO_MEMORY;
5791 status = unix_convert(ctx, conn, base_name, &smb_fname,
5794 /* If an error we expect this to be
5795 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5797 if (!NT_STATUS_IS_OK(status)) {
5798 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5802 /* Create an smb_fname to call rename_internals_fsp() */
5803 status = create_synthetic_smb_fname(talloc_tos(),
5806 if (!NT_STATUS_IS_OK(status)) {
5814 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5815 fsp->fnum, fsp->fsp_name, base_name ));
5816 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5819 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5820 fname, base_name ));
5821 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5822 overwrite, False, dest_has_wcard,
5823 FILE_WRITE_ATTRIBUTES);
5826 TALLOC_FREE(smb_fname);
5830 /****************************************************************************
5831 Deal with SMB_SET_POSIX_ACL.
5832 ****************************************************************************/
5834 #if defined(HAVE_POSIX_ACLS)
5835 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5840 SMB_STRUCT_STAT *psbuf)
5842 uint16 posix_acl_version;
5843 uint16 num_file_acls;
5844 uint16 num_def_acls;
5845 bool valid_file_acls = True;
5846 bool valid_def_acls = True;
5848 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5849 return NT_STATUS_INVALID_PARAMETER;
5851 posix_acl_version = SVAL(pdata,0);
5852 num_file_acls = SVAL(pdata,2);
5853 num_def_acls = SVAL(pdata,4);
5855 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5856 valid_file_acls = False;
5860 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5861 valid_def_acls = False;
5865 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5866 return NT_STATUS_INVALID_PARAMETER;
5869 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5870 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5871 return NT_STATUS_INVALID_PARAMETER;
5874 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5875 fname ? fname : fsp->fsp_name,
5876 (unsigned int)num_file_acls,
5877 (unsigned int)num_def_acls));
5879 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5880 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5881 return map_nt_error_from_unix(errno);
5884 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5885 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5886 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5887 return map_nt_error_from_unix(errno);
5889 return NT_STATUS_OK;
5893 /****************************************************************************
5894 Deal with SMB_SET_POSIX_LOCK.
5895 ****************************************************************************/
5897 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5898 struct smb_request *req,
5906 bool blocking_lock = False;
5907 enum brl_type lock_type;
5909 NTSTATUS status = NT_STATUS_OK;
5911 if (fsp == NULL || fsp->fh->fd == -1) {
5912 return NT_STATUS_INVALID_HANDLE;
5915 if (total_data != POSIX_LOCK_DATA_SIZE) {
5916 return NT_STATUS_INVALID_PARAMETER;
5919 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5920 case POSIX_LOCK_TYPE_READ:
5921 lock_type = READ_LOCK;
5923 case POSIX_LOCK_TYPE_WRITE:
5924 /* Return the right POSIX-mappable error code for files opened read-only. */
5925 if (!fsp->can_write) {
5926 return NT_STATUS_INVALID_HANDLE;
5928 lock_type = WRITE_LOCK;
5930 case POSIX_LOCK_TYPE_UNLOCK:
5931 lock_type = UNLOCK_LOCK;
5934 return NT_STATUS_INVALID_PARAMETER;
5937 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5938 blocking_lock = False;
5939 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5940 blocking_lock = True;
5942 return NT_STATUS_INVALID_PARAMETER;
5945 if (!lp_blocking_locks(SNUM(conn))) {
5946 blocking_lock = False;
5949 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5950 #if defined(HAVE_LONGLONG)
5951 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5952 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5953 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5954 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5955 #else /* HAVE_LONGLONG */
5956 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5957 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5958 #endif /* HAVE_LONGLONG */
5960 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5961 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5963 (unsigned int)lock_type,
5964 (unsigned int)lock_pid,
5968 if (lock_type == UNLOCK_LOCK) {
5969 status = do_unlock(smbd_messaging_context(),
5976 uint32 block_smbpid;
5978 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5990 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5992 * A blocking lock was requested. Package up
5993 * this smb into a queued request and push it
5994 * onto the blocking lock queue.
5996 if(push_blocking_lock_request(br_lck,
5999 -1, /* infinite timeout. */
6007 TALLOC_FREE(br_lck);
6011 TALLOC_FREE(br_lck);
6017 /****************************************************************************
6018 Deal with SMB_INFO_STANDARD.
6019 ****************************************************************************/
6021 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6025 const struct smb_filename *smb_fname)
6027 struct smb_file_time ft;
6030 if (total_data < 12) {
6031 return NT_STATUS_INVALID_PARAMETER;
6035 ft.create_time = interpret_long_date(pdata);
6038 ft.atime = interpret_long_date(pdata + 8);
6041 ft.mtime = interpret_long_date(pdata + 16);
6043 DEBUG(10,("smb_set_info_standard: file %s\n",
6044 smb_fname_str_dbg(smb_fname)));
6046 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
6049 /****************************************************************************
6050 Deal with SMB_SET_FILE_BASIC_INFO.
6051 ****************************************************************************/
6053 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6057 const struct smb_filename *smb_fname)
6059 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6060 struct timespec write_time;
6061 struct timespec changed_time;
6062 struct smb_file_time ft;
6064 NTSTATUS status = NT_STATUS_OK;
6065 bool setting_write_time = true;
6069 if (total_data < 36) {
6070 return NT_STATUS_INVALID_PARAMETER;
6073 /* Set the attributes */
6074 dosmode = IVAL(pdata,32);
6075 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6076 if (!NT_STATUS_IS_OK(status)) {
6081 ft.atime = interpret_long_date(pdata+8);
6083 write_time = interpret_long_date(pdata+16);
6084 changed_time = interpret_long_date(pdata+24);
6087 ft.mtime = timespec_min(&write_time, &changed_time);
6090 ft.create_time = interpret_long_date(pdata);
6092 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
6093 !null_timespec(write_time)) {
6094 ft.mtime = write_time;
6097 /* Prefer a defined time to an undefined one. */
6098 if (null_timespec(ft.mtime)) {
6099 if (null_timespec(write_time)) {
6100 ft.mtime = changed_time;
6101 setting_write_time = false;
6103 ft.mtime = write_time;
6107 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6108 smb_fname_str_dbg(smb_fname)));
6110 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6111 setting_write_time);
6114 /****************************************************************************
6115 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6116 ****************************************************************************/
6118 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6119 struct smb_request *req,
6123 struct smb_filename *smb_fname)
6125 uint64_t allocation_size = 0;
6126 NTSTATUS status = NT_STATUS_OK;
6127 files_struct *new_fsp = NULL;
6129 if (!VALID_STAT(smb_fname->st)) {
6130 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6133 if (total_data < 8) {
6134 return NT_STATUS_INVALID_PARAMETER;
6137 allocation_size = (uint64_t)IVAL(pdata,0);
6138 #ifdef LARGE_SMB_OFF_T
6139 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6140 #else /* LARGE_SMB_OFF_T */
6141 if (IVAL(pdata,4) != 0) {
6142 /* more than 32 bits? */
6143 return NT_STATUS_INVALID_PARAMETER;
6145 #endif /* LARGE_SMB_OFF_T */
6147 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6148 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6149 (double)allocation_size));
6151 if (allocation_size) {
6152 allocation_size = smb_roundup(conn, allocation_size);
6155 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6156 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6157 (double)allocation_size));
6159 if (fsp && fsp->fh->fd != -1) {
6160 /* Open file handle. */
6161 /* Only change if needed. */
6162 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6163 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6164 return map_nt_error_from_unix(errno);
6167 /* But always update the time. */
6169 * This is equivalent to a write. Ensure it's seen immediately
6170 * if there are no pending writes.
6172 trigger_write_time_update_immediate(fsp);
6173 return NT_STATUS_OK;
6176 /* Pathname or stat or directory file. */
6177 status = SMB_VFS_CREATE_FILE(
6180 0, /* root_dir_fid */
6181 smb_fname, /* fname */
6182 FILE_WRITE_DATA, /* access_mask */
6183 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6185 FILE_OPEN, /* create_disposition*/
6186 0, /* create_options */
6187 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6188 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6189 0, /* allocation_size */
6192 &new_fsp, /* result */
6195 if (!NT_STATUS_IS_OK(status)) {
6196 /* NB. We check for open_was_deferred in the caller. */
6200 /* Only change if needed. */
6201 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6202 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6203 status = map_nt_error_from_unix(errno);
6204 close_file(req, new_fsp, NORMAL_CLOSE);
6209 /* Changing the allocation size should set the last mod time. */
6211 * This is equivalent to a write. Ensure it's seen immediately
6212 * if there are no pending writes.
6214 trigger_write_time_update_immediate(new_fsp);
6216 close_file(req, new_fsp, NORMAL_CLOSE);
6217 return NT_STATUS_OK;
6220 /****************************************************************************
6221 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6222 ****************************************************************************/
6224 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6225 struct smb_request *req,
6229 const struct smb_filename *smb_fname)
6233 if (total_data < 8) {
6234 return NT_STATUS_INVALID_PARAMETER;
6237 size = IVAL(pdata,0);
6238 #ifdef LARGE_SMB_OFF_T
6239 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6240 #else /* LARGE_SMB_OFF_T */
6241 if (IVAL(pdata,4) != 0) {
6242 /* more than 32 bits? */
6243 return NT_STATUS_INVALID_PARAMETER;
6245 #endif /* LARGE_SMB_OFF_T */
6246 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6247 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6250 return smb_set_file_size(conn, req,
6257 /****************************************************************************
6258 Allow a UNIX info mknod.
6259 ****************************************************************************/
6261 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6264 const struct smb_filename *smb_fname)
6266 uint32 file_type = IVAL(pdata,56);
6267 #if defined(HAVE_MAKEDEV)
6268 uint32 dev_major = IVAL(pdata,60);
6269 uint32 dev_minor = IVAL(pdata,68);
6271 SMB_DEV_T dev = (SMB_DEV_T)0;
6272 uint32 raw_unixmode = IVAL(pdata,84);
6276 if (total_data < 100) {
6277 return NT_STATUS_INVALID_PARAMETER;
6280 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6281 PERM_NEW_FILE, &unixmode);
6282 if (!NT_STATUS_IS_OK(status)) {
6286 #if defined(HAVE_MAKEDEV)
6287 dev = makedev(dev_major, dev_minor);
6290 switch (file_type) {
6291 #if defined(S_IFIFO)
6292 case UNIX_TYPE_FIFO:
6293 unixmode |= S_IFIFO;
6296 #if defined(S_IFSOCK)
6297 case UNIX_TYPE_SOCKET:
6298 unixmode |= S_IFSOCK;
6301 #if defined(S_IFCHR)
6302 case UNIX_TYPE_CHARDEV:
6303 unixmode |= S_IFCHR;
6306 #if defined(S_IFBLK)
6307 case UNIX_TYPE_BLKDEV:
6308 unixmode |= S_IFBLK;
6312 return NT_STATUS_INVALID_PARAMETER;
6315 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6316 "%.0f mode 0%o for file %s\n", (double)dev,
6317 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6319 /* Ok - do the mknod. */
6320 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6321 return map_nt_error_from_unix(errno);
6324 /* If any of the other "set" calls fail we
6325 * don't want to end up with a half-constructed mknod.
6328 if (lp_inherit_perms(SNUM(conn))) {
6330 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6332 return NT_STATUS_NO_MEMORY;
6334 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6336 TALLOC_FREE(parent);
6339 return NT_STATUS_OK;
6342 /****************************************************************************
6343 Deal with SMB_SET_FILE_UNIX_BASIC.
6344 ****************************************************************************/
6346 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6347 struct smb_request *req,
6351 const struct smb_filename *smb_fname)
6353 struct smb_file_time ft;
6354 uint32 raw_unixmode;
6357 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6358 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6359 NTSTATUS status = NT_STATUS_OK;
6360 bool delete_on_fail = False;
6361 enum perm_type ptype;
6362 files_struct *all_fsps = NULL;
6363 bool modify_mtime = true;
6365 SMB_STRUCT_STAT sbuf;
6369 if (total_data < 100) {
6370 return NT_STATUS_INVALID_PARAMETER;
6373 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6374 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6375 size=IVAL(pdata,0); /* first 8 Bytes are size */
6376 #ifdef LARGE_SMB_OFF_T
6377 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6378 #else /* LARGE_SMB_OFF_T */
6379 if (IVAL(pdata,4) != 0) {
6380 /* more than 32 bits? */
6381 return NT_STATUS_INVALID_PARAMETER;
6383 #endif /* LARGE_SMB_OFF_T */
6386 ft.atime = interpret_long_date(pdata+24); /* access_time */
6387 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6388 set_owner = (uid_t)IVAL(pdata,40);
6389 set_grp = (gid_t)IVAL(pdata,48);
6390 raw_unixmode = IVAL(pdata,84);
6392 if (VALID_STAT(smb_fname->st)) {
6393 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6394 ptype = PERM_EXISTING_DIR;
6396 ptype = PERM_EXISTING_FILE;
6399 ptype = PERM_NEW_FILE;
6402 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6404 if (!NT_STATUS_IS_OK(status)) {
6408 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6409 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6410 smb_fname_str_dbg(smb_fname), (double)size,
6411 (unsigned int)set_owner, (unsigned int)set_grp,
6412 (int)raw_unixmode));
6414 sbuf = smb_fname->st;
6416 if (!VALID_STAT(sbuf)) {
6417 struct smb_filename *smb_fname_tmp = NULL;
6419 * The only valid use of this is to create character and block
6420 * devices, and named pipes. This is deprecated (IMHO) and
6421 * a new info level should be used for mknod. JRA.
6424 status = smb_unix_mknod(conn,
6428 if (!NT_STATUS_IS_OK(status)) {
6432 status = copy_smb_filename(talloc_tos(), smb_fname,
6434 if (!NT_STATUS_IS_OK(status)) {
6438 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6439 status = map_nt_error_from_unix(errno);
6440 TALLOC_FREE(smb_fname_tmp);
6441 SMB_VFS_UNLINK(conn, smb_fname);
6445 sbuf = smb_fname_tmp->st;
6446 TALLOC_FREE(smb_fname_tmp);
6448 /* Ensure we don't try and change anything else. */
6449 raw_unixmode = SMB_MODE_NO_CHANGE;
6450 size = get_file_size_stat(&sbuf);
6451 ft.atime = sbuf.st_ex_atime;
6452 ft.mtime = sbuf.st_ex_mtime;
6454 * We continue here as we might want to change the
6457 delete_on_fail = True;
6461 /* Horrible backwards compatibility hack as an old server bug
6462 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6466 size = get_file_size_stat(&sbuf);
6471 * Deal with the UNIX specific mode set.
6474 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6475 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6476 "setting mode 0%o for file %s\n",
6477 (unsigned int)unixmode,
6478 smb_fname_str_dbg(smb_fname)));
6479 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6480 return map_nt_error_from_unix(errno);
6485 * Deal with the UNIX specific uid set.
6488 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6489 (sbuf.st_ex_uid != set_owner)) {
6492 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6493 "changing owner %u for path %s\n",
6494 (unsigned int)set_owner,
6495 smb_fname_str_dbg(smb_fname)));
6497 if (S_ISLNK(sbuf.st_ex_mode)) {
6498 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6499 set_owner, (gid_t)-1);
6501 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6502 set_owner, (gid_t)-1);
6506 status = map_nt_error_from_unix(errno);
6507 if (delete_on_fail) {
6508 SMB_VFS_UNLINK(conn, smb_fname);
6515 * Deal with the UNIX specific gid set.
6518 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6519 (sbuf.st_ex_gid != set_grp)) {
6520 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6521 "changing group %u for file %s\n",
6522 (unsigned int)set_owner,
6523 smb_fname_str_dbg(smb_fname)));
6524 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6526 status = map_nt_error_from_unix(errno);
6527 if (delete_on_fail) {
6528 SMB_VFS_UNLINK(conn, smb_fname);
6534 /* Deal with any size changes. */
6536 status = smb_set_file_size(conn, req,
6541 if (!NT_STATUS_IS_OK(status)) {
6545 /* Deal with any time changes. */
6546 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6547 /* No change, don't cancel anything. */
6551 id = vfs_file_id_from_sbuf(conn, &sbuf);
6552 for(all_fsps = file_find_di_first(id); all_fsps;
6553 all_fsps = file_find_di_next(all_fsps)) {
6555 * We're setting the time explicitly for UNIX.
6556 * Cancel any pending changes over all handles.
6558 all_fsps->update_write_time_on_close = false;
6559 TALLOC_FREE(all_fsps->update_write_time_event);
6563 * Override the "setting_write_time"
6564 * parameter here as it almost does what
6565 * we need. Just remember if we modified
6566 * mtime and send the notify ourselves.
6568 if (null_timespec(ft.mtime)) {
6569 modify_mtime = false;
6572 status = smb_set_file_time(conn,
6578 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6579 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6584 /****************************************************************************
6585 Deal with SMB_SET_FILE_UNIX_INFO2.
6586 ****************************************************************************/
6588 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6589 struct smb_request *req,
6593 const struct smb_filename *smb_fname)
6599 if (total_data < 116) {
6600 return NT_STATUS_INVALID_PARAMETER;
6603 /* Start by setting all the fields that are common between UNIX_BASIC
6606 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6608 if (!NT_STATUS_IS_OK(status)) {
6612 smb_fflags = IVAL(pdata, 108);
6613 smb_fmask = IVAL(pdata, 112);
6615 /* NB: We should only attempt to alter the file flags if the client
6616 * sends a non-zero mask.
6618 if (smb_fmask != 0) {
6619 int stat_fflags = 0;
6621 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6622 smb_fmask, &stat_fflags)) {
6623 /* Client asked to alter a flag we don't understand. */
6624 return NT_STATUS_INVALID_PARAMETER;
6627 if (fsp && fsp->fh->fd != -1) {
6628 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6629 return NT_STATUS_NOT_SUPPORTED;
6631 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6632 stat_fflags) != 0) {
6633 return map_nt_error_from_unix(errno);
6638 /* XXX: need to add support for changing the create_time here. You
6639 * can do this for paths on Darwin with setattrlist(2). The right way
6640 * to hook this up is probably by extending the VFS utimes interface.
6643 return NT_STATUS_OK;
6646 /****************************************************************************
6647 Create a directory with POSIX semantics.
6648 ****************************************************************************/
6650 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6651 struct smb_request *req,
6655 SMB_STRUCT_STAT *psbuf,
6656 int *pdata_return_size)
6658 struct smb_filename *smb_fname;
6659 NTSTATUS status = NT_STATUS_OK;
6660 uint32 raw_unixmode = 0;
6661 uint32 mod_unixmode = 0;
6662 mode_t unixmode = (mode_t)0;
6663 files_struct *fsp = NULL;
6664 uint16 info_level_return = 0;
6666 char *pdata = *ppdata;
6668 if (total_data < 18) {
6669 return NT_STATUS_INVALID_PARAMETER;
6672 raw_unixmode = IVAL(pdata,8);
6673 /* Next 4 bytes are not yet defined. */
6675 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6676 if (!NT_STATUS_IS_OK(status)) {
6680 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6682 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6683 fname, (unsigned int)unixmode ));
6685 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6687 if (!NT_STATUS_IS_OK(status)) {
6691 status = SMB_VFS_CREATE_FILE(
6694 0, /* root_dir_fid */
6695 smb_fname, /* fname */
6696 FILE_READ_ATTRIBUTES, /* access_mask */
6697 FILE_SHARE_NONE, /* share_access */
6698 FILE_CREATE, /* create_disposition*/
6699 FILE_DIRECTORY_FILE, /* create_options */
6700 mod_unixmode, /* file_attributes */
6701 0, /* oplock_request */
6702 0, /* allocation_size */
6708 *psbuf = smb_fname->st;
6709 TALLOC_FREE(smb_fname);
6711 if (NT_STATUS_IS_OK(status)) {
6712 close_file(req, fsp, NORMAL_CLOSE);
6715 info_level_return = SVAL(pdata,16);
6717 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6718 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6719 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6720 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6722 *pdata_return_size = 12;
6725 /* Realloc the data size */
6726 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6727 if (*ppdata == NULL) {
6728 *pdata_return_size = 0;
6729 return NT_STATUS_NO_MEMORY;
6733 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6734 SSVAL(pdata,2,0); /* No fnum. */
6735 SIVAL(pdata,4,info); /* Was directory created. */
6737 switch (info_level_return) {
6738 case SMB_QUERY_FILE_UNIX_BASIC:
6739 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6740 SSVAL(pdata,10,0); /* Padding. */
6741 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6743 case SMB_QUERY_FILE_UNIX_INFO2:
6744 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6745 SSVAL(pdata,10,0); /* Padding. */
6746 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6749 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6750 SSVAL(pdata,10,0); /* Padding. */
6757 /****************************************************************************
6758 Open/Create a file with POSIX semantics.
6759 ****************************************************************************/
6761 static NTSTATUS smb_posix_open(connection_struct *conn,
6762 struct smb_request *req,
6766 SMB_STRUCT_STAT *psbuf,
6767 int *pdata_return_size)
6769 struct smb_filename *smb_fname = NULL;
6770 bool extended_oplock_granted = False;
6771 char *pdata = *ppdata;
6773 uint32 wire_open_mode = 0;
6774 uint32 raw_unixmode = 0;
6775 uint32 mod_unixmode = 0;
6776 uint32 create_disp = 0;
6777 uint32 access_mask = 0;
6778 uint32 create_options = 0;
6779 NTSTATUS status = NT_STATUS_OK;
6780 mode_t unixmode = (mode_t)0;
6781 files_struct *fsp = NULL;
6782 int oplock_request = 0;
6784 uint16 info_level_return = 0;
6786 if (total_data < 18) {
6787 return NT_STATUS_INVALID_PARAMETER;
6790 flags = IVAL(pdata,0);
6791 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6792 if (oplock_request) {
6793 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6796 wire_open_mode = IVAL(pdata,4);
6798 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6799 return smb_posix_mkdir(conn, req,
6807 switch (wire_open_mode & SMB_ACCMODE) {
6809 access_mask = FILE_READ_DATA;
6812 access_mask = FILE_WRITE_DATA;
6815 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6818 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6819 (unsigned int)wire_open_mode ));
6820 return NT_STATUS_INVALID_PARAMETER;
6823 wire_open_mode &= ~SMB_ACCMODE;
6825 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6826 create_disp = FILE_CREATE;
6827 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6828 create_disp = FILE_OVERWRITE_IF;
6829 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6830 create_disp = FILE_OPEN_IF;
6831 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6832 create_disp = FILE_OPEN;
6834 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6835 (unsigned int)wire_open_mode ));
6836 return NT_STATUS_INVALID_PARAMETER;
6839 raw_unixmode = IVAL(pdata,8);
6840 /* Next 4 bytes are not yet defined. */
6842 status = unix_perms_from_wire(conn,
6845 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6848 if (!NT_STATUS_IS_OK(status)) {
6852 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6854 if (wire_open_mode & SMB_O_SYNC) {
6855 create_options |= FILE_WRITE_THROUGH;
6857 if (wire_open_mode & SMB_O_APPEND) {
6858 access_mask |= FILE_APPEND_DATA;
6860 if (wire_open_mode & SMB_O_DIRECT) {
6861 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6864 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6866 (unsigned int)wire_open_mode,
6867 (unsigned int)unixmode ));
6869 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6871 if (!NT_STATUS_IS_OK(status)) {
6875 status = SMB_VFS_CREATE_FILE(
6878 0, /* root_dir_fid */
6879 smb_fname, /* fname */
6880 access_mask, /* access_mask */
6881 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6883 create_disp, /* create_disposition*/
6884 FILE_NON_DIRECTORY_FILE, /* create_options */
6885 mod_unixmode, /* file_attributes */
6886 oplock_request, /* oplock_request */
6887 0, /* allocation_size */
6893 *psbuf = smb_fname->st;
6894 TALLOC_FREE(smb_fname);
6896 if (!NT_STATUS_IS_OK(status)) {
6900 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6901 extended_oplock_granted = True;
6904 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6905 extended_oplock_granted = True;
6908 info_level_return = SVAL(pdata,16);
6910 /* Allocate the correct return size. */
6912 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6913 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6914 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6915 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6917 *pdata_return_size = 12;
6920 /* Realloc the data size */
6921 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6922 if (*ppdata == NULL) {
6923 close_file(req, fsp, ERROR_CLOSE);
6924 *pdata_return_size = 0;
6925 return NT_STATUS_NO_MEMORY;
6929 if (extended_oplock_granted) {
6930 if (flags & REQUEST_BATCH_OPLOCK) {
6931 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6933 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6935 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6936 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6938 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6941 SSVAL(pdata,2,fsp->fnum);
6942 SIVAL(pdata,4,info); /* Was file created etc. */
6944 switch (info_level_return) {
6945 case SMB_QUERY_FILE_UNIX_BASIC:
6946 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6947 SSVAL(pdata,10,0); /* padding. */
6948 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6950 case SMB_QUERY_FILE_UNIX_INFO2:
6951 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6952 SSVAL(pdata,10,0); /* padding. */
6953 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6956 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6957 SSVAL(pdata,10,0); /* padding. */
6960 return NT_STATUS_OK;
6963 /****************************************************************************
6964 Delete a file with POSIX semantics.
6965 ****************************************************************************/
6967 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6968 struct smb_request *req,
6971 struct smb_filename *smb_fname)
6973 NTSTATUS status = NT_STATUS_OK;
6974 files_struct *fsp = NULL;
6978 int create_options = 0;
6980 struct share_mode_lock *lck = NULL;
6982 if (total_data < 2) {
6983 return NT_STATUS_INVALID_PARAMETER;
6986 flags = SVAL(pdata,0);
6988 if (!VALID_STAT(smb_fname->st)) {
6989 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6992 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6993 !VALID_STAT_OF_DIR(smb_fname->st)) {
6994 return NT_STATUS_NOT_A_DIRECTORY;
6997 DEBUG(10,("smb_posix_unlink: %s %s\n",
6998 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6999 smb_fname_str_dbg(smb_fname)));
7001 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7002 create_options |= FILE_DIRECTORY_FILE;
7005 status = SMB_VFS_CREATE_FILE(
7008 0, /* root_dir_fid */
7009 smb_fname, /* fname */
7010 DELETE_ACCESS, /* access_mask */
7011 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7013 FILE_OPEN, /* create_disposition*/
7014 create_options, /* create_options */
7015 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7016 0, /* oplock_request */
7017 0, /* allocation_size */
7023 if (!NT_STATUS_IS_OK(status)) {
7028 * Don't lie to client. If we can't really delete due to
7029 * non-POSIX opens return SHARING_VIOLATION.
7032 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7035 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7036 "lock for file %s\n", fsp->fsp_name));
7037 close_file(req, fsp, NORMAL_CLOSE);
7038 return NT_STATUS_INVALID_PARAMETER;
7042 * See if others still have the file open. If this is the case, then
7043 * don't delete. If all opens are POSIX delete we can set the delete
7044 * on close disposition.
7046 for (i=0; i<lck->num_share_modes; i++) {
7047 struct share_mode_entry *e = &lck->share_modes[i];
7048 if (is_valid_share_mode_entry(e)) {
7049 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7052 /* Fail with sharing violation. */
7053 close_file(req, fsp, NORMAL_CLOSE);
7055 return NT_STATUS_SHARING_VIOLATION;
7060 * Set the delete on close.
7062 status = smb_set_file_disposition_info(conn,
7068 if (!NT_STATUS_IS_OK(status)) {
7069 close_file(req, fsp, NORMAL_CLOSE);
7074 return close_file(req, fsp, NORMAL_CLOSE);
7077 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7078 struct smb_request *req,
7079 TALLOC_CTX *mem_ctx,
7080 uint16_t info_level,
7082 struct smb_filename *smb_fname,
7083 char **ppdata, int total_data,
7086 char *pdata = *ppdata;
7087 SMB_STRUCT_STAT sbuf;
7089 NTSTATUS status = NT_STATUS_OK;
7090 int data_return_size = 0;
7094 /* Set sbuf for use below. */
7095 sbuf = smb_fname->st;
7097 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7098 return NT_STATUS_INVALID_LEVEL;
7101 if (!CAN_WRITE(conn)) {
7102 /* Allow POSIX opens. The open path will deny
7103 * any non-readonly opens. */
7104 if (info_level != SMB_POSIX_PATH_OPEN) {
7105 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7109 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
7110 if (!NT_STATUS_IS_OK(status)) {
7114 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d totdata=%d\n",
7115 fname, fsp ? fsp->fnum : -1, info_level, total_data));
7117 switch (info_level) {
7119 case SMB_INFO_STANDARD:
7121 status = smb_set_info_standard(conn,
7129 case SMB_INFO_SET_EA:
7131 status = smb_info_set_ea(conn,
7139 case SMB_SET_FILE_BASIC_INFO:
7140 case SMB_FILE_BASIC_INFORMATION:
7142 status = smb_set_file_basic_info(conn,
7150 case SMB_FILE_ALLOCATION_INFORMATION:
7151 case SMB_SET_FILE_ALLOCATION_INFO:
7153 status = smb_set_file_allocation_info(conn, req,
7161 case SMB_FILE_END_OF_FILE_INFORMATION:
7162 case SMB_SET_FILE_END_OF_FILE_INFO:
7164 status = smb_set_file_end_of_file_info(conn, req,
7172 case SMB_FILE_DISPOSITION_INFORMATION:
7173 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7176 /* JRA - We used to just ignore this on a path ?
7177 * Shouldn't this be invalid level on a pathname
7180 if (tran_call != TRANSACT2_SETFILEINFO) {
7181 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7184 status = smb_set_file_disposition_info(conn,
7192 case SMB_FILE_POSITION_INFORMATION:
7194 status = smb_file_position_information(conn,
7201 /* From tridge Samba4 :
7202 * MODE_INFORMATION in setfileinfo (I have no
7203 * idea what "mode information" on a file is - it takes a value of 0,
7204 * 2, 4 or 6. What could it be?).
7207 case SMB_FILE_MODE_INFORMATION:
7209 status = smb_file_mode_information(conn,
7216 * CIFS UNIX extensions.
7219 case SMB_SET_FILE_UNIX_BASIC:
7221 status = smb_set_file_unix_basic(conn, req,
7229 case SMB_SET_FILE_UNIX_INFO2:
7231 status = smb_set_file_unix_info2(conn, req,
7239 case SMB_SET_FILE_UNIX_LINK:
7242 /* We must have a pathname for this. */
7243 return NT_STATUS_INVALID_LEVEL;
7245 status = smb_set_file_unix_link(conn, req, pdata,
7250 case SMB_SET_FILE_UNIX_HLINK:
7253 /* We must have a pathname for this. */
7254 return NT_STATUS_INVALID_LEVEL;
7256 status = smb_set_file_unix_hlink(conn, req,
7262 case SMB_FILE_RENAME_INFORMATION:
7264 status = smb_file_rename_information(conn, req,
7270 #if defined(HAVE_POSIX_ACLS)
7271 case SMB_SET_POSIX_ACL:
7273 status = smb_set_posix_acl(conn,
7283 case SMB_SET_POSIX_LOCK:
7286 return NT_STATUS_INVALID_LEVEL;
7288 status = smb_set_posix_lock(conn, req,
7289 pdata, total_data, fsp);
7293 case SMB_POSIX_PATH_OPEN:
7296 /* We must have a pathname for this. */
7297 return NT_STATUS_INVALID_LEVEL;
7300 status = smb_posix_open(conn, req,
7309 case SMB_POSIX_PATH_UNLINK:
7312 /* We must have a pathname for this. */
7313 return NT_STATUS_INVALID_LEVEL;
7316 status = smb_posix_unlink(conn, req,
7324 return NT_STATUS_INVALID_LEVEL;
7327 if (!NT_STATUS_IS_OK(status)) {
7331 *ret_data_size = data_return_size;
7332 return NT_STATUS_OK;
7335 /****************************************************************************
7336 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7337 ****************************************************************************/
7339 static void call_trans2setfilepathinfo(connection_struct *conn,
7340 struct smb_request *req,
7341 unsigned int tran_call,
7342 char **pparams, int total_params,
7343 char **ppdata, int total_data,
7344 unsigned int max_data_bytes)
7346 char *params = *pparams;
7347 char *pdata = *ppdata;
7350 struct smb_filename *smb_fname = NULL;
7351 files_struct *fsp = NULL;
7352 NTSTATUS status = NT_STATUS_OK;
7353 int data_return_size = 0;
7356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7360 if (tran_call == TRANSACT2_SETFILEINFO) {
7361 if (total_params < 4) {
7362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7366 fsp = file_fsp(req, SVAL(params,0));
7367 /* Basic check for non-null fsp. */
7368 if (!check_fsp_open(conn, req, fsp)) {
7371 info_level = SVAL(params,2);
7373 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
7375 reply_nterror(req, NT_STATUS_NO_MEMORY);
7379 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
7381 if (!NT_STATUS_IS_OK(status)) {
7382 reply_nterror(req, status);
7386 if(fsp->is_directory || fsp->fh->fd == -1) {
7388 * This is actually a SETFILEINFO on a directory
7389 * handle (returned from an NT SMB). NT5.0 seems
7390 * to do this call. JRA.
7392 if (INFO_LEVEL_IS_UNIX(info_level)) {
7393 /* Always do lstat for UNIX calls. */
7394 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7395 DEBUG(3,("call_trans2setfilepathinfo: "
7396 "SMB_VFS_LSTAT of %s failed "
7398 smb_fname_str_dbg(smb_fname),
7400 reply_nterror(req, map_nt_error_from_unix(errno));
7404 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7405 DEBUG(3,("call_trans2setfilepathinfo: "
7406 "fileinfo of %s failed (%s)\n",
7407 smb_fname_str_dbg(smb_fname),
7409 reply_nterror(req, map_nt_error_from_unix(errno));
7413 } else if (fsp->print_file) {
7415 * Doing a DELETE_ON_CLOSE should cancel a print job.
7417 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7418 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7420 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
7423 send_trans2_replies(conn, req, params, 2,
7428 reply_doserror(req, ERRDOS, ERRbadpath);
7433 * Original code - this is an open file.
7435 if (!check_fsp(conn, req, fsp)) {
7439 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7440 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7441 "of fnum %d failed (%s)\n", fsp->fnum,
7443 reply_nterror(req, map_nt_error_from_unix(errno));
7449 if (total_params < 7) {
7450 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7454 info_level = SVAL(params,0);
7455 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7456 total_params - 6, STR_TERMINATE,
7458 if (!NT_STATUS_IS_OK(status)) {
7459 reply_nterror(req, status);
7463 status = filename_convert(req, conn,
7464 req->flags2 & FLAGS2_DFS_PATHNAMES,
7468 if (!NT_STATUS_IS_OK(status)) {
7469 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7470 reply_botherror(req,
7471 NT_STATUS_PATH_NOT_COVERED,
7472 ERRSRV, ERRbadpath);
7475 reply_nterror(req, status);
7479 if (INFO_LEVEL_IS_UNIX(info_level)) {
7481 * For CIFS UNIX extensions the target name may not exist.
7484 /* Always do lstat for UNIX calls. */
7485 SMB_VFS_LSTAT(conn, smb_fname);
7487 } else if (!VALID_STAT(smb_fname->st) &&
7488 SMB_VFS_STAT(conn, smb_fname)) {
7489 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7491 smb_fname_str_dbg(smb_fname),
7493 reply_nterror(req, map_nt_error_from_unix(errno));
7498 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
7499 tran_call, fname, fsp ? fsp->fnum : -1, info_level,total_data));
7501 /* Realloc the parameter size */
7502 *pparams = (char *)SMB_REALLOC(*pparams,2);
7503 if (*pparams == NULL) {
7504 reply_nterror(req, NT_STATUS_NO_MEMORY);
7511 status = smbd_do_setfilepathinfo(conn, req, req,
7517 if (!NT_STATUS_IS_OK(status)) {
7518 if (open_was_deferred(req->mid)) {
7519 /* We have re-scheduled this call. */
7522 if (blocking_lock_was_deferred(req->mid)) {
7523 /* We have re-scheduled this call. */
7526 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7527 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7528 ERRSRV, ERRbadpath);
7531 if (info_level == SMB_POSIX_PATH_OPEN) {
7532 reply_openerror(req, status);
7536 reply_nterror(req, status);
7540 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7546 /****************************************************************************
7547 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7548 ****************************************************************************/
7550 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7551 char **pparams, int total_params,
7552 char **ppdata, int total_data,
7553 unsigned int max_data_bytes)
7555 struct smb_filename *smb_dname = NULL;
7556 char *params = *pparams;
7557 char *pdata = *ppdata;
7558 char *directory = NULL;
7559 NTSTATUS status = NT_STATUS_OK;
7560 struct ea_list *ea_list = NULL;
7561 TALLOC_CTX *ctx = talloc_tos();
7563 if (!CAN_WRITE(conn)) {
7564 reply_doserror(req, ERRSRV, ERRaccess);
7568 if (total_params < 5) {
7569 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7573 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7574 total_params - 4, STR_TERMINATE,
7576 if (!NT_STATUS_IS_OK(status)) {
7577 reply_nterror(req, status);
7581 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7583 status = filename_convert(ctx,
7585 req->flags2 & FLAGS2_DFS_PATHNAMES,
7590 if (!NT_STATUS_IS_OK(status)) {
7591 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7592 reply_botherror(req,
7593 NT_STATUS_PATH_NOT_COVERED,
7594 ERRSRV, ERRbadpath);
7597 reply_nterror(req, status);
7601 /* Any data in this call is an EA list. */
7602 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7603 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7608 * OS/2 workplace shell seems to send SET_EA requests of "null"
7609 * length (4 bytes containing IVAL 4).
7610 * They seem to have no effect. Bug #3212. JRA.
7613 if (total_data != 4) {
7614 if (total_data < 10) {
7615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7619 if (IVAL(pdata,0) > total_data) {
7620 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7621 IVAL(pdata,0), (unsigned int)total_data));
7622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7626 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7633 /* If total_data == 4 Windows doesn't care what values
7634 * are placed in that field, it just ignores them.
7635 * The System i QNTC IBM SMB client puts bad values here,
7636 * so ignore them. */
7638 status = create_directory(conn, req, smb_dname);
7640 if (!NT_STATUS_IS_OK(status)) {
7641 reply_nterror(req, status);
7645 /* Try and set any given EA. */
7647 status = set_ea(conn, NULL, smb_dname, ea_list);
7648 if (!NT_STATUS_IS_OK(status)) {
7649 reply_nterror(req, status);
7654 /* Realloc the parameter and data sizes */
7655 *pparams = (char *)SMB_REALLOC(*pparams,2);
7656 if(*pparams == NULL) {
7657 reply_nterror(req, NT_STATUS_NO_MEMORY);
7664 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7667 TALLOC_FREE(smb_dname);
7671 /****************************************************************************
7672 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7673 We don't actually do this - we just send a null response.
7674 ****************************************************************************/
7676 static void call_trans2findnotifyfirst(connection_struct *conn,
7677 struct smb_request *req,
7678 char **pparams, int total_params,
7679 char **ppdata, int total_data,
7680 unsigned int max_data_bytes)
7682 char *params = *pparams;
7685 if (total_params < 6) {
7686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7690 info_level = SVAL(params,4);
7691 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7693 switch (info_level) {
7698 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7702 /* Realloc the parameter and data sizes */
7703 *pparams = (char *)SMB_REALLOC(*pparams,6);
7704 if (*pparams == NULL) {
7705 reply_nterror(req, NT_STATUS_NO_MEMORY);
7710 SSVAL(params,0,fnf_handle);
7711 SSVAL(params,2,0); /* No changes */
7712 SSVAL(params,4,0); /* No EA errors */
7719 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7724 /****************************************************************************
7725 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7726 changes). Currently this does nothing.
7727 ****************************************************************************/
7729 static void call_trans2findnotifynext(connection_struct *conn,
7730 struct smb_request *req,
7731 char **pparams, int total_params,
7732 char **ppdata, int total_data,
7733 unsigned int max_data_bytes)
7735 char *params = *pparams;
7737 DEBUG(3,("call_trans2findnotifynext\n"));
7739 /* Realloc the parameter and data sizes */
7740 *pparams = (char *)SMB_REALLOC(*pparams,4);
7741 if (*pparams == NULL) {
7742 reply_nterror(req, NT_STATUS_NO_MEMORY);
7747 SSVAL(params,0,0); /* No changes */
7748 SSVAL(params,2,0); /* No EA errors */
7750 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7755 /****************************************************************************
7756 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7757 ****************************************************************************/
7759 static void call_trans2getdfsreferral(connection_struct *conn,
7760 struct smb_request *req,
7761 char **pparams, int total_params,
7762 char **ppdata, int total_data,
7763 unsigned int max_data_bytes)
7765 char *params = *pparams;
7766 char *pathname = NULL;
7768 int max_referral_level;
7769 NTSTATUS status = NT_STATUS_OK;
7770 TALLOC_CTX *ctx = talloc_tos();
7772 DEBUG(10,("call_trans2getdfsreferral\n"));
7774 if (total_params < 3) {
7775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7779 max_referral_level = SVAL(params,0);
7781 if(!lp_host_msdfs()) {
7782 reply_doserror(req, ERRDOS, ERRbadfunc);
7786 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7787 total_params - 2, STR_TERMINATE);
7789 reply_nterror(req, NT_STATUS_NOT_FOUND);
7792 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7793 ppdata,&status)) < 0) {
7794 reply_nterror(req, status);
7798 SSVAL(req->inbuf, smb_flg2,
7799 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7800 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7805 #define LMCAT_SPL 0x53
7806 #define LMFUNC_GETJOBID 0x60
7808 /****************************************************************************
7809 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7810 ****************************************************************************/
7812 static void call_trans2ioctl(connection_struct *conn,
7813 struct smb_request *req,
7814 char **pparams, int total_params,
7815 char **ppdata, int total_data,
7816 unsigned int max_data_bytes)
7818 char *pdata = *ppdata;
7819 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7821 /* check for an invalid fid before proceeding */
7824 reply_doserror(req, ERRDOS, ERRbadfid);
7828 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7829 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7830 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7831 if (*ppdata == NULL) {
7832 reply_nterror(req, NT_STATUS_NO_MEMORY);
7837 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7838 CAN ACCEPT THIS IN UNICODE. JRA. */
7840 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7841 srvstr_push(pdata, req->flags2, pdata + 2,
7842 global_myname(), 15,
7843 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7844 srvstr_push(pdata, req->flags2, pdata+18,
7845 lp_servicename(SNUM(conn)), 13,
7846 STR_ASCII|STR_TERMINATE); /* Service name */
7847 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7852 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7853 reply_doserror(req, ERRSRV, ERRerror);
7856 /****************************************************************************
7857 Reply to a SMBfindclose (stop trans2 directory search).
7858 ****************************************************************************/
7860 void reply_findclose(struct smb_request *req)
7864 START_PROFILE(SMBfindclose);
7867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7868 END_PROFILE(SMBfindclose);
7872 dptr_num = SVALS(req->vwv+0, 0);
7874 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7876 dptr_close(&dptr_num);
7878 reply_outbuf(req, 0, 0);
7880 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7882 END_PROFILE(SMBfindclose);
7886 /****************************************************************************
7887 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7888 ****************************************************************************/
7890 void reply_findnclose(struct smb_request *req)
7894 START_PROFILE(SMBfindnclose);
7897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7898 END_PROFILE(SMBfindnclose);
7902 dptr_num = SVAL(req->vwv+0, 0);
7904 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7906 /* We never give out valid handles for a
7907 findnotifyfirst - so any dptr_num is ok here.
7910 reply_outbuf(req, 0, 0);
7912 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7914 END_PROFILE(SMBfindnclose);
7918 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7919 struct trans_state *state)
7921 if (Protocol >= PROTOCOL_NT1) {
7922 req->flags2 |= 0x40; /* IS_LONG_NAME */
7923 SSVAL(req->inbuf,smb_flg2,req->flags2);
7926 if (conn->encrypt_level == Required && !req->encrypted) {
7927 if (state->call != TRANSACT2_QFSINFO &&
7928 state->call != TRANSACT2_SETFSINFO) {
7929 DEBUG(0,("handle_trans2: encryption required "
7931 (unsigned int)state->call));
7932 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7937 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7939 /* Now we must call the relevant TRANS2 function */
7940 switch(state->call) {
7941 case TRANSACT2_OPEN:
7943 START_PROFILE(Trans2_open);
7944 call_trans2open(conn, req,
7945 &state->param, state->total_param,
7946 &state->data, state->total_data,
7947 state->max_data_return);
7948 END_PROFILE(Trans2_open);
7952 case TRANSACT2_FINDFIRST:
7954 START_PROFILE(Trans2_findfirst);
7955 call_trans2findfirst(conn, req,
7956 &state->param, state->total_param,
7957 &state->data, state->total_data,
7958 state->max_data_return);
7959 END_PROFILE(Trans2_findfirst);
7963 case TRANSACT2_FINDNEXT:
7965 START_PROFILE(Trans2_findnext);
7966 call_trans2findnext(conn, req,
7967 &state->param, state->total_param,
7968 &state->data, state->total_data,
7969 state->max_data_return);
7970 END_PROFILE(Trans2_findnext);
7974 case TRANSACT2_QFSINFO:
7976 START_PROFILE(Trans2_qfsinfo);
7977 call_trans2qfsinfo(conn, req,
7978 &state->param, state->total_param,
7979 &state->data, state->total_data,
7980 state->max_data_return);
7981 END_PROFILE(Trans2_qfsinfo);
7985 case TRANSACT2_SETFSINFO:
7987 START_PROFILE(Trans2_setfsinfo);
7988 call_trans2setfsinfo(conn, req,
7989 &state->param, state->total_param,
7990 &state->data, state->total_data,
7991 state->max_data_return);
7992 END_PROFILE(Trans2_setfsinfo);
7996 case TRANSACT2_QPATHINFO:
7997 case TRANSACT2_QFILEINFO:
7999 START_PROFILE(Trans2_qpathinfo);
8000 call_trans2qfilepathinfo(conn, req, state->call,
8001 &state->param, state->total_param,
8002 &state->data, state->total_data,
8003 state->max_data_return);
8004 END_PROFILE(Trans2_qpathinfo);
8008 case TRANSACT2_SETPATHINFO:
8009 case TRANSACT2_SETFILEINFO:
8011 START_PROFILE(Trans2_setpathinfo);
8012 call_trans2setfilepathinfo(conn, req, state->call,
8013 &state->param, state->total_param,
8014 &state->data, state->total_data,
8015 state->max_data_return);
8016 END_PROFILE(Trans2_setpathinfo);
8020 case TRANSACT2_FINDNOTIFYFIRST:
8022 START_PROFILE(Trans2_findnotifyfirst);
8023 call_trans2findnotifyfirst(conn, req,
8024 &state->param, state->total_param,
8025 &state->data, state->total_data,
8026 state->max_data_return);
8027 END_PROFILE(Trans2_findnotifyfirst);
8031 case TRANSACT2_FINDNOTIFYNEXT:
8033 START_PROFILE(Trans2_findnotifynext);
8034 call_trans2findnotifynext(conn, req,
8035 &state->param, state->total_param,
8036 &state->data, state->total_data,
8037 state->max_data_return);
8038 END_PROFILE(Trans2_findnotifynext);
8042 case TRANSACT2_MKDIR:
8044 START_PROFILE(Trans2_mkdir);
8045 call_trans2mkdir(conn, req,
8046 &state->param, state->total_param,
8047 &state->data, state->total_data,
8048 state->max_data_return);
8049 END_PROFILE(Trans2_mkdir);
8053 case TRANSACT2_GET_DFS_REFERRAL:
8055 START_PROFILE(Trans2_get_dfs_referral);
8056 call_trans2getdfsreferral(conn, req,
8057 &state->param, state->total_param,
8058 &state->data, state->total_data,
8059 state->max_data_return);
8060 END_PROFILE(Trans2_get_dfs_referral);
8064 case TRANSACT2_IOCTL:
8066 START_PROFILE(Trans2_ioctl);
8067 call_trans2ioctl(conn, req,
8068 &state->param, state->total_param,
8069 &state->data, state->total_data,
8070 state->max_data_return);
8071 END_PROFILE(Trans2_ioctl);
8076 /* Error in request */
8077 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8078 reply_doserror(req, ERRSRV,ERRerror);
8082 /****************************************************************************
8083 Reply to a SMBtrans2.
8084 ****************************************************************************/
8086 void reply_trans2(struct smb_request *req)
8088 connection_struct *conn = req->conn;
8093 unsigned int tran_call;
8094 struct trans_state *state;
8097 START_PROFILE(SMBtrans2);
8099 if (req->wct < 14) {
8100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8101 END_PROFILE(SMBtrans2);
8105 dsoff = SVAL(req->vwv+12, 0);
8106 dscnt = SVAL(req->vwv+11, 0);
8107 psoff = SVAL(req->vwv+10, 0);
8108 pscnt = SVAL(req->vwv+9, 0);
8109 tran_call = SVAL(req->vwv+14, 0);
8111 result = allow_new_trans(conn->pending_trans, req->mid);
8112 if (!NT_STATUS_IS_OK(result)) {
8113 DEBUG(2, ("Got invalid trans2 request: %s\n",
8114 nt_errstr(result)));
8115 reply_nterror(req, result);
8116 END_PROFILE(SMBtrans2);
8121 switch (tran_call) {
8122 /* List the allowed trans2 calls on IPC$ */
8123 case TRANSACT2_OPEN:
8124 case TRANSACT2_GET_DFS_REFERRAL:
8125 case TRANSACT2_QFILEINFO:
8126 case TRANSACT2_QFSINFO:
8127 case TRANSACT2_SETFSINFO:
8130 reply_doserror(req, ERRSRV, ERRaccess);
8131 END_PROFILE(SMBtrans2);
8136 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8137 DEBUG(0, ("talloc failed\n"));
8138 reply_nterror(req, NT_STATUS_NO_MEMORY);
8139 END_PROFILE(SMBtrans2);
8143 state->cmd = SMBtrans2;
8145 state->mid = req->mid;
8146 state->vuid = req->vuid;
8147 state->setup_count = SVAL(req->vwv+13, 0);
8148 state->setup = NULL;
8149 state->total_param = SVAL(req->vwv+0, 0);
8150 state->param = NULL;
8151 state->total_data = SVAL(req->vwv+1, 0);
8153 state->max_param_return = SVAL(req->vwv+2, 0);
8154 state->max_data_return = SVAL(req->vwv+3, 0);
8155 state->max_setup_return = SVAL(req->vwv+4, 0);
8156 state->close_on_completion = BITSETW(req->vwv+5, 0);
8157 state->one_way = BITSETW(req->vwv+5, 1);
8159 state->call = tran_call;
8161 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8162 is so as a sanity check */
8163 if (state->setup_count != 1) {
8165 * Need to have rc=0 for ioctl to get job id for OS/2.
8166 * Network printing will fail if function is not successful.
8167 * Similar function in reply.c will be used if protocol
8168 * is LANMAN1.0 instead of LM1.2X002.
8169 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8170 * outbuf doesn't have to be set(only job id is used).
8172 if ( (state->setup_count == 4)
8173 && (tran_call == TRANSACT2_IOCTL)
8174 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8175 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8176 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8178 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8179 DEBUG(2,("Transaction is %d\n",tran_call));
8181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8182 END_PROFILE(SMBtrans2);
8187 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8190 if (state->total_data) {
8192 if (trans_oob(state->total_data, 0, dscnt)
8193 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8197 /* Can't use talloc here, the core routines do realloc on the
8198 * params and data. */
8199 state->data = (char *)SMB_MALLOC(state->total_data);
8200 if (state->data == NULL) {
8201 DEBUG(0,("reply_trans2: data malloc fail for %u "
8202 "bytes !\n", (unsigned int)state->total_data));
8204 reply_nterror(req, NT_STATUS_NO_MEMORY);
8205 END_PROFILE(SMBtrans2);
8209 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8212 if (state->total_param) {
8214 if (trans_oob(state->total_param, 0, pscnt)
8215 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8219 /* Can't use talloc here, the core routines do realloc on the
8220 * params and data. */
8221 state->param = (char *)SMB_MALLOC(state->total_param);
8222 if (state->param == NULL) {
8223 DEBUG(0,("reply_trans: param malloc fail for %u "
8224 "bytes !\n", (unsigned int)state->total_param));
8225 SAFE_FREE(state->data);
8227 reply_nterror(req, NT_STATUS_NO_MEMORY);
8228 END_PROFILE(SMBtrans2);
8232 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8235 state->received_data = dscnt;
8236 state->received_param = pscnt;
8238 if ((state->received_param == state->total_param) &&
8239 (state->received_data == state->total_data)) {
8241 handle_trans2(conn, req, state);
8243 SAFE_FREE(state->data);
8244 SAFE_FREE(state->param);
8246 END_PROFILE(SMBtrans2);
8250 DLIST_ADD(conn->pending_trans, state);
8252 /* We need to send an interim response then receive the rest
8253 of the parameter/data bytes */
8254 reply_outbuf(req, 0, 0);
8255 show_msg((char *)req->outbuf);
8256 END_PROFILE(SMBtrans2);
8261 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8262 SAFE_FREE(state->data);
8263 SAFE_FREE(state->param);
8265 END_PROFILE(SMBtrans2);
8266 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8270 /****************************************************************************
8271 Reply to a SMBtranss2
8272 ****************************************************************************/
8274 void reply_transs2(struct smb_request *req)
8276 connection_struct *conn = req->conn;
8277 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8278 struct trans_state *state;
8280 START_PROFILE(SMBtranss2);
8282 show_msg((char *)req->inbuf);
8285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8286 END_PROFILE(SMBtranss2);
8290 for (state = conn->pending_trans; state != NULL;
8291 state = state->next) {
8292 if (state->mid == req->mid) {
8297 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8298 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8299 END_PROFILE(SMBtranss2);
8303 /* Revise state->total_param and state->total_data in case they have
8304 changed downwards */
8306 if (SVAL(req->vwv+0, 0) < state->total_param)
8307 state->total_param = SVAL(req->vwv+0, 0);
8308 if (SVAL(req->vwv+1, 0) < state->total_data)
8309 state->total_data = SVAL(req->vwv+1, 0);
8311 pcnt = SVAL(req->vwv+2, 0);
8312 poff = SVAL(req->vwv+3, 0);
8313 pdisp = SVAL(req->vwv+4, 0);
8315 dcnt = SVAL(req->vwv+5, 0);
8316 doff = SVAL(req->vwv+6, 0);
8317 ddisp = SVAL(req->vwv+7, 0);
8319 state->received_param += pcnt;
8320 state->received_data += dcnt;
8322 if ((state->received_data > state->total_data) ||
8323 (state->received_param > state->total_param))
8327 if (trans_oob(state->total_param, pdisp, pcnt)
8328 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8331 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8335 if (trans_oob(state->total_data, ddisp, dcnt)
8336 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8339 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8342 if ((state->received_param < state->total_param) ||
8343 (state->received_data < state->total_data)) {
8344 END_PROFILE(SMBtranss2);
8348 handle_trans2(conn, req, state);
8350 DLIST_REMOVE(conn->pending_trans, state);
8351 SAFE_FREE(state->data);
8352 SAFE_FREE(state->param);
8355 END_PROFILE(SMBtranss2);
8360 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8361 DLIST_REMOVE(conn->pending_trans, state);
8362 SAFE_FREE(state->data);
8363 SAFE_FREE(state->param);
8365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8366 END_PROFILE(SMBtranss2);