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 /****************************************************************************
2691 Reply to a TRANS2_QFSINFO (query filesystem info).
2692 ****************************************************************************/
2694 static void call_trans2qfsinfo(connection_struct *conn,
2695 struct smb_request *req,
2696 char **pparams, int total_params,
2697 char **ppdata, int total_data,
2698 unsigned int max_data_bytes)
2700 char *pdata, *end_data;
2701 char *params = *pparams;
2705 const char *vname = volume_label(SNUM(conn));
2706 int snum = SNUM(conn);
2707 char *fstype = lp_fstype(SNUM(conn));
2708 uint32 additional_flags = 0;
2710 if (total_params < 2) {
2711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2715 info_level = SVAL(params,0);
2718 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2719 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2720 "info level (0x%x) on IPC$.\n",
2721 (unsigned int)info_level));
2722 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2727 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2728 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2729 DEBUG(0,("call_trans2qfsinfo: encryption required "
2730 "and info level 0x%x sent.\n",
2731 (unsigned int)info_level));
2732 exit_server_cleanly("encryption required "
2738 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2740 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
2741 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2742 reply_doserror(req, ERRSRV, ERRinvdevice);
2746 *ppdata = (char *)SMB_REALLOC(
2747 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2748 if (*ppdata == NULL ) {
2749 reply_nterror(req, NT_STATUS_NO_MEMORY);
2754 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2755 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2757 switch (info_level) {
2758 case SMB_INFO_ALLOCATION:
2760 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2762 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2763 reply_nterror(req, map_nt_error_from_unix(errno));
2767 block_size = lp_block_size(snum);
2768 if (bsize < block_size) {
2769 uint64_t factor = block_size/bsize;
2774 if (bsize > block_size) {
2775 uint64_t factor = bsize/block_size;
2780 bytes_per_sector = 512;
2781 sectors_per_unit = bsize/bytes_per_sector;
2783 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2784 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2785 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2787 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2788 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2789 SIVAL(pdata,l1_cUnit,dsize);
2790 SIVAL(pdata,l1_cUnitAvail,dfree);
2791 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2795 case SMB_INFO_VOLUME:
2796 /* Return volume name */
2798 * Add volume serial number - hash of a combination of
2799 * the called hostname and the service name.
2801 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2803 * Win2k3 and previous mess this up by sending a name length
2804 * one byte short. I believe only older clients (OS/2 Win9x) use
2805 * this call so try fixing this by adding a terminating null to
2806 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2810 pdata+l2_vol_szVolLabel, vname,
2811 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2812 STR_NOALIGN|STR_TERMINATE);
2813 SCVAL(pdata,l2_vol_cch,len);
2814 data_len = l2_vol_szVolLabel + len;
2815 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2816 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2820 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2821 case SMB_FS_ATTRIBUTE_INFORMATION:
2823 additional_flags = 0;
2824 #if defined(HAVE_SYS_QUOTAS)
2825 additional_flags |= FILE_VOLUME_QUOTAS;
2828 if(lp_nt_acl_support(SNUM(conn))) {
2829 additional_flags |= FILE_PERSISTENT_ACLS;
2832 /* Capabilities are filled in at connection time through STATVFS call */
2833 additional_flags |= conn->fs_capabilities;
2835 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2836 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2837 additional_flags); /* FS ATTRIBUTES */
2839 SIVAL(pdata,4,255); /* Max filename component length */
2840 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2841 and will think we can't do long filenames */
2842 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2843 PTR_DIFF(end_data, pdata+12),
2846 data_len = 12 + len;
2849 case SMB_QUERY_FS_LABEL_INFO:
2850 case SMB_FS_LABEL_INFORMATION:
2851 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2852 PTR_DIFF(end_data, pdata+4), 0);
2857 case SMB_QUERY_FS_VOLUME_INFO:
2858 case SMB_FS_VOLUME_INFORMATION:
2861 * Add volume serial number - hash of a combination of
2862 * the called hostname and the service name.
2864 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2865 (str_checksum(get_local_machine_name())<<16));
2867 /* Max label len is 32 characters. */
2868 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2869 PTR_DIFF(end_data, pdata+18),
2871 SIVAL(pdata,12,len);
2874 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2875 (int)strlen(vname),vname, lp_servicename(snum)));
2878 case SMB_QUERY_FS_SIZE_INFO:
2879 case SMB_FS_SIZE_INFORMATION:
2881 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2883 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2884 reply_nterror(req, 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,("call_trans2qfsinfo : SMB_QUERY_FS_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);
2906 SBIG_UINT(pdata,8,dfree);
2907 SIVAL(pdata,16,sectors_per_unit);
2908 SIVAL(pdata,20,bytes_per_sector);
2912 case SMB_FS_FULL_SIZE_INFORMATION:
2914 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2916 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2917 reply_nterror(req, map_nt_error_from_unix(errno));
2920 block_size = lp_block_size(snum);
2921 if (bsize < block_size) {
2922 uint64_t factor = block_size/bsize;
2927 if (bsize > block_size) {
2928 uint64_t factor = bsize/block_size;
2933 bytes_per_sector = 512;
2934 sectors_per_unit = bsize/bytes_per_sector;
2935 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2936 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2937 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2938 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2939 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2940 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2941 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2942 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2946 case SMB_QUERY_FS_DEVICE_INFO:
2947 case SMB_FS_DEVICE_INFORMATION:
2949 SIVAL(pdata,0,0); /* dev type */
2950 SIVAL(pdata,4,0); /* characteristics */
2953 #ifdef HAVE_SYS_QUOTAS
2954 case SMB_FS_QUOTA_INFORMATION:
2956 * what we have to send --metze:
2958 * Unknown1: 24 NULL bytes
2959 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2960 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2961 * Quota Flags: 2 byte :
2962 * Unknown3: 6 NULL bytes
2966 * details for Quota Flags:
2968 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2969 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2970 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2971 * 0x0001 Enable Quotas: enable quota for this fs
2975 /* we need to fake up a fsp here,
2976 * because its not send in this call
2979 SMB_NTQUOTA_STRUCT quotas;
2982 ZERO_STRUCT(quotas);
2988 if (conn->server_info->utok.uid != 0) {
2989 DEBUG(0,("set_user_quota: access_denied "
2990 "service [%s] user [%s]\n",
2991 lp_servicename(SNUM(conn)),
2992 conn->server_info->unix_name));
2993 reply_doserror(req, ERRDOS, ERRnoaccess);
2997 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2998 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2999 reply_doserror(req, ERRSRV, ERRerror);
3005 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
3007 /* Unknown1 24 NULL bytes*/
3008 SBIG_UINT(pdata,0,(uint64_t)0);
3009 SBIG_UINT(pdata,8,(uint64_t)0);
3010 SBIG_UINT(pdata,16,(uint64_t)0);
3012 /* Default Soft Quota 8 bytes */
3013 SBIG_UINT(pdata,24,quotas.softlim);
3015 /* Default Hard Quota 8 bytes */
3016 SBIG_UINT(pdata,32,quotas.hardlim);
3018 /* Quota flag 2 bytes */
3019 SSVAL(pdata,40,quotas.qflags);
3021 /* Unknown3 6 NULL bytes */
3027 #endif /* HAVE_SYS_QUOTAS */
3028 case SMB_FS_OBJECTID_INFORMATION:
3030 unsigned char objid[16];
3031 struct smb_extended_info extended_info;
3032 memcpy(pdata,create_volume_objectid(conn, objid),16);
3033 samba_extended_info_version (&extended_info);
3034 SIVAL(pdata,16,extended_info.samba_magic);
3035 SIVAL(pdata,20,extended_info.samba_version);
3036 SIVAL(pdata,24,extended_info.samba_subversion);
3037 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3038 memcpy(pdata+36,extended_info.samba_version_string,28);
3044 * Query the version and capabilities of the CIFS UNIX extensions
3048 case SMB_QUERY_CIFS_UNIX_INFO:
3050 bool large_write = lp_min_receive_file_size() &&
3051 !srv_is_signing_active(smbd_server_conn);
3052 bool large_read = !srv_is_signing_active(smbd_server_conn);
3053 int encrypt_caps = 0;
3055 if (!lp_unix_extensions()) {
3056 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3060 switch (conn->encrypt_level) {
3066 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3069 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3070 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3071 large_write = false;
3077 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3078 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3080 /* We have POSIX ACLs, pathname, encryption,
3081 * large read/write, and locking capability. */
3083 SBIG_UINT(pdata,4,((uint64_t)(
3084 CIFS_UNIX_POSIX_ACLS_CAP|
3085 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3086 CIFS_UNIX_FCNTL_LOCKS_CAP|
3087 CIFS_UNIX_EXTATTR_CAP|
3088 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3090 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3092 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3096 case SMB_QUERY_POSIX_FS_INFO:
3099 vfs_statvfs_struct svfs;
3101 if (!lp_unix_extensions()) {
3102 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3106 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3110 SIVAL(pdata,0,svfs.OptimalTransferSize);
3111 SIVAL(pdata,4,svfs.BlockSize);
3112 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3113 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3114 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3115 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3116 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3117 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3118 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3120 } else if (rc == EOPNOTSUPP) {
3121 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3123 #endif /* EOPNOTSUPP */
3125 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3126 reply_doserror(req, ERRSRV, ERRerror);
3132 case SMB_QUERY_POSIX_WHOAMI:
3138 if (!lp_unix_extensions()) {
3139 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3143 if (max_data_bytes < 40) {
3144 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3148 /* We ARE guest if global_sid_Builtin_Guests is
3149 * in our list of SIDs.
3151 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3152 conn->server_info->ptok)) {
3153 flags |= SMB_WHOAMI_GUEST;
3156 /* We are NOT guest if global_sid_Authenticated_Users
3157 * is in our list of SIDs.
3159 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3160 conn->server_info->ptok)) {
3161 flags &= ~SMB_WHOAMI_GUEST;
3164 /* NOTE: 8 bytes for UID/GID, irrespective of native
3165 * platform size. This matches
3166 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3168 data_len = 4 /* flags */
3175 + 4 /* pad/reserved */
3176 + (conn->server_info->utok.ngroups * 8)
3178 + (conn->server_info->ptok->num_sids *
3182 SIVAL(pdata, 0, flags);
3183 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3185 (uint64_t)conn->server_info->utok.uid);
3186 SBIG_UINT(pdata, 16,
3187 (uint64_t)conn->server_info->utok.gid);
3190 if (data_len >= max_data_bytes) {
3191 /* Potential overflow, skip the GIDs and SIDs. */
3193 SIVAL(pdata, 24, 0); /* num_groups */
3194 SIVAL(pdata, 28, 0); /* num_sids */
3195 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3196 SIVAL(pdata, 36, 0); /* reserved */
3202 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3203 SIVAL(pdata, 28, conn->server_info->num_sids);
3205 /* We walk the SID list twice, but this call is fairly
3206 * infrequent, and I don't expect that it's performance
3207 * sensitive -- jpeach
3209 for (i = 0, sid_bytes = 0;
3210 i < conn->server_info->ptok->num_sids; ++i) {
3211 sid_bytes += ndr_size_dom_sid(
3212 &conn->server_info->ptok->user_sids[i],
3217 /* SID list byte count */
3218 SIVAL(pdata, 32, sid_bytes);
3220 /* 4 bytes pad/reserved - must be zero */
3221 SIVAL(pdata, 36, 0);
3225 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3226 SBIG_UINT(pdata, data_len,
3227 (uint64_t)conn->server_info->utok.groups[i]);
3233 i < conn->server_info->ptok->num_sids; ++i) {
3234 int sid_len = ndr_size_dom_sid(
3235 &conn->server_info->ptok->user_sids[i],
3239 sid_linearize(pdata + data_len, sid_len,
3240 &conn->server_info->ptok->user_sids[i]);
3241 data_len += sid_len;
3247 case SMB_MAC_QUERY_FS_INFO:
3249 * Thursby MAC extension... ONLY on NTFS filesystems
3250 * once we do streams then we don't need this
3252 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3254 SIVAL(pdata,84,0x100); /* Don't support mac... */
3259 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3264 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3267 DEBUG( 4, ( "%s info_level = %d\n",
3268 smb_fn_name(req->cmd), info_level) );
3273 /****************************************************************************
3274 Reply to a TRANS2_SETFSINFO (set filesystem info).
3275 ****************************************************************************/
3277 static void call_trans2setfsinfo(connection_struct *conn,
3278 struct smb_request *req,
3279 char **pparams, int total_params,
3280 char **ppdata, int total_data,
3281 unsigned int max_data_bytes)
3283 char *pdata = *ppdata;
3284 char *params = *pparams;
3287 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3290 if (total_params < 4) {
3291 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3297 info_level = SVAL(params,2);
3300 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3301 info_level != SMB_SET_CIFS_UNIX_INFO) {
3302 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3303 "info level (0x%x) on IPC$.\n",
3304 (unsigned int)info_level));
3305 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3310 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3311 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3312 DEBUG(0,("call_trans2setfsinfo: encryption required "
3313 "and info level 0x%x sent.\n",
3314 (unsigned int)info_level));
3315 exit_server_cleanly("encryption required "
3321 switch(info_level) {
3322 case SMB_SET_CIFS_UNIX_INFO:
3324 uint16 client_unix_major;
3325 uint16 client_unix_minor;
3326 uint32 client_unix_cap_low;
3327 uint32 client_unix_cap_high;
3329 if (!lp_unix_extensions()) {
3331 NT_STATUS_INVALID_LEVEL);
3335 /* There should be 12 bytes of capabilities set. */
3336 if (total_data < 8) {
3339 NT_STATUS_INVALID_PARAMETER);
3342 client_unix_major = SVAL(pdata,0);
3343 client_unix_minor = SVAL(pdata,2);
3344 client_unix_cap_low = IVAL(pdata,4);
3345 client_unix_cap_high = IVAL(pdata,8);
3346 /* Just print these values for now. */
3347 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3348 cap_low = 0x%x, cap_high = 0x%x\n",
3349 (unsigned int)client_unix_major,
3350 (unsigned int)client_unix_minor,
3351 (unsigned int)client_unix_cap_low,
3352 (unsigned int)client_unix_cap_high ));
3354 /* Here is where we must switch to posix pathname processing... */
3355 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3356 lp_set_posix_pathnames();
3357 mangle_change_to_posix();
3360 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3361 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3362 /* Client that knows how to do posix locks,
3363 * but not posix open/mkdir operations. Set a
3364 * default type for read/write checks. */
3366 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3372 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3375 size_t param_len = 0;
3376 size_t data_len = total_data;
3378 if (!lp_unix_extensions()) {
3381 NT_STATUS_INVALID_LEVEL);
3385 if (lp_smb_encrypt(SNUM(conn)) == false) {
3388 NT_STATUS_NOT_SUPPORTED);
3392 DEBUG( 4,("call_trans2setfsinfo: "
3393 "request transport encryption.\n"));
3395 status = srv_request_encryption_setup(conn,
3396 (unsigned char **)ppdata,
3398 (unsigned char **)pparams,
3401 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3402 !NT_STATUS_IS_OK(status)) {
3403 reply_nterror(req, status);
3407 send_trans2_replies(conn, req,
3414 if (NT_STATUS_IS_OK(status)) {
3415 /* Server-side transport
3416 * encryption is now *on*. */
3417 status = srv_encryption_start(conn);
3418 if (!NT_STATUS_IS_OK(status)) {
3419 exit_server_cleanly(
3420 "Failure in setting "
3421 "up encrypted transport");
3427 case SMB_FS_QUOTA_INFORMATION:
3429 files_struct *fsp = NULL;
3430 SMB_NTQUOTA_STRUCT quotas;
3432 ZERO_STRUCT(quotas);
3435 if ((conn->server_info->utok.uid != 0)
3436 ||!CAN_WRITE(conn)) {
3437 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3438 lp_servicename(SNUM(conn)),
3439 conn->server_info->unix_name));
3440 reply_doserror(req, ERRSRV, ERRaccess);
3444 /* note: normaly there're 48 bytes,
3445 * but we didn't use the last 6 bytes for now
3448 fsp = file_fsp(req, SVAL(params,0));
3450 if (!check_fsp_ntquota_handle(conn, req,
3452 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3454 req, NT_STATUS_INVALID_HANDLE);
3458 if (total_data < 42) {
3459 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3463 NT_STATUS_INVALID_PARAMETER);
3467 /* unknown_1 24 NULL bytes in pdata*/
3469 /* the soft quotas 8 bytes (uint64_t)*/
3470 quotas.softlim = (uint64_t)IVAL(pdata,24);
3471 #ifdef LARGE_SMB_OFF_T
3472 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3473 #else /* LARGE_SMB_OFF_T */
3474 if ((IVAL(pdata,28) != 0)&&
3475 ((quotas.softlim != 0xFFFFFFFF)||
3476 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3477 /* more than 32 bits? */
3480 NT_STATUS_INVALID_PARAMETER);
3483 #endif /* LARGE_SMB_OFF_T */
3485 /* the hard quotas 8 bytes (uint64_t)*/
3486 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3487 #ifdef LARGE_SMB_OFF_T
3488 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3489 #else /* LARGE_SMB_OFF_T */
3490 if ((IVAL(pdata,36) != 0)&&
3491 ((quotas.hardlim != 0xFFFFFFFF)||
3492 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3493 /* more than 32 bits? */
3496 NT_STATUS_INVALID_PARAMETER);
3499 #endif /* LARGE_SMB_OFF_T */
3501 /* quota_flags 2 bytes **/
3502 quotas.qflags = SVAL(pdata,40);
3504 /* unknown_2 6 NULL bytes follow*/
3506 /* now set the quotas */
3507 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3508 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3509 reply_doserror(req, ERRSRV, ERRerror);
3516 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3518 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3524 * sending this reply works fine,
3525 * but I'm not sure it's the same
3526 * like windows do...
3529 reply_outbuf(req, 10, 0);
3532 #if defined(HAVE_POSIX_ACLS)
3533 /****************************************************************************
3534 Utility function to count the number of entries in a POSIX acl.
3535 ****************************************************************************/
3537 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3539 unsigned int ace_count = 0;
3540 int entry_id = SMB_ACL_FIRST_ENTRY;
3541 SMB_ACL_ENTRY_T entry;
3543 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3545 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3546 entry_id = SMB_ACL_NEXT_ENTRY;
3553 /****************************************************************************
3554 Utility function to marshall a POSIX acl into wire format.
3555 ****************************************************************************/
3557 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3559 int entry_id = SMB_ACL_FIRST_ENTRY;
3560 SMB_ACL_ENTRY_T entry;
3562 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3563 SMB_ACL_TAG_T tagtype;
3564 SMB_ACL_PERMSET_T permset;
3565 unsigned char perms = 0;
3566 unsigned int own_grp;
3569 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3570 entry_id = SMB_ACL_NEXT_ENTRY;
3573 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3574 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3578 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3579 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3583 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3584 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3585 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3587 SCVAL(pdata,1,perms);
3590 case SMB_ACL_USER_OBJ:
3591 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3592 own_grp = (unsigned int)pst->st_ex_uid;
3593 SIVAL(pdata,2,own_grp);
3598 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3600 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3603 own_grp = (unsigned int)*puid;
3604 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3605 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3606 SIVAL(pdata,2,own_grp);
3610 case SMB_ACL_GROUP_OBJ:
3611 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3612 own_grp = (unsigned int)pst->st_ex_gid;
3613 SIVAL(pdata,2,own_grp);
3618 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3620 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3623 own_grp = (unsigned int)*pgid;
3624 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3625 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3626 SIVAL(pdata,2,own_grp);
3631 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3632 SIVAL(pdata,2,0xFFFFFFFF);
3633 SIVAL(pdata,6,0xFFFFFFFF);
3636 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3637 SIVAL(pdata,2,0xFFFFFFFF);
3638 SIVAL(pdata,6,0xFFFFFFFF);
3641 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3644 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3651 /****************************************************************************
3652 Store the FILE_UNIX_BASIC info.
3653 ****************************************************************************/
3655 static char *store_file_unix_basic(connection_struct *conn,
3658 const SMB_STRUCT_STAT *psbuf)
3660 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3661 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3663 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3666 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3669 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3670 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3671 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3674 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3678 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3682 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3685 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3689 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3693 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3696 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3700 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3707 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3708 * the chflags(2) (or equivalent) flags.
3710 * XXX: this really should be behind the VFS interface. To do this, we would
3711 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3712 * Each VFS module could then implement its own mapping as appropriate for the
3713 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3715 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3719 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3723 { UF_IMMUTABLE, EXT_IMMUTABLE },
3727 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3731 { UF_HIDDEN, EXT_HIDDEN },
3734 /* Do not remove. We need to guarantee that this array has at least one
3735 * entry to build on HP-UX.
3741 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3742 uint32 *smb_fflags, uint32 *smb_fmask)
3746 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3747 *smb_fmask |= info2_flags_map[i].smb_fflag;
3748 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3749 *smb_fflags |= info2_flags_map[i].smb_fflag;
3754 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3755 const uint32 smb_fflags,
3756 const uint32 smb_fmask,
3759 uint32 max_fmask = 0;
3762 *stat_fflags = psbuf->st_ex_flags;
3764 /* For each flags requested in smb_fmask, check the state of the
3765 * corresponding flag in smb_fflags and set or clear the matching
3769 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3770 max_fmask |= info2_flags_map[i].smb_fflag;
3771 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3772 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3773 *stat_fflags |= info2_flags_map[i].stat_fflag;
3775 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3780 /* If smb_fmask is asking to set any bits that are not supported by
3781 * our flag mappings, we should fail.
3783 if ((smb_fmask & max_fmask) != smb_fmask) {
3791 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3792 * of file flags and birth (create) time.
3794 static char *store_file_unix_basic_info2(connection_struct *conn,
3797 const SMB_STRUCT_STAT *psbuf)
3799 uint32 file_flags = 0;
3800 uint32 flags_mask = 0;
3802 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3804 /* Create (birth) time 64 bit */
3805 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3808 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3809 SIVAL(pdata, 0, file_flags); /* flags */
3810 SIVAL(pdata, 4, flags_mask); /* mask */
3816 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3817 const struct stream_struct *streams,
3819 unsigned int max_data_bytes,
3820 unsigned int *data_size)
3823 unsigned int ofs = 0;
3825 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3826 unsigned int next_offset;
3828 smb_ucs2_t *namebuf;
3830 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3831 streams[i].name, &namelen) ||
3834 return NT_STATUS_INVALID_PARAMETER;
3838 * name_buf is now null-terminated, we need to marshall as not
3844 SIVAL(data, ofs+4, namelen);
3845 SOFF_T(data, ofs+8, streams[i].size);
3846 SOFF_T(data, ofs+16, streams[i].alloc_size);
3847 memcpy(data+ofs+24, namebuf, namelen);
3848 TALLOC_FREE(namebuf);
3850 next_offset = ofs + 24 + namelen;
3852 if (i == num_streams-1) {
3853 SIVAL(data, ofs, 0);
3856 unsigned int align = ndr_align_size(next_offset, 8);
3858 memset(data+next_offset, 0, align);
3859 next_offset += align;
3861 SIVAL(data, ofs, next_offset - ofs);
3870 return NT_STATUS_OK;
3873 /****************************************************************************
3874 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3875 ****************************************************************************/
3877 static void call_trans2qpipeinfo(connection_struct *conn,
3878 struct smb_request *req,
3879 unsigned int tran_call,
3880 char **pparams, int total_params,
3881 char **ppdata, int total_data,
3882 unsigned int max_data_bytes)
3884 char *params = *pparams;
3885 char *pdata = *ppdata;
3886 unsigned int data_size = 0;
3887 unsigned int param_size = 2;
3892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3896 if (total_params < 4) {
3897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3901 fsp = file_fsp(req, SVAL(params,0));
3902 if (!fsp_is_np(fsp)) {
3903 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3907 info_level = SVAL(params,2);
3909 *pparams = (char *)SMB_REALLOC(*pparams,2);
3910 if (*pparams == NULL) {
3911 reply_nterror(req, NT_STATUS_NO_MEMORY);
3916 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3917 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3918 if (*ppdata == NULL ) {
3919 reply_nterror(req, NT_STATUS_NO_MEMORY);
3924 switch (info_level) {
3925 case SMB_FILE_STANDARD_INFORMATION:
3927 SOFF_T(pdata,0,4096LL);
3934 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3938 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3944 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3945 TALLOC_CTX *mem_ctx,
3946 uint16_t info_level,
3948 const struct smb_filename *smb_fname,
3949 bool delete_pending,
3950 struct timespec write_time_ts,
3952 struct ea_list *ea_list,
3953 int lock_data_count,
3956 unsigned int max_data_bytes,
3958 unsigned int *pdata_size)
3960 char *pdata = *ppdata;
3961 char *dstart, *dend;
3962 unsigned int data_size;
3963 struct timespec create_time_ts, mtime_ts, atime_ts;
3964 time_t create_time, mtime, atime;
3965 SMB_STRUCT_STAT sbuf;
3973 uint64_t file_size = 0;
3975 uint64_t allocation_size = 0;
3976 uint64_t file_index = 0;
3977 uint32_t access_mask = 0;
3979 sbuf = smb_fname->st;
3981 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3982 return NT_STATUS_INVALID_LEVEL;
3985 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
3986 if (!NT_STATUS_IS_OK(status)) {
3990 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
3991 fname, fsp ? fsp->fnum : -1, info_level, max_data_bytes));
3994 mode = dos_mode_msdfs(conn, smb_fname);
3996 mode = dos_mode(conn, smb_fname);
3999 mode = FILE_ATTRIBUTE_NORMAL;
4001 nlink = sbuf.st_ex_nlink;
4003 if (nlink && (mode&aDIR)) {
4007 if ((nlink > 0) && delete_pending) {
4011 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4012 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4013 if (*ppdata == NULL) {
4014 return NT_STATUS_NO_MEMORY;
4018 dend = dstart + data_size - 1;
4020 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4021 update_stat_ex_mtime(&sbuf, write_time_ts);
4024 create_time_ts = sbuf.st_ex_btime;
4025 mtime_ts = sbuf.st_ex_mtime;
4026 atime_ts = sbuf.st_ex_atime;
4028 if (lp_dos_filetime_resolution(SNUM(conn))) {
4029 dos_filetime_timespec(&create_time_ts);
4030 dos_filetime_timespec(&mtime_ts);
4031 dos_filetime_timespec(&atime_ts);
4034 create_time = convert_timespec_to_time_t(create_time_ts);
4035 mtime = convert_timespec_to_time_t(mtime_ts);
4036 atime = convert_timespec_to_time_t(atime_ts);
4038 p = strrchr_m(smb_fname->base_name,'/');
4040 base_name = smb_fname->base_name;
4044 /* NT expects the name to be in an exact form of the *full*
4045 filename. See the trans2 torture test */
4046 if (ISDOT(base_name)) {
4047 dos_fname = talloc_strdup(mem_ctx, "\\");
4049 return NT_STATUS_NO_MEMORY;
4052 dos_fname = talloc_asprintf(mem_ctx,
4056 return NT_STATUS_NO_MEMORY;
4058 string_replace(dos_fname, '/', '\\');
4061 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4064 /* Do we have this path open ? */
4066 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4067 fsp1 = file_find_di_first(fileid);
4068 if (fsp1 && fsp1->initial_allocation_size) {
4069 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4073 if (!(mode & aDIR)) {
4074 file_size = get_file_size_stat(&sbuf);
4077 if (fsp && fsp->fh) {
4078 pos = fsp->fh->position_information;
4082 access_mask = fsp->access_mask;
4084 /* GENERIC_EXECUTE mapping from Windows */
4085 access_mask = 0x12019F;
4088 /* This should be an index number - looks like
4091 I think this causes us to fail the IFSKIT
4092 BasicFileInformationTest. -tpot */
4093 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4094 file_index |= ((sbuf.st_ex_dev) & UINT32_MAX) << 32; /* FileIndexHigh */
4096 switch (info_level) {
4097 case SMB_INFO_STANDARD:
4098 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4100 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4101 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4102 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4103 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4104 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4105 SSVAL(pdata,l1_attrFile,mode);
4108 case SMB_INFO_QUERY_EA_SIZE:
4110 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4111 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4113 srv_put_dos_date2(pdata,0,create_time);
4114 srv_put_dos_date2(pdata,4,atime);
4115 srv_put_dos_date2(pdata,8,mtime); /* write time */
4116 SIVAL(pdata,12,(uint32)file_size);
4117 SIVAL(pdata,16,(uint32)allocation_size);
4118 SSVAL(pdata,20,mode);
4119 SIVAL(pdata,22,ea_size);
4123 case SMB_INFO_IS_NAME_VALID:
4124 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4126 /* os/2 needs this ? really ?*/
4127 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4129 /* This is only reached for qpathinfo */
4133 case SMB_INFO_QUERY_EAS_FROM_LIST:
4135 size_t total_ea_len = 0;
4136 struct ea_list *ea_file_list = NULL;
4138 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4140 ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4141 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4143 if (!ea_list || (total_ea_len > data_size)) {
4145 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4149 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4153 case SMB_INFO_QUERY_ALL_EAS:
4155 /* We have data_size bytes to put EA's into. */
4156 size_t total_ea_len = 0;
4158 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4160 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4161 if (!ea_list || (total_ea_len > data_size)) {
4163 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4167 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4171 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4173 /* We have data_size bytes to put EA's into. */
4174 size_t total_ea_len = 0;
4175 struct ea_list *ea_file_list = NULL;
4177 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4179 /*TODO: add filtering and index handling */
4181 ea_file_list = get_ea_list_from_file(mem_ctx,
4185 if (!ea_file_list) {
4186 return NT_STATUS_NO_EAS_ON_FILE;
4189 status = fill_ea_chained_buffer(mem_ctx,
4193 conn, ea_file_list);
4194 if (!NT_STATUS_IS_OK(status)) {
4200 case SMB_FILE_BASIC_INFORMATION:
4201 case SMB_QUERY_FILE_BASIC_INFO:
4203 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4204 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4205 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4207 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4211 put_long_date_timespec(pdata,create_time_ts);
4212 put_long_date_timespec(pdata+8,atime_ts);
4213 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4214 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4215 SIVAL(pdata,32,mode);
4217 DEBUG(5,("SMB_QFBI - "));
4218 DEBUG(5,("create: %s ", ctime(&create_time)));
4219 DEBUG(5,("access: %s ", ctime(&atime)));
4220 DEBUG(5,("write: %s ", ctime(&mtime)));
4221 DEBUG(5,("change: %s ", ctime(&mtime)));
4222 DEBUG(5,("mode: %x\n", mode));
4225 case SMB_FILE_STANDARD_INFORMATION:
4226 case SMB_QUERY_FILE_STANDARD_INFO:
4228 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4230 SOFF_T(pdata,0,allocation_size);
4231 SOFF_T(pdata,8,file_size);
4232 SIVAL(pdata,16,nlink);
4233 SCVAL(pdata,20,delete_pending?1:0);
4234 SCVAL(pdata,21,(mode&aDIR)?1:0);
4235 SSVAL(pdata,22,0); /* Padding. */
4238 case SMB_FILE_EA_INFORMATION:
4239 case SMB_QUERY_FILE_EA_INFO:
4241 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4242 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4244 SIVAL(pdata,0,ea_size);
4248 /* Get the 8.3 name - used if NT SMB was negotiated. */
4249 case SMB_QUERY_FILE_ALT_NAME_INFO:
4250 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4253 char mangled_name[13];
4254 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4255 if (!name_to_8_3(base_name,mangled_name,
4256 True,conn->params)) {
4257 return NT_STATUS_NO_MEMORY;
4259 len = srvstr_push(dstart, flags2,
4260 pdata+4, mangled_name,
4261 PTR_DIFF(dend, pdata+4),
4263 data_size = 4 + len;
4268 case SMB_QUERY_FILE_NAME_INFO:
4272 this must be *exactly* right for ACLs on mapped drives to work
4274 len = srvstr_push(dstart, flags2,
4276 PTR_DIFF(dend, pdata+4),
4278 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4279 data_size = 4 + len;
4284 case SMB_FILE_ALLOCATION_INFORMATION:
4285 case SMB_QUERY_FILE_ALLOCATION_INFO:
4286 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4288 SOFF_T(pdata,0,allocation_size);
4291 case SMB_FILE_END_OF_FILE_INFORMATION:
4292 case SMB_QUERY_FILE_END_OF_FILEINFO:
4293 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4295 SOFF_T(pdata,0,file_size);
4298 case SMB_QUERY_FILE_ALL_INFO:
4299 case SMB_FILE_ALL_INFORMATION:
4302 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4303 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4304 put_long_date_timespec(pdata,create_time_ts);
4305 put_long_date_timespec(pdata+8,atime_ts);
4306 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4307 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4308 SIVAL(pdata,32,mode);
4309 SIVAL(pdata,36,0); /* padding. */
4311 SOFF_T(pdata,0,allocation_size);
4312 SOFF_T(pdata,8,file_size);
4313 SIVAL(pdata,16,nlink);
4314 SCVAL(pdata,20,delete_pending);
4315 SCVAL(pdata,21,(mode&aDIR)?1:0);
4318 SIVAL(pdata,0,ea_size);
4319 pdata += 4; /* EA info */
4320 len = srvstr_push(dstart, flags2,
4322 PTR_DIFF(dend, pdata+4),
4326 data_size = PTR_DIFF(pdata,(*ppdata));
4330 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4333 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4334 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4335 put_long_date_timespec(pdata+0x00,create_time_ts);
4336 put_long_date_timespec(pdata+0x08,atime_ts);
4337 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4338 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4339 SIVAL(pdata, 0x20, mode);
4340 SIVAL(pdata, 0x24, 0); /* padding. */
4341 SBVAL(pdata, 0x28, allocation_size);
4342 SBVAL(pdata, 0x30, file_size);
4343 SIVAL(pdata, 0x38, nlink);
4344 SCVAL(pdata, 0x3C, delete_pending);
4345 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4346 SSVAL(pdata, 0x3E, 0); /* padding */
4347 SBVAL(pdata, 0x40, file_index);
4348 SIVAL(pdata, 0x48, ea_size);
4349 SIVAL(pdata, 0x4C, access_mask);
4350 SBVAL(pdata, 0x50, pos);
4351 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4352 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4356 len = srvstr_push(dstart, flags2,
4358 PTR_DIFF(dend, pdata+4),
4362 data_size = PTR_DIFF(pdata,(*ppdata));
4365 case SMB_FILE_INTERNAL_INFORMATION:
4367 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4368 SBVAL(pdata, 0, file_index);
4372 case SMB_FILE_ACCESS_INFORMATION:
4373 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4374 SIVAL(pdata, 0, access_mask);
4378 case SMB_FILE_NAME_INFORMATION:
4379 /* Pathname with leading '\'. */
4382 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4383 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4384 SIVAL(pdata,0,byte_len);
4385 data_size = 4 + byte_len;
4389 case SMB_FILE_DISPOSITION_INFORMATION:
4390 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4392 SCVAL(pdata,0,delete_pending);
4395 case SMB_FILE_POSITION_INFORMATION:
4396 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4398 SOFF_T(pdata,0,pos);
4401 case SMB_FILE_MODE_INFORMATION:
4402 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4403 SIVAL(pdata,0,mode);
4407 case SMB_FILE_ALIGNMENT_INFORMATION:
4408 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4409 SIVAL(pdata,0,0); /* No alignment needed. */
4414 * NT4 server just returns "invalid query" to this - if we try
4415 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4418 /* The first statement above is false - verified using Thursby
4419 * client against NT4 -- gcolley.
4421 case SMB_QUERY_FILE_STREAM_INFO:
4422 case SMB_FILE_STREAM_INFORMATION: {
4423 unsigned int num_streams;
4424 struct stream_struct *streams;
4426 DEBUG(10,("smbd_do_qfilepathinfo: "
4427 "SMB_FILE_STREAM_INFORMATION\n"));
4429 status = SMB_VFS_STREAMINFO(
4430 conn, fsp, fname, talloc_tos(),
4431 &num_streams, &streams);
4433 if (!NT_STATUS_IS_OK(status)) {
4434 DEBUG(10, ("could not get stream info: %s\n",
4435 nt_errstr(status)));
4439 status = marshall_stream_info(num_streams, streams,
4440 pdata, max_data_bytes,
4443 if (!NT_STATUS_IS_OK(status)) {
4444 DEBUG(10, ("marshall_stream_info failed: %s\n",
4445 nt_errstr(status)));
4449 TALLOC_FREE(streams);
4453 case SMB_QUERY_COMPRESSION_INFO:
4454 case SMB_FILE_COMPRESSION_INFORMATION:
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4456 SOFF_T(pdata,0,file_size);
4457 SIVAL(pdata,8,0); /* ??? */
4458 SIVAL(pdata,12,0); /* ??? */
4462 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4463 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4464 put_long_date_timespec(pdata,create_time_ts);
4465 put_long_date_timespec(pdata+8,atime_ts);
4466 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4467 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4468 SOFF_T(pdata,32,allocation_size);
4469 SOFF_T(pdata,40,file_size);
4470 SIVAL(pdata,48,mode);
4471 SIVAL(pdata,52,0); /* ??? */
4475 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4477 SIVAL(pdata,0,mode);
4483 * CIFS UNIX Extensions.
4486 case SMB_QUERY_FILE_UNIX_BASIC:
4488 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4489 data_size = PTR_DIFF(pdata,(*ppdata));
4493 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4495 for (i=0; i<100; i++)
4496 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4502 case SMB_QUERY_FILE_UNIX_INFO2:
4504 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4505 data_size = PTR_DIFF(pdata,(*ppdata));
4509 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4511 for (i=0; i<100; i++)
4512 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4518 case SMB_QUERY_FILE_UNIX_LINK:
4521 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4524 return NT_STATUS_NO_MEMORY;
4527 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4529 if(!S_ISLNK(sbuf.st_ex_mode)) {
4530 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4533 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4535 len = SMB_VFS_READLINK(conn,fname,
4538 return map_nt_error_from_unix(errno);
4541 len = srvstr_push(dstart, flags2,
4543 PTR_DIFF(dend, pdata),
4546 data_size = PTR_DIFF(pdata,(*ppdata));
4551 #if defined(HAVE_POSIX_ACLS)
4552 case SMB_QUERY_POSIX_ACL:
4554 SMB_ACL_T file_acl = NULL;
4555 SMB_ACL_T def_acl = NULL;
4556 uint16 num_file_acls = 0;
4557 uint16 num_def_acls = 0;
4559 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4560 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4562 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4565 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4566 DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4568 return NT_STATUS_NOT_IMPLEMENTED;
4571 if (S_ISDIR(sbuf.st_ex_mode)) {
4572 if (fsp && fsp->is_directory) {
4573 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4575 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4577 def_acl = free_empty_sys_acl(conn, def_acl);
4580 num_file_acls = count_acl_entries(conn, file_acl);
4581 num_def_acls = count_acl_entries(conn, def_acl);
4583 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4584 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4586 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4587 SMB_POSIX_ACL_HEADER_SIZE) ));
4589 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4592 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4594 return NT_STATUS_BUFFER_TOO_SMALL;
4597 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4598 SSVAL(pdata,2,num_file_acls);
4599 SSVAL(pdata,4,num_def_acls);
4600 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4602 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4605 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4607 return NT_STATUS_INTERNAL_ERROR;
4609 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4611 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4614 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4616 return NT_STATUS_INTERNAL_ERROR;
4620 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4623 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4625 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4631 case SMB_QUERY_POSIX_LOCK:
4636 enum brl_type lock_type;
4638 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4639 return NT_STATUS_INVALID_PARAMETER;
4642 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4643 case POSIX_LOCK_TYPE_READ:
4644 lock_type = READ_LOCK;
4646 case POSIX_LOCK_TYPE_WRITE:
4647 lock_type = WRITE_LOCK;
4649 case POSIX_LOCK_TYPE_UNLOCK:
4651 /* There's no point in asking for an unlock... */
4652 return NT_STATUS_INVALID_PARAMETER;
4655 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4656 #if defined(HAVE_LONGLONG)
4657 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4658 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4659 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4660 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4661 #else /* HAVE_LONGLONG */
4662 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4663 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4664 #endif /* HAVE_LONGLONG */
4666 status = query_lock(fsp,
4673 if (ERROR_WAS_LOCK_DENIED(status)) {
4674 /* Here we need to report who has it locked... */
4675 data_size = POSIX_LOCK_DATA_SIZE;
4677 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4678 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4679 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4680 #if defined(HAVE_LONGLONG)
4681 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4682 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4683 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4684 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4685 #else /* HAVE_LONGLONG */
4686 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4687 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4688 #endif /* HAVE_LONGLONG */
4690 } else if (NT_STATUS_IS_OK(status)) {
4691 /* For success we just return a copy of what we sent
4692 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4693 data_size = POSIX_LOCK_DATA_SIZE;
4694 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4695 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4703 return NT_STATUS_INVALID_LEVEL;
4706 *pdata_size = data_size;
4707 return NT_STATUS_OK;
4710 /****************************************************************************
4711 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4712 file name or file id).
4713 ****************************************************************************/
4715 static void call_trans2qfilepathinfo(connection_struct *conn,
4716 struct smb_request *req,
4717 unsigned int tran_call,
4718 char **pparams, int total_params,
4719 char **ppdata, int total_data,
4720 unsigned int max_data_bytes)
4722 char *params = *pparams;
4723 char *pdata = *ppdata;
4725 unsigned int data_size = 0;
4726 unsigned int param_size = 2;
4728 struct smb_filename *smb_fname = NULL;
4729 bool delete_pending = False;
4730 struct timespec write_time_ts;
4731 files_struct *fsp = NULL;
4732 struct file_id fileid;
4733 struct ea_list *ea_list = NULL;
4734 int lock_data_count = 0;
4735 char *lock_data = NULL;
4736 bool ms_dfs_link = false;
4737 NTSTATUS status = NT_STATUS_OK;
4740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4744 ZERO_STRUCT(write_time_ts);
4746 if (tran_call == TRANSACT2_QFILEINFO) {
4747 if (total_params < 4) {
4748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4753 call_trans2qpipeinfo(conn, req, tran_call,
4754 pparams, total_params,
4760 fsp = file_fsp(req, SVAL(params,0));
4761 info_level = SVAL(params,2);
4763 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4765 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4766 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4770 /* Initial check for valid fsp ptr. */
4771 if (!check_fsp_open(conn, req, fsp)) {
4775 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
4777 reply_nterror(req, NT_STATUS_NO_MEMORY);
4781 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
4783 if (!NT_STATUS_IS_OK(status)) {
4784 reply_nterror(req, status);
4788 if(fsp->fake_file_handle) {
4790 * This is actually for the QUOTA_FAKE_FILE --metze
4793 /* We know this name is ok, it's already passed the checks. */
4795 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
4797 * This is actually a QFILEINFO on a directory
4798 * handle (returned from an NT SMB). NT5.0 seems
4799 * to do this call. JRA.
4802 if (INFO_LEVEL_IS_UNIX(info_level)) {
4803 /* Always do lstat for UNIX calls. */
4804 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4805 DEBUG(3,("call_trans2qfilepathinfo: "
4806 "SMB_VFS_LSTAT of %s failed "
4808 smb_fname_str_dbg(smb_fname),
4811 map_nt_error_from_unix(errno));
4814 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4815 DEBUG(3,("call_trans2qfilepathinfo: "
4816 "SMB_VFS_STAT of %s failed (%s)\n",
4817 smb_fname_str_dbg(smb_fname),
4820 map_nt_error_from_unix(errno));
4824 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4825 get_file_infos(fileid, &delete_pending, &write_time_ts);
4828 * Original code - this is an open file.
4830 if (!check_fsp(conn, req, fsp)) {
4834 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4835 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4836 fsp->fnum, strerror(errno)));
4838 map_nt_error_from_unix(errno));
4841 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4842 get_file_infos(fileid, &delete_pending, &write_time_ts);
4847 if (total_params < 7) {
4848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4852 info_level = SVAL(params,0);
4854 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4856 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4857 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4861 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4863 STR_TERMINATE, &status);
4864 if (!NT_STATUS_IS_OK(status)) {
4865 reply_nterror(req, status);
4869 status = filename_convert(req,
4871 req->flags2 & FLAGS2_DFS_PATHNAMES,
4875 if (!NT_STATUS_IS_OK(status)) {
4876 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4877 reply_botherror(req,
4878 NT_STATUS_PATH_NOT_COVERED,
4879 ERRSRV, ERRbadpath);
4882 reply_nterror(req, status);
4886 /* If this is a stream, check if there is a delete_pending. */
4887 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4888 && is_ntfs_stream_smb_fname(smb_fname)) {
4889 struct smb_filename *smb_fname_base = NULL;
4891 /* Create an smb_filename with stream_name == NULL. */
4893 create_synthetic_smb_fname(talloc_tos(),
4894 smb_fname->base_name,
4897 if (!NT_STATUS_IS_OK(status)) {
4898 reply_nterror(req, status);
4902 if (INFO_LEVEL_IS_UNIX(info_level)) {
4903 /* Always do lstat for UNIX calls. */
4904 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4905 DEBUG(3,("call_trans2qfilepathinfo: "
4906 "SMB_VFS_LSTAT of %s failed "
4908 smb_fname_str_dbg(smb_fname_base),
4910 TALLOC_FREE(smb_fname_base);
4912 map_nt_error_from_unix(errno));
4916 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4917 DEBUG(3,("call_trans2qfilepathinfo: "
4918 "fileinfo of %s failed "
4920 smb_fname_str_dbg(smb_fname_base),
4922 TALLOC_FREE(smb_fname_base);
4924 map_nt_error_from_unix(errno));
4929 fileid = vfs_file_id_from_sbuf(conn,
4930 &smb_fname_base->st);
4931 TALLOC_FREE(smb_fname_base);
4932 get_file_infos(fileid, &delete_pending, NULL);
4933 if (delete_pending) {
4934 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4939 if (INFO_LEVEL_IS_UNIX(info_level)) {
4940 /* Always do lstat for UNIX calls. */
4941 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4942 DEBUG(3,("call_trans2qfilepathinfo: "
4943 "SMB_VFS_LSTAT of %s failed (%s)\n",
4944 smb_fname_str_dbg(smb_fname),
4947 map_nt_error_from_unix(errno));
4951 } else if (!VALID_STAT(smb_fname->st) &&
4952 SMB_VFS_STAT(conn, smb_fname) &&
4953 (info_level != SMB_INFO_IS_NAME_VALID)) {
4954 ms_dfs_link = check_msdfs_link(conn, fname,
4958 DEBUG(3,("call_trans2qfilepathinfo: "
4959 "SMB_VFS_STAT of %s failed (%s)\n",
4960 smb_fname_str_dbg(smb_fname),
4963 map_nt_error_from_unix(errno));
4968 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4969 get_file_infos(fileid, &delete_pending, &write_time_ts);
4970 if (delete_pending) {
4971 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4976 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4977 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4979 /* Pull out any data sent here before we realloc. */
4980 switch (info_level) {
4981 case SMB_INFO_QUERY_EAS_FROM_LIST:
4983 /* Pull any EA list from the data portion. */
4986 if (total_data < 4) {
4988 req, NT_STATUS_INVALID_PARAMETER);
4991 ea_size = IVAL(pdata,0);
4993 if (total_data > 0 && ea_size != total_data) {
4994 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4995 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4997 req, NT_STATUS_INVALID_PARAMETER);
5001 if (!lp_ea_support(SNUM(conn))) {
5002 reply_doserror(req, ERRDOS,
5003 ERReasnotsupported);
5007 /* Pull out the list of names. */
5008 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5011 req, NT_STATUS_INVALID_PARAMETER);
5017 case SMB_QUERY_POSIX_LOCK:
5019 if (fsp == NULL || fsp->fh->fd == -1) {
5020 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5024 if (total_data != POSIX_LOCK_DATA_SIZE) {
5026 req, NT_STATUS_INVALID_PARAMETER);
5030 /* Copy the lock range data. */
5031 lock_data = (char *)TALLOC_MEMDUP(
5032 req, pdata, total_data);
5034 reply_nterror(req, NT_STATUS_NO_MEMORY);
5037 lock_data_count = total_data;
5043 *pparams = (char *)SMB_REALLOC(*pparams,2);
5044 if (*pparams == NULL) {
5045 reply_nterror(req, NT_STATUS_NO_MEMORY);
5052 * draft-leach-cifs-v1-spec-02.txt
5053 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5056 * The requested information is placed in the Data portion of the
5057 * transaction response. For the information levels greater than 0x100,
5058 * the transaction response has 1 parameter word which should be
5059 * ignored by the client.
5061 * However Windows only follows this rule for the IS_NAME_VALID call.
5063 switch (info_level) {
5064 case SMB_INFO_IS_NAME_VALID:
5069 if ((info_level & 0xFF00) == 0xFF00) {
5071 * We use levels that start with 0xFF00
5072 * internally to represent SMB2 specific levels
5074 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5078 status = smbd_do_qfilepathinfo(conn, req, info_level,
5080 delete_pending, write_time_ts,
5081 ms_dfs_link, ea_list,
5082 lock_data_count, lock_data,
5083 req->flags2, max_data_bytes,
5084 ppdata, &data_size);
5085 if (!NT_STATUS_IS_OK(status)) {
5086 reply_nterror(req, status);
5090 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5096 /****************************************************************************
5097 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5099 ****************************************************************************/
5101 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5102 connection_struct *conn,
5103 const struct smb_filename *smb_fname_old,
5104 const struct smb_filename *smb_fname_new)
5106 char *oldname = NULL;
5107 char *newname = NULL;
5108 NTSTATUS status = NT_STATUS_OK;
5110 /* source must already exist. */
5111 if (!VALID_STAT(smb_fname_old->st)) {
5112 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5115 /* Disallow if newname already exists. */
5116 if (VALID_STAT(smb_fname_new->st)) {
5117 return NT_STATUS_OBJECT_NAME_COLLISION;
5120 /* No links from a directory. */
5121 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5122 return NT_STATUS_FILE_IS_A_DIRECTORY;
5125 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
5126 if (!NT_STATUS_IS_OK(status)) {
5129 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
5130 if (!NT_STATUS_IS_OK(status)) {
5134 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
5136 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
5137 status = map_nt_error_from_unix(errno);
5138 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5139 nt_errstr(status), newname, oldname));
5142 TALLOC_FREE(newname);
5143 TALLOC_FREE(oldname);
5147 /****************************************************************************
5148 Deal with setting the time from any of the setfilepathinfo functions.
5149 ****************************************************************************/
5151 NTSTATUS smb_set_file_time(connection_struct *conn,
5153 const struct smb_filename *smb_fname,
5154 struct smb_file_time *ft,
5155 bool setting_write_time)
5157 struct smb_filename *smb_fname_base = NULL;
5159 FILE_NOTIFY_CHANGE_LAST_ACCESS
5160 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5163 if (!VALID_STAT(smb_fname->st)) {
5164 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5167 /* get some defaults (no modifications) if any info is zero or -1. */
5168 if (null_timespec(ft->atime)) {
5169 ft->atime= smb_fname->st.st_ex_atime;
5170 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5173 if (null_timespec(ft->mtime)) {
5174 ft->mtime = smb_fname->st.st_ex_mtime;
5175 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5178 if (!setting_write_time) {
5179 /* ft->mtime comes from change time, not write time. */
5180 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5183 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5184 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5185 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5186 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5187 if (!null_timespec(ft->create_time)) {
5188 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5189 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5193 * Try and set the times of this file if
5194 * they are different from the current values.
5198 struct timespec mts = smb_fname->st.st_ex_mtime;
5199 struct timespec ats = smb_fname->st.st_ex_atime;
5200 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5201 (timespec_compare(&ft->mtime, &mts) == 0)) {
5202 return NT_STATUS_OK;
5206 if (setting_write_time) {
5208 * This was a Windows setfileinfo on an open file.
5209 * NT does this a lot. We also need to
5210 * set the time here, as it can be read by
5211 * FindFirst/FindNext and with the patch for bug #2045
5212 * in smbd/fileio.c it ensures that this timestamp is
5213 * kept sticky even after a write. We save the request
5214 * away and will set it on file close and after a write. JRA.
5217 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5218 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5221 if (fsp->base_fsp) {
5222 set_sticky_write_time_fsp(fsp->base_fsp,
5225 set_sticky_write_time_fsp(fsp, ft->mtime);
5228 set_sticky_write_time_path(
5229 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5234 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5236 /* Always call ntimes on the base, even if a stream was passed in. */
5237 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5238 NULL, &smb_fname->st,
5240 if (!NT_STATUS_IS_OK(status)) {
5244 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5245 TALLOC_FREE(smb_fname_base);
5246 return map_nt_error_from_unix(errno);
5248 TALLOC_FREE(smb_fname_base);
5250 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5251 smb_fname->base_name);
5252 return NT_STATUS_OK;
5255 /****************************************************************************
5256 Deal with setting the dosmode from any of the setfilepathinfo functions.
5257 ****************************************************************************/
5259 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5260 const struct smb_filename *smb_fname,
5263 struct smb_filename *smb_fname_base = NULL;
5266 if (!VALID_STAT(smb_fname->st)) {
5267 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5270 /* Always operate on the base_name, even if a stream was passed in. */
5271 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5272 NULL, &smb_fname->st,
5274 if (!NT_STATUS_IS_OK(status)) {
5279 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5286 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5288 /* check the mode isn't different, before changing it */
5289 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5290 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5291 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5292 (unsigned int)dosmode));
5294 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5296 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5298 smb_fname_str_dbg(smb_fname_base),
5300 status = map_nt_error_from_unix(errno);
5304 status = NT_STATUS_OK;
5306 TALLOC_FREE(smb_fname_base);
5310 /****************************************************************************
5311 Deal with setting the size from any of the setfilepathinfo functions.
5312 ****************************************************************************/
5314 static NTSTATUS smb_set_file_size(connection_struct *conn,
5315 struct smb_request *req,
5317 const struct smb_filename *smb_fname,
5318 const SMB_STRUCT_STAT *psbuf,
5321 NTSTATUS status = NT_STATUS_OK;
5322 struct smb_filename *smb_fname_tmp = NULL;
5323 files_struct *new_fsp = NULL;
5325 if (!VALID_STAT(*psbuf)) {
5326 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5329 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5331 if (size == get_file_size_stat(psbuf)) {
5332 return NT_STATUS_OK;
5335 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5336 smb_fname_str_dbg(smb_fname), (double)size));
5338 if (fsp && fsp->fh->fd != -1) {
5339 /* Handle based call. */
5340 if (vfs_set_filelen(fsp, size) == -1) {
5341 return map_nt_error_from_unix(errno);
5343 trigger_write_time_update_immediate(fsp);
5344 return NT_STATUS_OK;
5347 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5348 if (!NT_STATUS_IS_OK(status)) {
5352 smb_fname_tmp->st = *psbuf;
5354 status = SMB_VFS_CREATE_FILE(
5357 0, /* root_dir_fid */
5358 smb_fname_tmp, /* fname */
5359 FILE_WRITE_ATTRIBUTES, /* access_mask */
5360 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5362 FILE_OPEN, /* create_disposition*/
5363 0, /* create_options */
5364 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5365 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5366 0, /* allocation_size */
5369 &new_fsp, /* result */
5372 TALLOC_FREE(smb_fname_tmp);
5374 if (!NT_STATUS_IS_OK(status)) {
5375 /* NB. We check for open_was_deferred in the caller. */
5379 if (vfs_set_filelen(new_fsp, size) == -1) {
5380 status = map_nt_error_from_unix(errno);
5381 close_file(req, new_fsp,NORMAL_CLOSE);
5385 trigger_write_time_update_immediate(new_fsp);
5386 close_file(req, new_fsp,NORMAL_CLOSE);
5387 return NT_STATUS_OK;
5390 /****************************************************************************
5391 Deal with SMB_INFO_SET_EA.
5392 ****************************************************************************/
5394 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5398 const struct smb_filename *smb_fname)
5400 struct ea_list *ea_list = NULL;
5401 TALLOC_CTX *ctx = NULL;
5402 NTSTATUS status = NT_STATUS_OK;
5404 if (total_data < 10) {
5406 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5407 length. They seem to have no effect. Bug #3212. JRA */
5409 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5410 /* We're done. We only get EA info in this call. */
5411 return NT_STATUS_OK;
5414 return NT_STATUS_INVALID_PARAMETER;
5417 if (IVAL(pdata,0) > total_data) {
5418 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5419 IVAL(pdata,0), (unsigned int)total_data));
5420 return NT_STATUS_INVALID_PARAMETER;
5424 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5426 return NT_STATUS_INVALID_PARAMETER;
5428 status = set_ea(conn, fsp, smb_fname, ea_list);
5433 /****************************************************************************
5434 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5435 ****************************************************************************/
5437 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5441 const struct smb_filename *smb_fname)
5443 NTSTATUS status = NT_STATUS_OK;
5444 bool delete_on_close;
5447 if (total_data < 1) {
5448 return NT_STATUS_INVALID_PARAMETER;
5452 return NT_STATUS_INVALID_HANDLE;
5455 delete_on_close = (CVAL(pdata,0) ? True : False);
5456 dosmode = dos_mode(conn, smb_fname);
5458 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5459 "delete_on_close = %u\n",
5460 smb_fname_str_dbg(smb_fname),
5461 (unsigned int)dosmode,
5462 (unsigned int)delete_on_close ));
5464 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5466 if (!NT_STATUS_IS_OK(status)) {
5470 /* The set is across all open files on this dev/inode pair. */
5471 if (!set_delete_on_close(fsp, delete_on_close,
5472 &conn->server_info->utok)) {
5473 return NT_STATUS_ACCESS_DENIED;
5475 return NT_STATUS_OK;
5478 /****************************************************************************
5479 Deal with SMB_FILE_POSITION_INFORMATION.
5480 ****************************************************************************/
5482 static NTSTATUS smb_file_position_information(connection_struct *conn,
5487 uint64_t position_information;
5489 if (total_data < 8) {
5490 return NT_STATUS_INVALID_PARAMETER;
5494 /* Ignore on pathname based set. */
5495 return NT_STATUS_OK;
5498 position_information = (uint64_t)IVAL(pdata,0);
5499 #ifdef LARGE_SMB_OFF_T
5500 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5501 #else /* LARGE_SMB_OFF_T */
5502 if (IVAL(pdata,4) != 0) {
5503 /* more than 32 bits? */
5504 return NT_STATUS_INVALID_PARAMETER;
5506 #endif /* LARGE_SMB_OFF_T */
5508 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5509 fsp->fsp_name, (double)position_information ));
5510 fsp->fh->position_information = position_information;
5511 return NT_STATUS_OK;
5514 /****************************************************************************
5515 Deal with SMB_FILE_MODE_INFORMATION.
5516 ****************************************************************************/
5518 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5524 if (total_data < 4) {
5525 return NT_STATUS_INVALID_PARAMETER;
5527 mode = IVAL(pdata,0);
5528 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5529 return NT_STATUS_INVALID_PARAMETER;
5531 return NT_STATUS_OK;
5534 /****************************************************************************
5535 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5536 ****************************************************************************/
5538 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5539 struct smb_request *req,
5544 char *link_target = NULL;
5545 const char *newname = fname;
5546 NTSTATUS status = NT_STATUS_OK;
5547 TALLOC_CTX *ctx = talloc_tos();
5549 /* Set a symbolic link. */
5550 /* Don't allow this if follow links is false. */
5552 if (total_data == 0) {
5553 return NT_STATUS_INVALID_PARAMETER;
5556 if (!lp_symlinks(SNUM(conn))) {
5557 return NT_STATUS_ACCESS_DENIED;
5560 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5561 total_data, STR_TERMINATE);
5564 return NT_STATUS_INVALID_PARAMETER;
5567 /* !widelinks forces the target path to be within the share. */
5568 /* This means we can interpret the target as a pathname. */
5569 if (!lp_widelinks(SNUM(conn))) {
5570 char *rel_name = NULL;
5571 char *last_dirp = NULL;
5573 if (*link_target == '/') {
5574 /* No absolute paths allowed. */
5575 return NT_STATUS_ACCESS_DENIED;
5577 rel_name = talloc_strdup(ctx,newname);
5579 return NT_STATUS_NO_MEMORY;
5581 last_dirp = strrchr_m(rel_name, '/');
5583 last_dirp[1] = '\0';
5585 rel_name = talloc_strdup(ctx,"./");
5587 return NT_STATUS_NO_MEMORY;
5590 rel_name = talloc_asprintf_append(rel_name,
5594 return NT_STATUS_NO_MEMORY;
5597 status = check_name(conn, rel_name);
5598 if (!NT_STATUS_IS_OK(status)) {
5603 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5604 newname, link_target ));
5606 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5607 return map_nt_error_from_unix(errno);
5610 return NT_STATUS_OK;
5613 /****************************************************************************
5614 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5615 ****************************************************************************/
5617 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5618 struct smb_request *req,
5619 const char *pdata, int total_data,
5620 const struct smb_filename *smb_fname_new)
5622 char *oldname = NULL;
5623 struct smb_filename *smb_fname_old = NULL;
5624 TALLOC_CTX *ctx = talloc_tos();
5625 NTSTATUS status = NT_STATUS_OK;
5627 /* Set a hard link. */
5628 if (total_data == 0) {
5629 return NT_STATUS_INVALID_PARAMETER;
5632 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5633 total_data, STR_TERMINATE, &status);
5634 if (!NT_STATUS_IS_OK(status)) {
5638 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5639 smb_fname_str_dbg(smb_fname_new), oldname));
5641 status = filename_convert(ctx,
5643 req->flags2 & FLAGS2_DFS_PATHNAMES,
5647 if (!NT_STATUS_IS_OK(status)) {
5651 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5654 /****************************************************************************
5655 Deal with SMB_FILE_RENAME_INFORMATION.
5656 ****************************************************************************/
5658 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5659 struct smb_request *req,
5668 char *newname = NULL;
5669 char *base_name = NULL;
5670 struct smb_filename *smb_fname = NULL;
5671 bool dest_has_wcard = False;
5672 NTSTATUS status = NT_STATUS_OK;
5674 TALLOC_CTX *ctx = talloc_tos();
5676 if (total_data < 13) {
5677 return NT_STATUS_INVALID_PARAMETER;
5680 overwrite = (CVAL(pdata,0) ? True : False);
5681 root_fid = IVAL(pdata,4);
5682 len = IVAL(pdata,8);
5684 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5685 return NT_STATUS_INVALID_PARAMETER;
5688 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5691 if (!NT_STATUS_IS_OK(status)) {
5695 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5698 status = resolve_dfspath_wcard(ctx, conn,
5699 req->flags2 & FLAGS2_DFS_PATHNAMES,
5703 if (!NT_STATUS_IS_OK(status)) {
5707 /* Check the new name has no '/' characters. */
5708 if (strchr_m(newname, '/')) {
5709 return NT_STATUS_NOT_SUPPORTED;
5712 if (fsp && fsp->base_fsp) {
5713 /* newname must be a stream name. */
5714 if (newname[0] != ':') {
5715 return NT_STATUS_NOT_SUPPORTED;
5718 /* Create an smb_fname to call rename_internals_fsp() with. */
5719 status = create_synthetic_smb_fname(talloc_tos(),
5720 fsp->base_fsp->fsp_name,
5721 newname, NULL, &smb_fname);
5722 if (!NT_STATUS_IS_OK(status)) {
5727 * Set the original last component, since
5728 * rename_internals_fsp() requires it.
5730 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5731 if (smb_fname->original_lcomp == NULL) {
5732 status = NT_STATUS_NO_MEMORY;
5736 /* Create a char * to call rename_internals() with. */
5737 base_name = talloc_asprintf(ctx, "%s%s",
5738 fsp->base_fsp->fsp_name,
5741 status = NT_STATUS_NO_MEMORY;
5745 /* newname must *not* be a stream name. */
5746 if (newname[0] == ':') {
5747 return NT_STATUS_NOT_SUPPORTED;
5750 /* Create the base directory. */
5751 base_name = talloc_strdup(ctx, fname);
5753 return NT_STATUS_NO_MEMORY;
5755 p = strrchr_m(base_name, '/');
5759 base_name = talloc_strdup(ctx, "./");
5761 return NT_STATUS_NO_MEMORY;
5764 /* Append the new name. */
5765 base_name = talloc_asprintf_append(base_name,
5769 return NT_STATUS_NO_MEMORY;
5772 status = unix_convert(ctx, conn, base_name, &smb_fname,
5775 /* If an error we expect this to be
5776 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5778 if (!NT_STATUS_IS_OK(status)) {
5779 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5783 /* Create an smb_fname to call rename_internals_fsp() */
5784 status = create_synthetic_smb_fname(talloc_tos(),
5787 if (!NT_STATUS_IS_OK(status)) {
5795 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5796 fsp->fnum, fsp->fsp_name, base_name ));
5797 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5800 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5801 fname, base_name ));
5802 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5803 overwrite, False, dest_has_wcard,
5804 FILE_WRITE_ATTRIBUTES);
5807 TALLOC_FREE(smb_fname);
5811 /****************************************************************************
5812 Deal with SMB_SET_POSIX_ACL.
5813 ****************************************************************************/
5815 #if defined(HAVE_POSIX_ACLS)
5816 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5821 SMB_STRUCT_STAT *psbuf)
5823 uint16 posix_acl_version;
5824 uint16 num_file_acls;
5825 uint16 num_def_acls;
5826 bool valid_file_acls = True;
5827 bool valid_def_acls = True;
5829 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5830 return NT_STATUS_INVALID_PARAMETER;
5832 posix_acl_version = SVAL(pdata,0);
5833 num_file_acls = SVAL(pdata,2);
5834 num_def_acls = SVAL(pdata,4);
5836 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5837 valid_file_acls = False;
5841 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5842 valid_def_acls = False;
5846 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5847 return NT_STATUS_INVALID_PARAMETER;
5850 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5851 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5852 return NT_STATUS_INVALID_PARAMETER;
5855 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5856 fname ? fname : fsp->fsp_name,
5857 (unsigned int)num_file_acls,
5858 (unsigned int)num_def_acls));
5860 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5861 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5862 return map_nt_error_from_unix(errno);
5865 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5866 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5867 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5868 return map_nt_error_from_unix(errno);
5870 return NT_STATUS_OK;
5874 /****************************************************************************
5875 Deal with SMB_SET_POSIX_LOCK.
5876 ****************************************************************************/
5878 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5879 struct smb_request *req,
5887 bool blocking_lock = False;
5888 enum brl_type lock_type;
5890 NTSTATUS status = NT_STATUS_OK;
5892 if (fsp == NULL || fsp->fh->fd == -1) {
5893 return NT_STATUS_INVALID_HANDLE;
5896 if (total_data != POSIX_LOCK_DATA_SIZE) {
5897 return NT_STATUS_INVALID_PARAMETER;
5900 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5901 case POSIX_LOCK_TYPE_READ:
5902 lock_type = READ_LOCK;
5904 case POSIX_LOCK_TYPE_WRITE:
5905 /* Return the right POSIX-mappable error code for files opened read-only. */
5906 if (!fsp->can_write) {
5907 return NT_STATUS_INVALID_HANDLE;
5909 lock_type = WRITE_LOCK;
5911 case POSIX_LOCK_TYPE_UNLOCK:
5912 lock_type = UNLOCK_LOCK;
5915 return NT_STATUS_INVALID_PARAMETER;
5918 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5919 blocking_lock = False;
5920 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5921 blocking_lock = True;
5923 return NT_STATUS_INVALID_PARAMETER;
5926 if (!lp_blocking_locks(SNUM(conn))) {
5927 blocking_lock = False;
5930 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5931 #if defined(HAVE_LONGLONG)
5932 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5933 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5934 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5935 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5936 #else /* HAVE_LONGLONG */
5937 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5938 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5939 #endif /* HAVE_LONGLONG */
5941 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5942 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5944 (unsigned int)lock_type,
5945 (unsigned int)lock_pid,
5949 if (lock_type == UNLOCK_LOCK) {
5950 status = do_unlock(smbd_messaging_context(),
5957 uint32 block_smbpid;
5959 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5971 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5973 * A blocking lock was requested. Package up
5974 * this smb into a queued request and push it
5975 * onto the blocking lock queue.
5977 if(push_blocking_lock_request(br_lck,
5980 -1, /* infinite timeout. */
5988 TALLOC_FREE(br_lck);
5992 TALLOC_FREE(br_lck);
5998 /****************************************************************************
5999 Deal with SMB_INFO_STANDARD.
6000 ****************************************************************************/
6002 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6006 const struct smb_filename *smb_fname)
6008 struct smb_file_time ft;
6011 if (total_data < 12) {
6012 return NT_STATUS_INVALID_PARAMETER;
6016 ft.create_time = interpret_long_date(pdata);
6019 ft.atime = interpret_long_date(pdata + 8);
6022 ft.mtime = interpret_long_date(pdata + 16);
6024 DEBUG(10,("smb_set_info_standard: file %s\n",
6025 smb_fname_str_dbg(smb_fname)));
6027 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
6030 /****************************************************************************
6031 Deal with SMB_SET_FILE_BASIC_INFO.
6032 ****************************************************************************/
6034 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6038 const struct smb_filename *smb_fname)
6040 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6041 struct timespec write_time;
6042 struct timespec changed_time;
6043 struct smb_file_time ft;
6045 NTSTATUS status = NT_STATUS_OK;
6046 bool setting_write_time = true;
6050 if (total_data < 36) {
6051 return NT_STATUS_INVALID_PARAMETER;
6054 /* Set the attributes */
6055 dosmode = IVAL(pdata,32);
6056 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6057 if (!NT_STATUS_IS_OK(status)) {
6062 ft.atime = interpret_long_date(pdata+8);
6064 write_time = interpret_long_date(pdata+16);
6065 changed_time = interpret_long_date(pdata+24);
6068 ft.mtime = timespec_min(&write_time, &changed_time);
6071 ft.create_time = interpret_long_date(pdata);
6073 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
6074 !null_timespec(write_time)) {
6075 ft.mtime = write_time;
6078 /* Prefer a defined time to an undefined one. */
6079 if (null_timespec(ft.mtime)) {
6080 if (null_timespec(write_time)) {
6081 ft.mtime = changed_time;
6082 setting_write_time = false;
6084 ft.mtime = write_time;
6088 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6089 smb_fname_str_dbg(smb_fname)));
6091 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6092 setting_write_time);
6095 /****************************************************************************
6096 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6097 ****************************************************************************/
6099 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6100 struct smb_request *req,
6104 struct smb_filename *smb_fname)
6106 uint64_t allocation_size = 0;
6107 NTSTATUS status = NT_STATUS_OK;
6108 files_struct *new_fsp = NULL;
6110 if (!VALID_STAT(smb_fname->st)) {
6111 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6114 if (total_data < 8) {
6115 return NT_STATUS_INVALID_PARAMETER;
6118 allocation_size = (uint64_t)IVAL(pdata,0);
6119 #ifdef LARGE_SMB_OFF_T
6120 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6121 #else /* LARGE_SMB_OFF_T */
6122 if (IVAL(pdata,4) != 0) {
6123 /* more than 32 bits? */
6124 return NT_STATUS_INVALID_PARAMETER;
6126 #endif /* LARGE_SMB_OFF_T */
6128 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6129 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6130 (double)allocation_size));
6132 if (allocation_size) {
6133 allocation_size = smb_roundup(conn, allocation_size);
6136 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6137 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6138 (double)allocation_size));
6140 if (fsp && fsp->fh->fd != -1) {
6141 /* Open file handle. */
6142 /* Only change if needed. */
6143 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6144 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6145 return map_nt_error_from_unix(errno);
6148 /* But always update the time. */
6150 * This is equivalent to a write. Ensure it's seen immediately
6151 * if there are no pending writes.
6153 trigger_write_time_update_immediate(fsp);
6154 return NT_STATUS_OK;
6157 /* Pathname or stat or directory file. */
6158 status = SMB_VFS_CREATE_FILE(
6161 0, /* root_dir_fid */
6162 smb_fname, /* fname */
6163 FILE_WRITE_DATA, /* access_mask */
6164 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6166 FILE_OPEN, /* create_disposition*/
6167 0, /* create_options */
6168 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6169 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6170 0, /* allocation_size */
6173 &new_fsp, /* result */
6176 if (!NT_STATUS_IS_OK(status)) {
6177 /* NB. We check for open_was_deferred in the caller. */
6181 /* Only change if needed. */
6182 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6183 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6184 status = map_nt_error_from_unix(errno);
6185 close_file(req, new_fsp, NORMAL_CLOSE);
6190 /* Changing the allocation size should set the last mod time. */
6192 * This is equivalent to a write. Ensure it's seen immediately
6193 * if there are no pending writes.
6195 trigger_write_time_update_immediate(new_fsp);
6197 close_file(req, new_fsp, NORMAL_CLOSE);
6198 return NT_STATUS_OK;
6201 /****************************************************************************
6202 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6203 ****************************************************************************/
6205 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6206 struct smb_request *req,
6210 const struct smb_filename *smb_fname)
6214 if (total_data < 8) {
6215 return NT_STATUS_INVALID_PARAMETER;
6218 size = IVAL(pdata,0);
6219 #ifdef LARGE_SMB_OFF_T
6220 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6221 #else /* LARGE_SMB_OFF_T */
6222 if (IVAL(pdata,4) != 0) {
6223 /* more than 32 bits? */
6224 return NT_STATUS_INVALID_PARAMETER;
6226 #endif /* LARGE_SMB_OFF_T */
6227 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6228 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6231 return smb_set_file_size(conn, req,
6238 /****************************************************************************
6239 Allow a UNIX info mknod.
6240 ****************************************************************************/
6242 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6245 const struct smb_filename *smb_fname)
6247 uint32 file_type = IVAL(pdata,56);
6248 #if defined(HAVE_MAKEDEV)
6249 uint32 dev_major = IVAL(pdata,60);
6250 uint32 dev_minor = IVAL(pdata,68);
6252 SMB_DEV_T dev = (SMB_DEV_T)0;
6253 uint32 raw_unixmode = IVAL(pdata,84);
6257 if (total_data < 100) {
6258 return NT_STATUS_INVALID_PARAMETER;
6261 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6262 PERM_NEW_FILE, &unixmode);
6263 if (!NT_STATUS_IS_OK(status)) {
6267 #if defined(HAVE_MAKEDEV)
6268 dev = makedev(dev_major, dev_minor);
6271 switch (file_type) {
6272 #if defined(S_IFIFO)
6273 case UNIX_TYPE_FIFO:
6274 unixmode |= S_IFIFO;
6277 #if defined(S_IFSOCK)
6278 case UNIX_TYPE_SOCKET:
6279 unixmode |= S_IFSOCK;
6282 #if defined(S_IFCHR)
6283 case UNIX_TYPE_CHARDEV:
6284 unixmode |= S_IFCHR;
6287 #if defined(S_IFBLK)
6288 case UNIX_TYPE_BLKDEV:
6289 unixmode |= S_IFBLK;
6293 return NT_STATUS_INVALID_PARAMETER;
6296 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6297 "%.0f mode 0%o for file %s\n", (double)dev,
6298 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6300 /* Ok - do the mknod. */
6301 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6302 return map_nt_error_from_unix(errno);
6305 /* If any of the other "set" calls fail we
6306 * don't want to end up with a half-constructed mknod.
6309 if (lp_inherit_perms(SNUM(conn))) {
6311 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6313 return NT_STATUS_NO_MEMORY;
6315 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6317 TALLOC_FREE(parent);
6320 return NT_STATUS_OK;
6323 /****************************************************************************
6324 Deal with SMB_SET_FILE_UNIX_BASIC.
6325 ****************************************************************************/
6327 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6328 struct smb_request *req,
6332 const struct smb_filename *smb_fname)
6334 struct smb_file_time ft;
6335 uint32 raw_unixmode;
6338 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6339 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6340 NTSTATUS status = NT_STATUS_OK;
6341 bool delete_on_fail = False;
6342 enum perm_type ptype;
6343 files_struct *all_fsps = NULL;
6344 bool modify_mtime = true;
6346 SMB_STRUCT_STAT sbuf;
6350 if (total_data < 100) {
6351 return NT_STATUS_INVALID_PARAMETER;
6354 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6355 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6356 size=IVAL(pdata,0); /* first 8 Bytes are size */
6357 #ifdef LARGE_SMB_OFF_T
6358 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6359 #else /* LARGE_SMB_OFF_T */
6360 if (IVAL(pdata,4) != 0) {
6361 /* more than 32 bits? */
6362 return NT_STATUS_INVALID_PARAMETER;
6364 #endif /* LARGE_SMB_OFF_T */
6367 ft.atime = interpret_long_date(pdata+24); /* access_time */
6368 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6369 set_owner = (uid_t)IVAL(pdata,40);
6370 set_grp = (gid_t)IVAL(pdata,48);
6371 raw_unixmode = IVAL(pdata,84);
6373 if (VALID_STAT(smb_fname->st)) {
6374 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6375 ptype = PERM_EXISTING_DIR;
6377 ptype = PERM_EXISTING_FILE;
6380 ptype = PERM_NEW_FILE;
6383 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6385 if (!NT_STATUS_IS_OK(status)) {
6389 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6390 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6391 smb_fname_str_dbg(smb_fname), (double)size,
6392 (unsigned int)set_owner, (unsigned int)set_grp,
6393 (int)raw_unixmode));
6395 sbuf = smb_fname->st;
6397 if (!VALID_STAT(sbuf)) {
6398 struct smb_filename *smb_fname_tmp = NULL;
6400 * The only valid use of this is to create character and block
6401 * devices, and named pipes. This is deprecated (IMHO) and
6402 * a new info level should be used for mknod. JRA.
6405 status = smb_unix_mknod(conn,
6409 if (!NT_STATUS_IS_OK(status)) {
6413 status = copy_smb_filename(talloc_tos(), smb_fname,
6415 if (!NT_STATUS_IS_OK(status)) {
6419 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6420 status = map_nt_error_from_unix(errno);
6421 TALLOC_FREE(smb_fname_tmp);
6422 SMB_VFS_UNLINK(conn, smb_fname);
6426 sbuf = smb_fname_tmp->st;
6427 TALLOC_FREE(smb_fname_tmp);
6429 /* Ensure we don't try and change anything else. */
6430 raw_unixmode = SMB_MODE_NO_CHANGE;
6431 size = get_file_size_stat(&sbuf);
6432 ft.atime = sbuf.st_ex_atime;
6433 ft.mtime = sbuf.st_ex_mtime;
6435 * We continue here as we might want to change the
6438 delete_on_fail = True;
6442 /* Horrible backwards compatibility hack as an old server bug
6443 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6447 size = get_file_size_stat(&sbuf);
6452 * Deal with the UNIX specific mode set.
6455 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6456 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6457 "setting mode 0%o for file %s\n",
6458 (unsigned int)unixmode,
6459 smb_fname_str_dbg(smb_fname)));
6460 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6461 return map_nt_error_from_unix(errno);
6466 * Deal with the UNIX specific uid set.
6469 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6470 (sbuf.st_ex_uid != set_owner)) {
6473 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6474 "changing owner %u for path %s\n",
6475 (unsigned int)set_owner,
6476 smb_fname_str_dbg(smb_fname)));
6478 if (S_ISLNK(sbuf.st_ex_mode)) {
6479 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6480 set_owner, (gid_t)-1);
6482 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6483 set_owner, (gid_t)-1);
6487 status = map_nt_error_from_unix(errno);
6488 if (delete_on_fail) {
6489 SMB_VFS_UNLINK(conn, smb_fname);
6496 * Deal with the UNIX specific gid set.
6499 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6500 (sbuf.st_ex_gid != set_grp)) {
6501 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6502 "changing group %u for file %s\n",
6503 (unsigned int)set_owner,
6504 smb_fname_str_dbg(smb_fname)));
6505 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6507 status = map_nt_error_from_unix(errno);
6508 if (delete_on_fail) {
6509 SMB_VFS_UNLINK(conn, smb_fname);
6515 /* Deal with any size changes. */
6517 status = smb_set_file_size(conn, req,
6522 if (!NT_STATUS_IS_OK(status)) {
6526 /* Deal with any time changes. */
6527 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6528 /* No change, don't cancel anything. */
6532 id = vfs_file_id_from_sbuf(conn, &sbuf);
6533 for(all_fsps = file_find_di_first(id); all_fsps;
6534 all_fsps = file_find_di_next(all_fsps)) {
6536 * We're setting the time explicitly for UNIX.
6537 * Cancel any pending changes over all handles.
6539 all_fsps->update_write_time_on_close = false;
6540 TALLOC_FREE(all_fsps->update_write_time_event);
6544 * Override the "setting_write_time"
6545 * parameter here as it almost does what
6546 * we need. Just remember if we modified
6547 * mtime and send the notify ourselves.
6549 if (null_timespec(ft.mtime)) {
6550 modify_mtime = false;
6553 status = smb_set_file_time(conn,
6559 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6560 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6565 /****************************************************************************
6566 Deal with SMB_SET_FILE_UNIX_INFO2.
6567 ****************************************************************************/
6569 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6570 struct smb_request *req,
6574 const struct smb_filename *smb_fname)
6580 if (total_data < 116) {
6581 return NT_STATUS_INVALID_PARAMETER;
6584 /* Start by setting all the fields that are common between UNIX_BASIC
6587 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6589 if (!NT_STATUS_IS_OK(status)) {
6593 smb_fflags = IVAL(pdata, 108);
6594 smb_fmask = IVAL(pdata, 112);
6596 /* NB: We should only attempt to alter the file flags if the client
6597 * sends a non-zero mask.
6599 if (smb_fmask != 0) {
6600 int stat_fflags = 0;
6602 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6603 smb_fmask, &stat_fflags)) {
6604 /* Client asked to alter a flag we don't understand. */
6605 return NT_STATUS_INVALID_PARAMETER;
6608 if (fsp && fsp->fh->fd != -1) {
6609 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6610 return NT_STATUS_NOT_SUPPORTED;
6612 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6613 stat_fflags) != 0) {
6614 return map_nt_error_from_unix(errno);
6619 /* XXX: need to add support for changing the create_time here. You
6620 * can do this for paths on Darwin with setattrlist(2). The right way
6621 * to hook this up is probably by extending the VFS utimes interface.
6624 return NT_STATUS_OK;
6627 /****************************************************************************
6628 Create a directory with POSIX semantics.
6629 ****************************************************************************/
6631 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6632 struct smb_request *req,
6636 SMB_STRUCT_STAT *psbuf,
6637 int *pdata_return_size)
6639 struct smb_filename *smb_fname;
6640 NTSTATUS status = NT_STATUS_OK;
6641 uint32 raw_unixmode = 0;
6642 uint32 mod_unixmode = 0;
6643 mode_t unixmode = (mode_t)0;
6644 files_struct *fsp = NULL;
6645 uint16 info_level_return = 0;
6647 char *pdata = *ppdata;
6649 if (total_data < 18) {
6650 return NT_STATUS_INVALID_PARAMETER;
6653 raw_unixmode = IVAL(pdata,8);
6654 /* Next 4 bytes are not yet defined. */
6656 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6657 if (!NT_STATUS_IS_OK(status)) {
6661 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6663 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6664 fname, (unsigned int)unixmode ));
6666 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6668 if (!NT_STATUS_IS_OK(status)) {
6672 status = SMB_VFS_CREATE_FILE(
6675 0, /* root_dir_fid */
6676 smb_fname, /* fname */
6677 FILE_READ_ATTRIBUTES, /* access_mask */
6678 FILE_SHARE_NONE, /* share_access */
6679 FILE_CREATE, /* create_disposition*/
6680 FILE_DIRECTORY_FILE, /* create_options */
6681 mod_unixmode, /* file_attributes */
6682 0, /* oplock_request */
6683 0, /* allocation_size */
6689 *psbuf = smb_fname->st;
6690 TALLOC_FREE(smb_fname);
6692 if (NT_STATUS_IS_OK(status)) {
6693 close_file(req, fsp, NORMAL_CLOSE);
6696 info_level_return = SVAL(pdata,16);
6698 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6699 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6700 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6701 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6703 *pdata_return_size = 12;
6706 /* Realloc the data size */
6707 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6708 if (*ppdata == NULL) {
6709 *pdata_return_size = 0;
6710 return NT_STATUS_NO_MEMORY;
6714 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6715 SSVAL(pdata,2,0); /* No fnum. */
6716 SIVAL(pdata,4,info); /* Was directory created. */
6718 switch (info_level_return) {
6719 case SMB_QUERY_FILE_UNIX_BASIC:
6720 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6721 SSVAL(pdata,10,0); /* Padding. */
6722 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6724 case SMB_QUERY_FILE_UNIX_INFO2:
6725 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6726 SSVAL(pdata,10,0); /* Padding. */
6727 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6730 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6731 SSVAL(pdata,10,0); /* Padding. */
6738 /****************************************************************************
6739 Open/Create a file with POSIX semantics.
6740 ****************************************************************************/
6742 static NTSTATUS smb_posix_open(connection_struct *conn,
6743 struct smb_request *req,
6747 SMB_STRUCT_STAT *psbuf,
6748 int *pdata_return_size)
6750 struct smb_filename *smb_fname = NULL;
6751 bool extended_oplock_granted = False;
6752 char *pdata = *ppdata;
6754 uint32 wire_open_mode = 0;
6755 uint32 raw_unixmode = 0;
6756 uint32 mod_unixmode = 0;
6757 uint32 create_disp = 0;
6758 uint32 access_mask = 0;
6759 uint32 create_options = 0;
6760 NTSTATUS status = NT_STATUS_OK;
6761 mode_t unixmode = (mode_t)0;
6762 files_struct *fsp = NULL;
6763 int oplock_request = 0;
6765 uint16 info_level_return = 0;
6767 if (total_data < 18) {
6768 return NT_STATUS_INVALID_PARAMETER;
6771 flags = IVAL(pdata,0);
6772 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6773 if (oplock_request) {
6774 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6777 wire_open_mode = IVAL(pdata,4);
6779 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6780 return smb_posix_mkdir(conn, req,
6788 switch (wire_open_mode & SMB_ACCMODE) {
6790 access_mask = FILE_READ_DATA;
6793 access_mask = FILE_WRITE_DATA;
6796 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6799 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6800 (unsigned int)wire_open_mode ));
6801 return NT_STATUS_INVALID_PARAMETER;
6804 wire_open_mode &= ~SMB_ACCMODE;
6806 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6807 create_disp = FILE_CREATE;
6808 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6809 create_disp = FILE_OVERWRITE_IF;
6810 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6811 create_disp = FILE_OPEN_IF;
6812 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6813 create_disp = FILE_OPEN;
6815 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6816 (unsigned int)wire_open_mode ));
6817 return NT_STATUS_INVALID_PARAMETER;
6820 raw_unixmode = IVAL(pdata,8);
6821 /* Next 4 bytes are not yet defined. */
6823 status = unix_perms_from_wire(conn,
6826 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6829 if (!NT_STATUS_IS_OK(status)) {
6833 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6835 if (wire_open_mode & SMB_O_SYNC) {
6836 create_options |= FILE_WRITE_THROUGH;
6838 if (wire_open_mode & SMB_O_APPEND) {
6839 access_mask |= FILE_APPEND_DATA;
6841 if (wire_open_mode & SMB_O_DIRECT) {
6842 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6845 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6847 (unsigned int)wire_open_mode,
6848 (unsigned int)unixmode ));
6850 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6852 if (!NT_STATUS_IS_OK(status)) {
6856 status = SMB_VFS_CREATE_FILE(
6859 0, /* root_dir_fid */
6860 smb_fname, /* fname */
6861 access_mask, /* access_mask */
6862 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6864 create_disp, /* create_disposition*/
6865 FILE_NON_DIRECTORY_FILE, /* create_options */
6866 mod_unixmode, /* file_attributes */
6867 oplock_request, /* oplock_request */
6868 0, /* allocation_size */
6874 *psbuf = smb_fname->st;
6875 TALLOC_FREE(smb_fname);
6877 if (!NT_STATUS_IS_OK(status)) {
6881 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6882 extended_oplock_granted = True;
6885 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6886 extended_oplock_granted = True;
6889 info_level_return = SVAL(pdata,16);
6891 /* Allocate the correct return size. */
6893 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6894 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6895 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6896 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6898 *pdata_return_size = 12;
6901 /* Realloc the data size */
6902 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6903 if (*ppdata == NULL) {
6904 close_file(req, fsp, ERROR_CLOSE);
6905 *pdata_return_size = 0;
6906 return NT_STATUS_NO_MEMORY;
6910 if (extended_oplock_granted) {
6911 if (flags & REQUEST_BATCH_OPLOCK) {
6912 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6914 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6916 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6917 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6919 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6922 SSVAL(pdata,2,fsp->fnum);
6923 SIVAL(pdata,4,info); /* Was file created etc. */
6925 switch (info_level_return) {
6926 case SMB_QUERY_FILE_UNIX_BASIC:
6927 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6928 SSVAL(pdata,10,0); /* padding. */
6929 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6931 case SMB_QUERY_FILE_UNIX_INFO2:
6932 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6933 SSVAL(pdata,10,0); /* padding. */
6934 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6937 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6938 SSVAL(pdata,10,0); /* padding. */
6941 return NT_STATUS_OK;
6944 /****************************************************************************
6945 Delete a file with POSIX semantics.
6946 ****************************************************************************/
6948 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6949 struct smb_request *req,
6952 struct smb_filename *smb_fname)
6954 NTSTATUS status = NT_STATUS_OK;
6955 files_struct *fsp = NULL;
6959 int create_options = 0;
6961 struct share_mode_lock *lck = NULL;
6963 if (total_data < 2) {
6964 return NT_STATUS_INVALID_PARAMETER;
6967 flags = SVAL(pdata,0);
6969 if (!VALID_STAT(smb_fname->st)) {
6970 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6973 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6974 !VALID_STAT_OF_DIR(smb_fname->st)) {
6975 return NT_STATUS_NOT_A_DIRECTORY;
6978 DEBUG(10,("smb_posix_unlink: %s %s\n",
6979 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6980 smb_fname_str_dbg(smb_fname)));
6982 if (VALID_STAT_OF_DIR(smb_fname->st)) {
6983 create_options |= FILE_DIRECTORY_FILE;
6986 status = SMB_VFS_CREATE_FILE(
6989 0, /* root_dir_fid */
6990 smb_fname, /* fname */
6991 DELETE_ACCESS, /* access_mask */
6992 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6994 FILE_OPEN, /* create_disposition*/
6995 create_options, /* create_options */
6996 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6997 0, /* oplock_request */
6998 0, /* allocation_size */
7004 if (!NT_STATUS_IS_OK(status)) {
7009 * Don't lie to client. If we can't really delete due to
7010 * non-POSIX opens return SHARING_VIOLATION.
7013 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7016 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7017 "lock for file %s\n", fsp->fsp_name));
7018 close_file(req, fsp, NORMAL_CLOSE);
7019 return NT_STATUS_INVALID_PARAMETER;
7023 * See if others still have the file open. If this is the case, then
7024 * don't delete. If all opens are POSIX delete we can set the delete
7025 * on close disposition.
7027 for (i=0; i<lck->num_share_modes; i++) {
7028 struct share_mode_entry *e = &lck->share_modes[i];
7029 if (is_valid_share_mode_entry(e)) {
7030 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7033 /* Fail with sharing violation. */
7034 close_file(req, fsp, NORMAL_CLOSE);
7036 return NT_STATUS_SHARING_VIOLATION;
7041 * Set the delete on close.
7043 status = smb_set_file_disposition_info(conn,
7049 if (!NT_STATUS_IS_OK(status)) {
7050 close_file(req, fsp, NORMAL_CLOSE);
7055 return close_file(req, fsp, NORMAL_CLOSE);
7058 static NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7059 struct smb_request *req,
7060 TALLOC_CTX *mem_ctx,
7061 uint16_t info_level,
7063 struct smb_filename *smb_fname,
7064 char **ppdata, int total_data,
7067 char *pdata = *ppdata;
7068 SMB_STRUCT_STAT sbuf;
7070 NTSTATUS status = NT_STATUS_OK;
7071 int data_return_size = 0;
7075 /* Set sbuf for use below. */
7076 sbuf = smb_fname->st;
7078 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7079 return NT_STATUS_INVALID_LEVEL;
7082 if (!CAN_WRITE(conn)) {
7083 /* Allow POSIX opens. The open path will deny
7084 * any non-readonly opens. */
7085 if (info_level != SMB_POSIX_PATH_OPEN) {
7086 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7090 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
7091 if (!NT_STATUS_IS_OK(status)) {
7095 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d totdata=%d\n",
7096 fname, fsp ? fsp->fnum : -1, info_level, total_data));
7098 switch (info_level) {
7100 case SMB_INFO_STANDARD:
7102 status = smb_set_info_standard(conn,
7110 case SMB_INFO_SET_EA:
7112 status = smb_info_set_ea(conn,
7120 case SMB_SET_FILE_BASIC_INFO:
7121 case SMB_FILE_BASIC_INFORMATION:
7123 status = smb_set_file_basic_info(conn,
7131 case SMB_FILE_ALLOCATION_INFORMATION:
7132 case SMB_SET_FILE_ALLOCATION_INFO:
7134 status = smb_set_file_allocation_info(conn, req,
7142 case SMB_FILE_END_OF_FILE_INFORMATION:
7143 case SMB_SET_FILE_END_OF_FILE_INFO:
7145 status = smb_set_file_end_of_file_info(conn, req,
7153 case SMB_FILE_DISPOSITION_INFORMATION:
7154 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7157 /* JRA - We used to just ignore this on a path ?
7158 * Shouldn't this be invalid level on a pathname
7161 if (tran_call != TRANSACT2_SETFILEINFO) {
7162 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7165 status = smb_set_file_disposition_info(conn,
7173 case SMB_FILE_POSITION_INFORMATION:
7175 status = smb_file_position_information(conn,
7182 /* From tridge Samba4 :
7183 * MODE_INFORMATION in setfileinfo (I have no
7184 * idea what "mode information" on a file is - it takes a value of 0,
7185 * 2, 4 or 6. What could it be?).
7188 case SMB_FILE_MODE_INFORMATION:
7190 status = smb_file_mode_information(conn,
7197 * CIFS UNIX extensions.
7200 case SMB_SET_FILE_UNIX_BASIC:
7202 status = smb_set_file_unix_basic(conn, req,
7210 case SMB_SET_FILE_UNIX_INFO2:
7212 status = smb_set_file_unix_info2(conn, req,
7220 case SMB_SET_FILE_UNIX_LINK:
7223 /* We must have a pathname for this. */
7224 return NT_STATUS_INVALID_LEVEL;
7226 status = smb_set_file_unix_link(conn, req, pdata,
7231 case SMB_SET_FILE_UNIX_HLINK:
7233 if (fsp || smb_fname == NULL) {
7234 /* We must have a pathname for this. */
7235 return NT_STATUS_INVALID_LEVEL;
7237 status = smb_set_file_unix_hlink(conn, req,
7243 case SMB_FILE_RENAME_INFORMATION:
7245 status = smb_file_rename_information(conn, req,
7251 #if defined(HAVE_POSIX_ACLS)
7252 case SMB_SET_POSIX_ACL:
7254 status = smb_set_posix_acl(conn,
7264 case SMB_SET_POSIX_LOCK:
7267 return NT_STATUS_INVALID_LEVEL;
7269 status = smb_set_posix_lock(conn, req,
7270 pdata, total_data, fsp);
7274 case SMB_POSIX_PATH_OPEN:
7277 /* We must have a pathname for this. */
7278 return NT_STATUS_INVALID_LEVEL;
7281 status = smb_posix_open(conn, req,
7290 case SMB_POSIX_PATH_UNLINK:
7293 /* We must have a pathname for this. */
7294 return NT_STATUS_INVALID_LEVEL;
7297 status = smb_posix_unlink(conn, req,
7305 return NT_STATUS_INVALID_LEVEL;
7308 if (!NT_STATUS_IS_OK(status)) {
7312 *ret_data_size = data_return_size;
7313 return NT_STATUS_OK;
7316 /****************************************************************************
7317 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7318 ****************************************************************************/
7320 static void call_trans2setfilepathinfo(connection_struct *conn,
7321 struct smb_request *req,
7322 unsigned int tran_call,
7323 char **pparams, int total_params,
7324 char **ppdata, int total_data,
7325 unsigned int max_data_bytes)
7327 char *params = *pparams;
7328 char *pdata = *ppdata;
7331 struct smb_filename *smb_fname = NULL;
7332 files_struct *fsp = NULL;
7333 NTSTATUS status = NT_STATUS_OK;
7334 int data_return_size = 0;
7337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7341 if (tran_call == TRANSACT2_SETFILEINFO) {
7342 if (total_params < 4) {
7343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7347 fsp = file_fsp(req, SVAL(params,0));
7348 /* Basic check for non-null fsp. */
7349 if (!check_fsp_open(conn, req, fsp)) {
7352 info_level = SVAL(params,2);
7354 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
7356 reply_nterror(req, NT_STATUS_NO_MEMORY);
7360 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
7362 if (!NT_STATUS_IS_OK(status)) {
7363 reply_nterror(req, status);
7367 if(fsp->is_directory || fsp->fh->fd == -1) {
7369 * This is actually a SETFILEINFO on a directory
7370 * handle (returned from an NT SMB). NT5.0 seems
7371 * to do this call. JRA.
7373 if (INFO_LEVEL_IS_UNIX(info_level)) {
7374 /* Always do lstat for UNIX calls. */
7375 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7376 DEBUG(3,("call_trans2setfilepathinfo: "
7377 "SMB_VFS_LSTAT of %s failed "
7379 smb_fname_str_dbg(smb_fname),
7381 reply_nterror(req, map_nt_error_from_unix(errno));
7385 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7386 DEBUG(3,("call_trans2setfilepathinfo: "
7387 "fileinfo of %s failed (%s)\n",
7388 smb_fname_str_dbg(smb_fname),
7390 reply_nterror(req, map_nt_error_from_unix(errno));
7394 } else if (fsp->print_file) {
7396 * Doing a DELETE_ON_CLOSE should cancel a print job.
7398 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7399 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7401 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
7404 send_trans2_replies(conn, req, params, 2,
7409 reply_doserror(req, ERRDOS, ERRbadpath);
7414 * Original code - this is an open file.
7416 if (!check_fsp(conn, req, fsp)) {
7420 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7421 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7422 "of fnum %d failed (%s)\n", fsp->fnum,
7424 reply_nterror(req, map_nt_error_from_unix(errno));
7430 if (total_params < 7) {
7431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7435 info_level = SVAL(params,0);
7436 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7437 total_params - 6, STR_TERMINATE,
7439 if (!NT_STATUS_IS_OK(status)) {
7440 reply_nterror(req, status);
7444 status = filename_convert(req, conn,
7445 req->flags2 & FLAGS2_DFS_PATHNAMES,
7449 if (!NT_STATUS_IS_OK(status)) {
7450 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7451 reply_botherror(req,
7452 NT_STATUS_PATH_NOT_COVERED,
7453 ERRSRV, ERRbadpath);
7456 reply_nterror(req, status);
7460 if (INFO_LEVEL_IS_UNIX(info_level)) {
7462 * For CIFS UNIX extensions the target name may not exist.
7465 /* Always do lstat for UNIX calls. */
7466 SMB_VFS_LSTAT(conn, smb_fname);
7468 } else if (!VALID_STAT(smb_fname->st) &&
7469 SMB_VFS_STAT(conn, smb_fname)) {
7470 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7472 smb_fname_str_dbg(smb_fname),
7474 reply_nterror(req, map_nt_error_from_unix(errno));
7479 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
7480 tran_call, fname, fsp ? fsp->fnum : -1, info_level,total_data));
7482 /* Realloc the parameter size */
7483 *pparams = (char *)SMB_REALLOC(*pparams,2);
7484 if (*pparams == NULL) {
7485 reply_nterror(req, NT_STATUS_NO_MEMORY);
7492 status = smbd_do_setfilepathinfo(conn, req, req,
7498 if (!NT_STATUS_IS_OK(status)) {
7499 if (open_was_deferred(req->mid)) {
7500 /* We have re-scheduled this call. */
7503 if (blocking_lock_was_deferred(req->mid)) {
7504 /* We have re-scheduled this call. */
7507 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7508 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7509 ERRSRV, ERRbadpath);
7512 if (info_level == SMB_POSIX_PATH_OPEN) {
7513 reply_openerror(req, status);
7517 reply_nterror(req, status);
7521 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7527 /****************************************************************************
7528 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7529 ****************************************************************************/
7531 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7532 char **pparams, int total_params,
7533 char **ppdata, int total_data,
7534 unsigned int max_data_bytes)
7536 struct smb_filename *smb_dname = NULL;
7537 char *params = *pparams;
7538 char *pdata = *ppdata;
7539 char *directory = NULL;
7540 NTSTATUS status = NT_STATUS_OK;
7541 struct ea_list *ea_list = NULL;
7542 TALLOC_CTX *ctx = talloc_tos();
7544 if (!CAN_WRITE(conn)) {
7545 reply_doserror(req, ERRSRV, ERRaccess);
7549 if (total_params < 5) {
7550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7554 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7555 total_params - 4, STR_TERMINATE,
7557 if (!NT_STATUS_IS_OK(status)) {
7558 reply_nterror(req, status);
7562 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7564 status = filename_convert(ctx,
7566 req->flags2 & FLAGS2_DFS_PATHNAMES,
7571 if (!NT_STATUS_IS_OK(status)) {
7572 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7573 reply_botherror(req,
7574 NT_STATUS_PATH_NOT_COVERED,
7575 ERRSRV, ERRbadpath);
7578 reply_nterror(req, status);
7582 /* Any data in this call is an EA list. */
7583 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7584 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7589 * OS/2 workplace shell seems to send SET_EA requests of "null"
7590 * length (4 bytes containing IVAL 4).
7591 * They seem to have no effect. Bug #3212. JRA.
7594 if (total_data != 4) {
7595 if (total_data < 10) {
7596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7600 if (IVAL(pdata,0) > total_data) {
7601 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7602 IVAL(pdata,0), (unsigned int)total_data));
7603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7607 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7610 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7614 /* If total_data == 4 Windows doesn't care what values
7615 * are placed in that field, it just ignores them.
7616 * The System i QNTC IBM SMB client puts bad values here,
7617 * so ignore them. */
7619 status = create_directory(conn, req, smb_dname);
7621 if (!NT_STATUS_IS_OK(status)) {
7622 reply_nterror(req, status);
7626 /* Try and set any given EA. */
7628 status = set_ea(conn, NULL, smb_dname, ea_list);
7629 if (!NT_STATUS_IS_OK(status)) {
7630 reply_nterror(req, status);
7635 /* Realloc the parameter and data sizes */
7636 *pparams = (char *)SMB_REALLOC(*pparams,2);
7637 if(*pparams == NULL) {
7638 reply_nterror(req, NT_STATUS_NO_MEMORY);
7645 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7648 TALLOC_FREE(smb_dname);
7652 /****************************************************************************
7653 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7654 We don't actually do this - we just send a null response.
7655 ****************************************************************************/
7657 static void call_trans2findnotifyfirst(connection_struct *conn,
7658 struct smb_request *req,
7659 char **pparams, int total_params,
7660 char **ppdata, int total_data,
7661 unsigned int max_data_bytes)
7663 char *params = *pparams;
7666 if (total_params < 6) {
7667 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7671 info_level = SVAL(params,4);
7672 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7674 switch (info_level) {
7679 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7683 /* Realloc the parameter and data sizes */
7684 *pparams = (char *)SMB_REALLOC(*pparams,6);
7685 if (*pparams == NULL) {
7686 reply_nterror(req, NT_STATUS_NO_MEMORY);
7691 SSVAL(params,0,fnf_handle);
7692 SSVAL(params,2,0); /* No changes */
7693 SSVAL(params,4,0); /* No EA errors */
7700 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7705 /****************************************************************************
7706 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7707 changes). Currently this does nothing.
7708 ****************************************************************************/
7710 static void call_trans2findnotifynext(connection_struct *conn,
7711 struct smb_request *req,
7712 char **pparams, int total_params,
7713 char **ppdata, int total_data,
7714 unsigned int max_data_bytes)
7716 char *params = *pparams;
7718 DEBUG(3,("call_trans2findnotifynext\n"));
7720 /* Realloc the parameter and data sizes */
7721 *pparams = (char *)SMB_REALLOC(*pparams,4);
7722 if (*pparams == NULL) {
7723 reply_nterror(req, NT_STATUS_NO_MEMORY);
7728 SSVAL(params,0,0); /* No changes */
7729 SSVAL(params,2,0); /* No EA errors */
7731 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7736 /****************************************************************************
7737 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7738 ****************************************************************************/
7740 static void call_trans2getdfsreferral(connection_struct *conn,
7741 struct smb_request *req,
7742 char **pparams, int total_params,
7743 char **ppdata, int total_data,
7744 unsigned int max_data_bytes)
7746 char *params = *pparams;
7747 char *pathname = NULL;
7749 int max_referral_level;
7750 NTSTATUS status = NT_STATUS_OK;
7751 TALLOC_CTX *ctx = talloc_tos();
7753 DEBUG(10,("call_trans2getdfsreferral\n"));
7755 if (total_params < 3) {
7756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7760 max_referral_level = SVAL(params,0);
7762 if(!lp_host_msdfs()) {
7763 reply_doserror(req, ERRDOS, ERRbadfunc);
7767 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7768 total_params - 2, STR_TERMINATE);
7770 reply_nterror(req, NT_STATUS_NOT_FOUND);
7773 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7774 ppdata,&status)) < 0) {
7775 reply_nterror(req, status);
7779 SSVAL(req->inbuf, smb_flg2,
7780 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7781 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7786 #define LMCAT_SPL 0x53
7787 #define LMFUNC_GETJOBID 0x60
7789 /****************************************************************************
7790 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7791 ****************************************************************************/
7793 static void call_trans2ioctl(connection_struct *conn,
7794 struct smb_request *req,
7795 char **pparams, int total_params,
7796 char **ppdata, int total_data,
7797 unsigned int max_data_bytes)
7799 char *pdata = *ppdata;
7800 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7802 /* check for an invalid fid before proceeding */
7805 reply_doserror(req, ERRDOS, ERRbadfid);
7809 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7810 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7811 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7812 if (*ppdata == NULL) {
7813 reply_nterror(req, NT_STATUS_NO_MEMORY);
7818 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7819 CAN ACCEPT THIS IN UNICODE. JRA. */
7821 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7822 srvstr_push(pdata, req->flags2, pdata + 2,
7823 global_myname(), 15,
7824 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7825 srvstr_push(pdata, req->flags2, pdata+18,
7826 lp_servicename(SNUM(conn)), 13,
7827 STR_ASCII|STR_TERMINATE); /* Service name */
7828 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7833 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7834 reply_doserror(req, ERRSRV, ERRerror);
7837 /****************************************************************************
7838 Reply to a SMBfindclose (stop trans2 directory search).
7839 ****************************************************************************/
7841 void reply_findclose(struct smb_request *req)
7845 START_PROFILE(SMBfindclose);
7848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7849 END_PROFILE(SMBfindclose);
7853 dptr_num = SVALS(req->vwv+0, 0);
7855 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7857 dptr_close(&dptr_num);
7859 reply_outbuf(req, 0, 0);
7861 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7863 END_PROFILE(SMBfindclose);
7867 /****************************************************************************
7868 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7869 ****************************************************************************/
7871 void reply_findnclose(struct smb_request *req)
7875 START_PROFILE(SMBfindnclose);
7878 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7879 END_PROFILE(SMBfindnclose);
7883 dptr_num = SVAL(req->vwv+0, 0);
7885 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7887 /* We never give out valid handles for a
7888 findnotifyfirst - so any dptr_num is ok here.
7891 reply_outbuf(req, 0, 0);
7893 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7895 END_PROFILE(SMBfindnclose);
7899 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7900 struct trans_state *state)
7902 if (Protocol >= PROTOCOL_NT1) {
7903 req->flags2 |= 0x40; /* IS_LONG_NAME */
7904 SSVAL(req->inbuf,smb_flg2,req->flags2);
7907 if (conn->encrypt_level == Required && !req->encrypted) {
7908 if (state->call != TRANSACT2_QFSINFO &&
7909 state->call != TRANSACT2_SETFSINFO) {
7910 DEBUG(0,("handle_trans2: encryption required "
7912 (unsigned int)state->call));
7913 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7918 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7920 /* Now we must call the relevant TRANS2 function */
7921 switch(state->call) {
7922 case TRANSACT2_OPEN:
7924 START_PROFILE(Trans2_open);
7925 call_trans2open(conn, req,
7926 &state->param, state->total_param,
7927 &state->data, state->total_data,
7928 state->max_data_return);
7929 END_PROFILE(Trans2_open);
7933 case TRANSACT2_FINDFIRST:
7935 START_PROFILE(Trans2_findfirst);
7936 call_trans2findfirst(conn, req,
7937 &state->param, state->total_param,
7938 &state->data, state->total_data,
7939 state->max_data_return);
7940 END_PROFILE(Trans2_findfirst);
7944 case TRANSACT2_FINDNEXT:
7946 START_PROFILE(Trans2_findnext);
7947 call_trans2findnext(conn, req,
7948 &state->param, state->total_param,
7949 &state->data, state->total_data,
7950 state->max_data_return);
7951 END_PROFILE(Trans2_findnext);
7955 case TRANSACT2_QFSINFO:
7957 START_PROFILE(Trans2_qfsinfo);
7958 call_trans2qfsinfo(conn, req,
7959 &state->param, state->total_param,
7960 &state->data, state->total_data,
7961 state->max_data_return);
7962 END_PROFILE(Trans2_qfsinfo);
7966 case TRANSACT2_SETFSINFO:
7968 START_PROFILE(Trans2_setfsinfo);
7969 call_trans2setfsinfo(conn, req,
7970 &state->param, state->total_param,
7971 &state->data, state->total_data,
7972 state->max_data_return);
7973 END_PROFILE(Trans2_setfsinfo);
7977 case TRANSACT2_QPATHINFO:
7978 case TRANSACT2_QFILEINFO:
7980 START_PROFILE(Trans2_qpathinfo);
7981 call_trans2qfilepathinfo(conn, req, state->call,
7982 &state->param, state->total_param,
7983 &state->data, state->total_data,
7984 state->max_data_return);
7985 END_PROFILE(Trans2_qpathinfo);
7989 case TRANSACT2_SETPATHINFO:
7990 case TRANSACT2_SETFILEINFO:
7992 START_PROFILE(Trans2_setpathinfo);
7993 call_trans2setfilepathinfo(conn, req, state->call,
7994 &state->param, state->total_param,
7995 &state->data, state->total_data,
7996 state->max_data_return);
7997 END_PROFILE(Trans2_setpathinfo);
8001 case TRANSACT2_FINDNOTIFYFIRST:
8003 START_PROFILE(Trans2_findnotifyfirst);
8004 call_trans2findnotifyfirst(conn, req,
8005 &state->param, state->total_param,
8006 &state->data, state->total_data,
8007 state->max_data_return);
8008 END_PROFILE(Trans2_findnotifyfirst);
8012 case TRANSACT2_FINDNOTIFYNEXT:
8014 START_PROFILE(Trans2_findnotifynext);
8015 call_trans2findnotifynext(conn, req,
8016 &state->param, state->total_param,
8017 &state->data, state->total_data,
8018 state->max_data_return);
8019 END_PROFILE(Trans2_findnotifynext);
8023 case TRANSACT2_MKDIR:
8025 START_PROFILE(Trans2_mkdir);
8026 call_trans2mkdir(conn, req,
8027 &state->param, state->total_param,
8028 &state->data, state->total_data,
8029 state->max_data_return);
8030 END_PROFILE(Trans2_mkdir);
8034 case TRANSACT2_GET_DFS_REFERRAL:
8036 START_PROFILE(Trans2_get_dfs_referral);
8037 call_trans2getdfsreferral(conn, req,
8038 &state->param, state->total_param,
8039 &state->data, state->total_data,
8040 state->max_data_return);
8041 END_PROFILE(Trans2_get_dfs_referral);
8045 case TRANSACT2_IOCTL:
8047 START_PROFILE(Trans2_ioctl);
8048 call_trans2ioctl(conn, req,
8049 &state->param, state->total_param,
8050 &state->data, state->total_data,
8051 state->max_data_return);
8052 END_PROFILE(Trans2_ioctl);
8057 /* Error in request */
8058 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8059 reply_doserror(req, ERRSRV,ERRerror);
8063 /****************************************************************************
8064 Reply to a SMBtrans2.
8065 ****************************************************************************/
8067 void reply_trans2(struct smb_request *req)
8069 connection_struct *conn = req->conn;
8074 unsigned int tran_call;
8075 struct trans_state *state;
8078 START_PROFILE(SMBtrans2);
8080 if (req->wct < 14) {
8081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8082 END_PROFILE(SMBtrans2);
8086 dsoff = SVAL(req->vwv+12, 0);
8087 dscnt = SVAL(req->vwv+11, 0);
8088 psoff = SVAL(req->vwv+10, 0);
8089 pscnt = SVAL(req->vwv+9, 0);
8090 tran_call = SVAL(req->vwv+14, 0);
8092 result = allow_new_trans(conn->pending_trans, req->mid);
8093 if (!NT_STATUS_IS_OK(result)) {
8094 DEBUG(2, ("Got invalid trans2 request: %s\n",
8095 nt_errstr(result)));
8096 reply_nterror(req, result);
8097 END_PROFILE(SMBtrans2);
8102 switch (tran_call) {
8103 /* List the allowed trans2 calls on IPC$ */
8104 case TRANSACT2_OPEN:
8105 case TRANSACT2_GET_DFS_REFERRAL:
8106 case TRANSACT2_QFILEINFO:
8107 case TRANSACT2_QFSINFO:
8108 case TRANSACT2_SETFSINFO:
8111 reply_doserror(req, ERRSRV, ERRaccess);
8112 END_PROFILE(SMBtrans2);
8117 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8118 DEBUG(0, ("talloc failed\n"));
8119 reply_nterror(req, NT_STATUS_NO_MEMORY);
8120 END_PROFILE(SMBtrans2);
8124 state->cmd = SMBtrans2;
8126 state->mid = req->mid;
8127 state->vuid = req->vuid;
8128 state->setup_count = SVAL(req->vwv+13, 0);
8129 state->setup = NULL;
8130 state->total_param = SVAL(req->vwv+0, 0);
8131 state->param = NULL;
8132 state->total_data = SVAL(req->vwv+1, 0);
8134 state->max_param_return = SVAL(req->vwv+2, 0);
8135 state->max_data_return = SVAL(req->vwv+3, 0);
8136 state->max_setup_return = SVAL(req->vwv+4, 0);
8137 state->close_on_completion = BITSETW(req->vwv+5, 0);
8138 state->one_way = BITSETW(req->vwv+5, 1);
8140 state->call = tran_call;
8142 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8143 is so as a sanity check */
8144 if (state->setup_count != 1) {
8146 * Need to have rc=0 for ioctl to get job id for OS/2.
8147 * Network printing will fail if function is not successful.
8148 * Similar function in reply.c will be used if protocol
8149 * is LANMAN1.0 instead of LM1.2X002.
8150 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8151 * outbuf doesn't have to be set(only job id is used).
8153 if ( (state->setup_count == 4)
8154 && (tran_call == TRANSACT2_IOCTL)
8155 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8156 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8157 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8159 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8160 DEBUG(2,("Transaction is %d\n",tran_call));
8162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8163 END_PROFILE(SMBtrans2);
8168 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8171 if (state->total_data) {
8173 if (trans_oob(state->total_data, 0, dscnt)
8174 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8178 /* Can't use talloc here, the core routines do realloc on the
8179 * params and data. */
8180 state->data = (char *)SMB_MALLOC(state->total_data);
8181 if (state->data == NULL) {
8182 DEBUG(0,("reply_trans2: data malloc fail for %u "
8183 "bytes !\n", (unsigned int)state->total_data));
8185 reply_nterror(req, NT_STATUS_NO_MEMORY);
8186 END_PROFILE(SMBtrans2);
8190 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8193 if (state->total_param) {
8195 if (trans_oob(state->total_param, 0, pscnt)
8196 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8200 /* Can't use talloc here, the core routines do realloc on the
8201 * params and data. */
8202 state->param = (char *)SMB_MALLOC(state->total_param);
8203 if (state->param == NULL) {
8204 DEBUG(0,("reply_trans: param malloc fail for %u "
8205 "bytes !\n", (unsigned int)state->total_param));
8206 SAFE_FREE(state->data);
8208 reply_nterror(req, NT_STATUS_NO_MEMORY);
8209 END_PROFILE(SMBtrans2);
8213 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8216 state->received_data = dscnt;
8217 state->received_param = pscnt;
8219 if ((state->received_param == state->total_param) &&
8220 (state->received_data == state->total_data)) {
8222 handle_trans2(conn, req, state);
8224 SAFE_FREE(state->data);
8225 SAFE_FREE(state->param);
8227 END_PROFILE(SMBtrans2);
8231 DLIST_ADD(conn->pending_trans, state);
8233 /* We need to send an interim response then receive the rest
8234 of the parameter/data bytes */
8235 reply_outbuf(req, 0, 0);
8236 show_msg((char *)req->outbuf);
8237 END_PROFILE(SMBtrans2);
8242 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8243 SAFE_FREE(state->data);
8244 SAFE_FREE(state->param);
8246 END_PROFILE(SMBtrans2);
8247 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8251 /****************************************************************************
8252 Reply to a SMBtranss2
8253 ****************************************************************************/
8255 void reply_transs2(struct smb_request *req)
8257 connection_struct *conn = req->conn;
8258 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8259 struct trans_state *state;
8261 START_PROFILE(SMBtranss2);
8263 show_msg((char *)req->inbuf);
8266 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8267 END_PROFILE(SMBtranss2);
8271 for (state = conn->pending_trans; state != NULL;
8272 state = state->next) {
8273 if (state->mid == req->mid) {
8278 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8280 END_PROFILE(SMBtranss2);
8284 /* Revise state->total_param and state->total_data in case they have
8285 changed downwards */
8287 if (SVAL(req->vwv+0, 0) < state->total_param)
8288 state->total_param = SVAL(req->vwv+0, 0);
8289 if (SVAL(req->vwv+1, 0) < state->total_data)
8290 state->total_data = SVAL(req->vwv+1, 0);
8292 pcnt = SVAL(req->vwv+2, 0);
8293 poff = SVAL(req->vwv+3, 0);
8294 pdisp = SVAL(req->vwv+4, 0);
8296 dcnt = SVAL(req->vwv+5, 0);
8297 doff = SVAL(req->vwv+6, 0);
8298 ddisp = SVAL(req->vwv+7, 0);
8300 state->received_param += pcnt;
8301 state->received_data += dcnt;
8303 if ((state->received_data > state->total_data) ||
8304 (state->received_param > state->total_param))
8308 if (trans_oob(state->total_param, pdisp, pcnt)
8309 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8312 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8316 if (trans_oob(state->total_data, ddisp, dcnt)
8317 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8320 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8323 if ((state->received_param < state->total_param) ||
8324 (state->received_data < state->total_data)) {
8325 END_PROFILE(SMBtranss2);
8329 handle_trans2(conn, req, state);
8331 DLIST_REMOVE(conn->pending_trans, state);
8332 SAFE_FREE(state->data);
8333 SAFE_FREE(state->param);
8336 END_PROFILE(SMBtranss2);
8341 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8342 DLIST_REMOVE(conn->pending_trans, state);
8343 SAFE_FREE(state->data);
8344 SAFE_FREE(state->param);
8346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8347 END_PROFILE(SMBtranss2);