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 "
506 "file %s by file descriptor.\n",
507 unix_ea_name, fsp_str_dbg(fsp)));
508 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
510 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
511 unix_ea_name, fname));
512 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
515 /* Removing a non existent attribute always succeeds. */
516 if (ret == -1 && errno == ENOATTR) {
517 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
523 if (fsp && (fsp->fh->fd != -1)) {
524 DEBUG(10,("set_ea: setting ea name %s on file "
525 "%s by file descriptor.\n",
526 unix_ea_name, fsp_str_dbg(fsp)));
527 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
528 ea_list->ea.value.data, ea_list->ea.value.length, 0);
530 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
531 unix_ea_name, fname));
532 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
533 ea_list->ea.value.data, ea_list->ea.value.length, 0);
539 if (errno == ENOTSUP) {
540 return NT_STATUS_EAS_NOT_SUPPORTED;
543 return map_nt_error_from_unix(errno);
549 /****************************************************************************
550 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
551 ****************************************************************************/
553 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
555 struct ea_list *ea_list_head = NULL;
556 size_t converted_size, offset = 0;
558 while (offset + 2 < data_size) {
559 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
560 unsigned int namelen = CVAL(pdata,offset);
562 offset++; /* Go past the namelen byte. */
564 /* integer wrap paranioa. */
565 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
566 (offset > data_size) || (namelen > data_size) ||
567 (offset + namelen >= data_size)) {
570 /* Ensure the name is null terminated. */
571 if (pdata[offset + namelen] != '\0') {
574 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
576 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
577 "failed: %s", strerror(errno)));
583 offset += (namelen + 1); /* Go past the name + terminating zero. */
584 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
585 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
591 /****************************************************************************
592 Read one EA list entry from the buffer.
593 ****************************************************************************/
595 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
597 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
599 unsigned int namelen;
600 size_t converted_size;
610 eal->ea.flags = CVAL(pdata,0);
611 namelen = CVAL(pdata,1);
612 val_len = SVAL(pdata,2);
614 if (4 + namelen + 1 + val_len > data_size) {
618 /* Ensure the name is null terminated. */
619 if (pdata[namelen + 4] != '\0') {
622 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
623 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
630 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
631 if (!eal->ea.value.data) {
635 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
637 /* Ensure we're null terminated just in case we print the value. */
638 eal->ea.value.data[val_len] = '\0';
639 /* But don't count the null. */
640 eal->ea.value.length--;
643 *pbytes_used = 4 + namelen + 1 + val_len;
646 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
647 dump_data(10, eal->ea.value.data, eal->ea.value.length);
652 /****************************************************************************
653 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
654 ****************************************************************************/
656 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
658 struct ea_list *ea_list_head = NULL;
660 size_t bytes_used = 0;
662 while (offset < data_size) {
663 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
669 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
670 offset += bytes_used;
676 /****************************************************************************
677 Count the total EA size needed.
678 ****************************************************************************/
680 static size_t ea_list_size(struct ea_list *ealist)
683 struct ea_list *listp;
686 for (listp = ealist; listp; listp = listp->next) {
687 push_ascii_fstring(dos_ea_name, listp->ea.name);
688 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
690 /* Add on 4 for total length. */
698 /****************************************************************************
699 Return a union of EA's from a file list and a list of names.
700 The TALLOC context for the two lists *MUST* be identical as we steal
701 memory from one list to add to another. JRA.
702 ****************************************************************************/
704 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
706 struct ea_list *nlistp, *flistp;
708 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
709 for (flistp = file_list; flistp; flistp = flistp->next) {
710 if (strequal(nlistp->ea.name, flistp->ea.name)) {
716 /* Copy the data from this entry. */
717 nlistp->ea.flags = flistp->ea.flags;
718 nlistp->ea.value = flistp->ea.value;
721 nlistp->ea.flags = 0;
722 ZERO_STRUCT(nlistp->ea.value);
726 *total_ea_len = ea_list_size(name_list);
730 /****************************************************************************
731 Send the required number of replies back.
732 We assume all fields other than the data fields are
733 set correctly for the type of call.
734 HACK ! Always assumes smb_setup field is zero.
735 ****************************************************************************/
737 void send_trans2_replies(connection_struct *conn,
738 struct smb_request *req,
745 /* As we are using a protocol > LANMAN1 then the max_send
746 variable must have been set in the sessetupX call.
747 This takes precedence over the max_xmit field in the
748 global struct. These different max_xmit variables should
749 be merged as this is now too confusing */
751 int data_to_send = datasize;
752 int params_to_send = paramsize;
754 const char *pp = params;
755 const char *pd = pdata;
756 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
757 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
758 int data_alignment_offset = 0;
759 bool overflow = False;
760 struct smbd_server_connection *sconn = smbd_server_conn;
761 int max_send = sconn->smb1.sessions.max_send;
763 /* Modify the data_to_send and datasize and set the error if
764 we're trying to send more than max_data_bytes. We still send
765 the part of the packet(s) that fit. Strange, but needed
768 if (max_data_bytes > 0 && datasize > max_data_bytes) {
769 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
770 max_data_bytes, datasize ));
771 datasize = data_to_send = max_data_bytes;
775 /* If there genuinely are no parameters or data to send just send the empty packet */
777 if(params_to_send == 0 && data_to_send == 0) {
778 reply_outbuf(req, 10, 0);
779 show_msg((char *)req->outbuf);
780 if (!srv_send_smb(smbd_server_fd(),
783 IS_CONN_ENCRYPTED(conn),
785 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
787 TALLOC_FREE(req->outbuf);
791 /* When sending params and data ensure that both are nicely aligned */
792 /* Only do this alignment when there is also data to send - else
793 can cause NT redirector problems. */
795 if (((params_to_send % 4) != 0) && (data_to_send != 0))
796 data_alignment_offset = 4 - (params_to_send % 4);
798 /* Space is bufsize minus Netbios over TCP header minus SMB header */
799 /* The alignment_offset is to align the param bytes on an even byte
800 boundary. NT 4.0 Beta needs this to work correctly. */
802 useable_space = max_send - (smb_size
805 + data_alignment_offset);
807 if (useable_space < 0) {
808 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
809 "= %d!!!", useable_space));
810 exit_server_cleanly("send_trans2_replies: Not enough space");
813 while (params_to_send || data_to_send) {
814 /* Calculate whether we will totally or partially fill this packet */
816 total_sent_thistime = params_to_send + data_to_send;
818 /* We can never send more than useable_space */
820 * Note that 'useable_space' does not include the alignment offsets,
821 * but we must include the alignment offsets in the calculation of
822 * the length of the data we send over the wire, as the alignment offsets
823 * are sent here. Fix from Marc_Jacobsen@hp.com.
826 total_sent_thistime = MIN(total_sent_thistime, useable_space);
828 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
829 + data_alignment_offset);
832 * We might have SMBtrans2s in req which was transferred to
833 * the outbuf, fix that.
835 SCVAL(req->outbuf, smb_com, SMBtrans2);
837 /* Set total params and data to be sent */
838 SSVAL(req->outbuf,smb_tprcnt,paramsize);
839 SSVAL(req->outbuf,smb_tdrcnt,datasize);
841 /* Calculate how many parameters and data we can fit into
842 * this packet. Parameters get precedence
845 params_sent_thistime = MIN(params_to_send,useable_space);
846 data_sent_thistime = useable_space - params_sent_thistime;
847 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
849 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
851 /* smb_proff is the offset from the start of the SMB header to the
852 parameter bytes, however the first 4 bytes of outbuf are
853 the Netbios over TCP header. Thus use smb_base() to subtract
854 them from the calculation */
856 SSVAL(req->outbuf,smb_proff,
857 ((smb_buf(req->outbuf)+alignment_offset)
858 - smb_base(req->outbuf)));
860 if(params_sent_thistime == 0)
861 SSVAL(req->outbuf,smb_prdisp,0);
863 /* Absolute displacement of param bytes sent in this packet */
864 SSVAL(req->outbuf,smb_prdisp,pp - params);
866 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
867 if(data_sent_thistime == 0) {
868 SSVAL(req->outbuf,smb_droff,0);
869 SSVAL(req->outbuf,smb_drdisp, 0);
871 /* The offset of the data bytes is the offset of the
872 parameter bytes plus the number of parameters being sent this time */
873 SSVAL(req->outbuf, smb_droff,
874 ((smb_buf(req->outbuf)+alignment_offset)
875 - smb_base(req->outbuf))
876 + params_sent_thistime + data_alignment_offset);
877 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
880 /* Initialize the padding for alignment */
882 if (alignment_offset != 0) {
883 memset(smb_buf(req->outbuf), 0, alignment_offset);
886 /* Copy the param bytes into the packet */
888 if(params_sent_thistime) {
889 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
890 params_sent_thistime);
893 /* Copy in the data bytes */
894 if(data_sent_thistime) {
895 if (data_alignment_offset != 0) {
896 memset((smb_buf(req->outbuf)+alignment_offset+
897 params_sent_thistime), 0,
898 data_alignment_offset);
900 memcpy(smb_buf(req->outbuf)+alignment_offset
901 +params_sent_thistime+data_alignment_offset,
902 pd,data_sent_thistime);
905 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
906 params_sent_thistime, data_sent_thistime, useable_space));
907 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
908 params_to_send, data_to_send, paramsize, datasize));
911 error_packet_set((char *)req->outbuf,
912 ERRDOS,ERRbufferoverflow,
913 STATUS_BUFFER_OVERFLOW,
917 /* Send the packet */
918 show_msg((char *)req->outbuf);
919 if (!srv_send_smb(smbd_server_fd(),
922 IS_CONN_ENCRYPTED(conn),
924 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
926 TALLOC_FREE(req->outbuf);
928 pp += params_sent_thistime;
929 pd += data_sent_thistime;
931 params_to_send -= params_sent_thistime;
932 data_to_send -= data_sent_thistime;
935 if(params_to_send < 0 || data_to_send < 0) {
936 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
937 params_to_send, data_to_send));
945 /****************************************************************************
946 Reply to a TRANSACT2_OPEN.
947 ****************************************************************************/
949 static void call_trans2open(connection_struct *conn,
950 struct smb_request *req,
951 char **pparams, int total_params,
952 char **ppdata, int total_data,
953 unsigned int max_data_bytes)
955 struct smb_filename *smb_fname = NULL;
956 char *params = *pparams;
957 char *pdata = *ppdata;
962 bool return_additional_info;
975 struct ea_list *ea_list = NULL;
980 uint32 create_disposition;
981 uint32 create_options = 0;
982 TALLOC_CTX *ctx = talloc_tos();
985 * Ensure we have enough parameters to perform the operation.
988 if (total_params < 29) {
989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
993 flags = SVAL(params, 0);
994 deny_mode = SVAL(params, 2);
995 open_attr = SVAL(params,6);
996 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
997 if (oplock_request) {
998 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1002 return_additional_info = BITSETW(params,0);
1003 open_sattr = SVAL(params, 4);
1004 open_time = make_unix_date3(params+8);
1006 open_ofun = SVAL(params,12);
1007 open_size = IVAL(params,14);
1008 pname = ¶ms[28];
1011 reply_doserror(req, ERRSRV, ERRaccess);
1015 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1016 total_params - 28, STR_TERMINATE,
1018 if (!NT_STATUS_IS_OK(status)) {
1019 reply_nterror(req, status);
1023 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1024 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1025 (unsigned int)open_ofun, open_size));
1027 status = filename_convert(ctx,
1029 req->flags2 & FLAGS2_DFS_PATHNAMES,
1033 if (!NT_STATUS_IS_OK(status)) {
1034 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1035 reply_botherror(req,
1036 NT_STATUS_PATH_NOT_COVERED,
1037 ERRSRV, ERRbadpath);
1040 reply_nterror(req, status);
1044 if (open_ofun == 0) {
1045 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1049 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1050 &access_mask, &share_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,
1152 fsp->fsp_name->base_name);
1153 SIVAL(params, 26, ea_size);
1155 SIVAL(params, 26, 0);
1158 /* Send the required number of replies */
1159 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1161 TALLOC_FREE(smb_fname);
1164 /*********************************************************
1165 Routine to check if a given string matches exactly.
1166 as a special case a mask of "." does NOT match. That
1167 is required for correct wildcard semantics
1168 Case can be significant or not.
1169 **********************************************************/
1171 static bool exact_match(connection_struct *conn,
1175 if (mask[0] == '.' && mask[1] == 0)
1177 if (dptr_has_wild(conn->dirptr)) {
1180 if (conn->case_sensitive)
1181 return strcmp(str,mask)==0;
1183 return StrCaseCmp(str,mask) == 0;
1186 /****************************************************************************
1187 Return the filetype for UNIX extensions.
1188 ****************************************************************************/
1190 static uint32 unix_filetype(mode_t mode)
1193 return UNIX_TYPE_FILE;
1194 else if(S_ISDIR(mode))
1195 return UNIX_TYPE_DIR;
1197 else if(S_ISLNK(mode))
1198 return UNIX_TYPE_SYMLINK;
1201 else if(S_ISCHR(mode))
1202 return UNIX_TYPE_CHARDEV;
1205 else if(S_ISBLK(mode))
1206 return UNIX_TYPE_BLKDEV;
1209 else if(S_ISFIFO(mode))
1210 return UNIX_TYPE_FIFO;
1213 else if(S_ISSOCK(mode))
1214 return UNIX_TYPE_SOCKET;
1217 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1218 return UNIX_TYPE_UNKNOWN;
1221 /****************************************************************************
1222 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1223 ****************************************************************************/
1225 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1227 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1228 const SMB_STRUCT_STAT *psbuf,
1230 enum perm_type ptype,
1235 if (perms == SMB_MODE_NO_CHANGE) {
1236 if (!VALID_STAT(*psbuf)) {
1237 return NT_STATUS_INVALID_PARAMETER;
1239 *ret_perms = psbuf->st_ex_mode;
1240 return NT_STATUS_OK;
1244 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1245 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1246 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1247 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1248 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1249 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1250 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1251 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1252 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1254 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1257 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1260 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1265 /* Apply mode mask */
1266 ret &= lp_create_mask(SNUM(conn));
1267 /* Add in force bits */
1268 ret |= lp_force_create_mode(SNUM(conn));
1271 ret &= lp_dir_mask(SNUM(conn));
1272 /* Add in force bits */
1273 ret |= lp_force_dir_mode(SNUM(conn));
1275 case PERM_EXISTING_FILE:
1276 /* Apply mode mask */
1277 ret &= lp_security_mask(SNUM(conn));
1278 /* Add in force bits */
1279 ret |= lp_force_security_mode(SNUM(conn));
1281 case PERM_EXISTING_DIR:
1282 /* Apply mode mask */
1283 ret &= lp_dir_security_mask(SNUM(conn));
1284 /* Add in force bits */
1285 ret |= lp_force_dir_security_mode(SNUM(conn));
1290 return NT_STATUS_OK;
1293 /****************************************************************************
1294 Needed to show the msdfs symlinks as directories. Modifies psbuf
1295 to be a directory if it's a msdfs link.
1296 ****************************************************************************/
1298 static bool check_msdfs_link(connection_struct *conn,
1299 const char *pathname,
1300 SMB_STRUCT_STAT *psbuf)
1302 int saved_errno = errno;
1303 if(lp_host_msdfs() &&
1304 lp_msdfs_root(SNUM(conn)) &&
1305 is_msdfs_link(conn, pathname, psbuf)) {
1307 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1310 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1311 errno = saved_errno;
1314 errno = saved_errno;
1319 /****************************************************************************
1320 Get a level dependent lanman2 dir entry.
1321 ****************************************************************************/
1323 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1324 connection_struct *conn,
1326 const char *path_mask,
1329 int requires_resume_key,
1335 int space_remaining,
1337 bool *got_exact_match,
1338 int *last_entry_off,
1339 struct ea_list *name_list)
1343 SMB_STRUCT_STAT sbuf;
1344 const char *mask = NULL;
1345 char *pathreal = NULL;
1347 char *p, *q, *pdata = *ppdata;
1351 SMB_OFF_T file_size = 0;
1352 uint64_t allocation_size = 0;
1354 struct timespec mdate_ts, adate_ts, create_date_ts;
1355 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1357 char *last_entry_ptr;
1359 uint32 nt_extmode; /* Used for NT connections instead of mode */
1360 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1361 bool check_mangled_names = lp_manglednames(conn->params);
1362 char mangled_name[13]; /* mangled 8.3 name. */
1364 *out_of_space = False;
1365 *got_exact_match = False;
1367 ZERO_STRUCT(mdate_ts);
1368 ZERO_STRUCT(adate_ts);
1369 ZERO_STRUCT(create_date_ts);
1371 if (!conn->dirptr) {
1375 p = strrchr_m(path_mask,'/');
1378 mask = talloc_strdup(ctx,"*.*");
1388 bool ms_dfs_link = False;
1390 /* Needed if we run out of space */
1391 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1392 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1395 * Due to bugs in NT client redirectors we are not using
1396 * resume keys any more - set them to zero.
1397 * Check out the related comments in findfirst/findnext.
1403 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1404 (long)conn->dirptr,curr_dirpos));
1411 * fname may get mangled, dname is never mangled.
1412 * Whenever we're accessing the filesystem we use
1413 * pathreal which is composed from dname.
1419 /* Mangle fname if it's an illegal name. */
1420 if (mangle_must_mangle(dname,conn->params)) {
1421 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1423 continue; /* Error - couldn't mangle. */
1425 fname = talloc_strdup(ctx, mangled_name);
1431 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1432 got_match = mask_match(fname, mask, conn->case_sensitive);
1435 if(!got_match && check_mangled_names &&
1436 !mangle_is_8_3(fname, False, conn->params)) {
1438 * It turns out that NT matches wildcards against
1439 * both long *and* short names. This may explain some
1440 * of the wildcard wierdness from old DOS clients
1441 * that some people have been seeing.... JRA.
1443 /* Force the mangling into 8.3. */
1444 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1446 continue; /* Error - couldn't mangle. */
1449 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1450 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1455 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1456 struct smb_filename *smb_fname = NULL;
1459 if (dont_descend && !isdots) {
1466 pathreal = talloc_asprintf(ctx,
1471 pathreal = talloc_asprintf(ctx,
1482 /* A dirent from dptr_ReadDirName isn't a stream. */
1483 status = create_synthetic_smb_fname(ctx, pathreal,
1486 if (!NT_STATUS_IS_OK(status)) {
1491 if (INFO_LEVEL_IS_UNIX(info_level)) {
1492 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
1493 DEBUG(5,("get_lanman2_dir_entry: "
1494 "Couldn't lstat [%s] (%s)\n",
1495 smb_fname_str_dbg(smb_fname),
1497 TALLOC_FREE(smb_fname);
1498 TALLOC_FREE(pathreal);
1502 } else if (!VALID_STAT(smb_fname->st) &&
1503 SMB_VFS_STAT(conn, smb_fname) != 0) {
1504 /* Needed to show the msdfs symlinks as
1508 check_msdfs_link(conn,
1509 smb_fname->base_name,
1512 DEBUG(5,("get_lanman2_dir_entry: "
1513 "Couldn't stat [%s] (%s)\n",
1514 smb_fname_str_dbg(smb_fname),
1516 TALLOC_FREE(smb_fname);
1517 TALLOC_FREE(pathreal);
1524 mode = dos_mode_msdfs(conn, smb_fname);
1526 mode = dos_mode(conn, smb_fname);
1529 if (!dir_check_ftype(conn,mode,dirtype)) {
1530 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1531 TALLOC_FREE(smb_fname);
1532 TALLOC_FREE(pathreal);
1537 if (!(mode & aDIR)) {
1538 file_size = get_file_size_stat(&smb_fname->st);
1541 SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1543 if (ask_sharemode) {
1544 struct timespec write_time_ts;
1545 struct file_id fileid;
1547 ZERO_STRUCT(write_time_ts);
1548 fileid = vfs_file_id_from_sbuf(conn,
1550 get_file_infos(fileid, NULL, &write_time_ts);
1551 if (!null_timespec(write_time_ts)) {
1552 update_stat_ex_mtime(&smb_fname->st,
1557 mdate_ts = smb_fname->st.st_ex_mtime;
1558 adate_ts = smb_fname->st.st_ex_atime;
1559 create_date_ts = smb_fname->st.st_ex_btime;
1561 if (lp_dos_filetime_resolution(SNUM(conn))) {
1562 dos_filetime_timespec(&create_date_ts);
1563 dos_filetime_timespec(&mdate_ts);
1564 dos_filetime_timespec(&adate_ts);
1567 create_date = convert_timespec_to_time_t(create_date_ts);
1568 mdate = convert_timespec_to_time_t(mdate_ts);
1569 adate = convert_timespec_to_time_t(adate_ts);
1571 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1572 smb_fname_str_dbg(smb_fname), fname));
1576 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1577 sbuf = smb_fname->st;
1579 TALLOC_FREE(smb_fname);
1589 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1591 switch (info_level) {
1592 case SMB_FIND_INFO_STANDARD:
1593 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1594 if(requires_resume_key) {
1598 srv_put_dos_date2(p,0,create_date);
1599 srv_put_dos_date2(p,4,adate);
1600 srv_put_dos_date2(p,8,mdate);
1601 SIVAL(p,12,(uint32)file_size);
1602 SIVAL(p,16,(uint32)allocation_size);
1606 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1607 p += ucs2_align(base_data, p, 0);
1609 len = srvstr_push(base_data, flags2, p,
1610 fname, PTR_DIFF(end_data, p),
1612 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1614 SCVAL(nameptr, -1, len - 2);
1616 SCVAL(nameptr, -1, 0);
1620 SCVAL(nameptr, -1, len - 1);
1622 SCVAL(nameptr, -1, 0);
1628 case SMB_FIND_EA_SIZE:
1629 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1630 if(requires_resume_key) {
1634 srv_put_dos_date2(p,0,create_date);
1635 srv_put_dos_date2(p,4,adate);
1636 srv_put_dos_date2(p,8,mdate);
1637 SIVAL(p,12,(uint32)file_size);
1638 SIVAL(p,16,(uint32)allocation_size);
1641 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1642 SIVAL(p,22,ea_size); /* Extended attributes */
1646 len = srvstr_push(base_data, flags2,
1647 p, fname, PTR_DIFF(end_data, p),
1648 STR_TERMINATE | STR_NOALIGN);
1649 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1662 SCVAL(nameptr,0,len);
1664 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1667 case SMB_FIND_EA_LIST:
1669 struct ea_list *file_list = NULL;
1672 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1676 if(requires_resume_key) {
1680 srv_put_dos_date2(p,0,create_date);
1681 srv_put_dos_date2(p,4,adate);
1682 srv_put_dos_date2(p,8,mdate);
1683 SIVAL(p,12,(uint32)file_size);
1684 SIVAL(p,16,(uint32)allocation_size);
1686 p += 22; /* p now points to the EA area. */
1688 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1689 name_list = ea_list_union(name_list, file_list, &ea_len);
1691 /* We need to determine if this entry will fit in the space available. */
1692 /* Max string size is 255 bytes. */
1693 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1694 /* Move the dirptr back to prev_dirpos */
1695 dptr_SeekDir(conn->dirptr, prev_dirpos);
1696 *out_of_space = True;
1697 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1698 return False; /* Not finished - just out of space */
1701 /* Push the ea_data followed by the name. */
1702 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1704 len = srvstr_push(base_data, flags2,
1705 p + 1, fname, PTR_DIFF(end_data, p+1),
1706 STR_TERMINATE | STR_NOALIGN);
1707 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1720 SCVAL(nameptr,0,len);
1722 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1726 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1727 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1728 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1730 SIVAL(p,0,reskey); p += 4;
1731 put_long_date_timespec(p,create_date_ts); p += 8;
1732 put_long_date_timespec(p,adate_ts); p += 8;
1733 put_long_date_timespec(p,mdate_ts); p += 8;
1734 put_long_date_timespec(p,mdate_ts); p += 8;
1735 SOFF_T(p,0,file_size); p += 8;
1736 SOFF_T(p,0,allocation_size); p += 8;
1737 SIVAL(p,0,nt_extmode); p += 4;
1738 q = p; p += 4; /* q is placeholder for name length. */
1740 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1741 SIVAL(p,0,ea_size); /* Extended attributes */
1744 /* Clear the short name buffer. This is
1745 * IMPORTANT as not doing so will trigger
1746 * a Win2k client bug. JRA.
1748 if (!was_8_3 && check_mangled_names) {
1749 if (!name_to_8_3(fname,mangled_name,True,
1751 /* Error - mangle failed ! */
1752 memset(mangled_name,'\0',12);
1754 mangled_name[12] = 0;
1755 len = srvstr_push(base_data, flags2,
1756 p+2, mangled_name, 24,
1757 STR_UPPER|STR_UNICODE);
1759 memset(p + 2 + len,'\0',24 - len);
1766 len = srvstr_push(base_data, flags2, p,
1767 fname, PTR_DIFF(end_data, p),
1768 STR_TERMINATE_ASCII);
1771 SIVAL(p,0,0); /* Ensure any padding is null. */
1772 len = PTR_DIFF(p, pdata);
1773 len = (len + 3) & ~3;
1778 case SMB_FIND_FILE_DIRECTORY_INFO:
1779 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1781 SIVAL(p,0,reskey); p += 4;
1782 put_long_date_timespec(p,create_date_ts); p += 8;
1783 put_long_date_timespec(p,adate_ts); p += 8;
1784 put_long_date_timespec(p,mdate_ts); p += 8;
1785 put_long_date_timespec(p,mdate_ts); p += 8;
1786 SOFF_T(p,0,file_size); p += 8;
1787 SOFF_T(p,0,allocation_size); p += 8;
1788 SIVAL(p,0,nt_extmode); p += 4;
1789 len = srvstr_push(base_data, flags2,
1790 p + 4, fname, PTR_DIFF(end_data, p+4),
1791 STR_TERMINATE_ASCII);
1794 SIVAL(p,0,0); /* Ensure any padding is null. */
1795 len = PTR_DIFF(p, pdata);
1796 len = (len + 3) & ~3;
1801 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1802 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1804 SIVAL(p,0,reskey); p += 4;
1805 put_long_date_timespec(p,create_date_ts); p += 8;
1806 put_long_date_timespec(p,adate_ts); p += 8;
1807 put_long_date_timespec(p,mdate_ts); p += 8;
1808 put_long_date_timespec(p,mdate_ts); p += 8;
1809 SOFF_T(p,0,file_size); p += 8;
1810 SOFF_T(p,0,allocation_size); p += 8;
1811 SIVAL(p,0,nt_extmode); p += 4;
1812 q = p; p += 4; /* q is placeholder for name length. */
1814 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1815 SIVAL(p,0,ea_size); /* Extended attributes */
1818 len = srvstr_push(base_data, flags2, p,
1819 fname, PTR_DIFF(end_data, p),
1820 STR_TERMINATE_ASCII);
1824 SIVAL(p,0,0); /* Ensure any padding is null. */
1825 len = PTR_DIFF(p, pdata);
1826 len = (len + 3) & ~3;
1831 case SMB_FIND_FILE_NAMES_INFO:
1832 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1834 SIVAL(p,0,reskey); p += 4;
1836 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1837 acl on a dir (tridge) */
1838 len = srvstr_push(base_data, flags2, p,
1839 fname, PTR_DIFF(end_data, p),
1840 STR_TERMINATE_ASCII);
1843 SIVAL(p,0,0); /* Ensure any padding is null. */
1844 len = PTR_DIFF(p, pdata);
1845 len = (len + 3) & ~3;
1850 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1851 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1853 SIVAL(p,0,reskey); p += 4;
1854 put_long_date_timespec(p,create_date_ts); p += 8;
1855 put_long_date_timespec(p,adate_ts); p += 8;
1856 put_long_date_timespec(p,mdate_ts); p += 8;
1857 put_long_date_timespec(p,mdate_ts); p += 8;
1858 SOFF_T(p,0,file_size); p += 8;
1859 SOFF_T(p,0,allocation_size); p += 8;
1860 SIVAL(p,0,nt_extmode); p += 4;
1861 q = p; p += 4; /* q is placeholder for name length. */
1863 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1864 SIVAL(p,0,ea_size); /* Extended attributes */
1867 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1868 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1869 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1870 len = srvstr_push(base_data, flags2, p,
1871 fname, PTR_DIFF(end_data, p),
1872 STR_TERMINATE_ASCII);
1875 SIVAL(p,0,0); /* Ensure any padding is null. */
1876 len = PTR_DIFF(p, pdata);
1877 len = (len + 3) & ~3;
1882 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1883 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1884 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1886 SIVAL(p,0,reskey); p += 4;
1887 put_long_date_timespec(p,create_date_ts); p += 8;
1888 put_long_date_timespec(p,adate_ts); p += 8;
1889 put_long_date_timespec(p,mdate_ts); p += 8;
1890 put_long_date_timespec(p,mdate_ts); p += 8;
1891 SOFF_T(p,0,file_size); p += 8;
1892 SOFF_T(p,0,allocation_size); p += 8;
1893 SIVAL(p,0,nt_extmode); p += 4;
1894 q = p; p += 4; /* q is placeholder for name length */
1896 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1897 SIVAL(p,0,ea_size); /* Extended attributes */
1900 /* Clear the short name buffer. This is
1901 * IMPORTANT as not doing so will trigger
1902 * a Win2k client bug. JRA.
1904 if (!was_8_3 && check_mangled_names) {
1905 if (!name_to_8_3(fname,mangled_name,True,
1907 /* Error - mangle failed ! */
1908 memset(mangled_name,'\0',12);
1910 mangled_name[12] = 0;
1911 len = srvstr_push(base_data, flags2,
1912 p+2, mangled_name, 24,
1913 STR_UPPER|STR_UNICODE);
1916 memset(p + 2 + len,'\0',24 - len);
1923 SSVAL(p,0,0); p += 2; /* Reserved ? */
1924 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1925 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1926 len = srvstr_push(base_data, flags2, p,
1927 fname, PTR_DIFF(end_data, p),
1928 STR_TERMINATE_ASCII);
1931 SIVAL(p,0,0); /* Ensure any padding is null. */
1932 len = PTR_DIFF(p, pdata);
1933 len = (len + 3) & ~3;
1938 /* CIFS UNIX Extension. */
1940 case SMB_FIND_FILE_UNIX:
1941 case SMB_FIND_FILE_UNIX_INFO2:
1943 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1945 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1947 if (info_level == SMB_FIND_FILE_UNIX) {
1948 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1949 p = store_file_unix_basic(conn, p,
1951 len = srvstr_push(base_data, flags2, p,
1952 fname, PTR_DIFF(end_data, p),
1955 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1956 p = store_file_unix_basic_info2(conn, p,
1960 len = srvstr_push(base_data, flags2, p, fname,
1961 PTR_DIFF(end_data, p), 0);
1962 SIVAL(nameptr, 0, len);
1966 SIVAL(p,0,0); /* Ensure any padding is null. */
1968 len = PTR_DIFF(p, pdata);
1969 len = (len + 3) & ~3;
1970 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1972 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1982 if (PTR_DIFF(p,pdata) > space_remaining) {
1983 /* Move the dirptr back to prev_dirpos */
1984 dptr_SeekDir(conn->dirptr, prev_dirpos);
1985 *out_of_space = True;
1986 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1987 return False; /* Not finished - just out of space */
1990 /* Setup the last entry pointer, as an offset from base_data */
1991 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1992 /* Advance the data pointer to the next slot */
1998 /****************************************************************************
1999 Reply to a TRANS2_FINDFIRST.
2000 ****************************************************************************/
2002 static void call_trans2findfirst(connection_struct *conn,
2003 struct smb_request *req,
2004 char **pparams, int total_params,
2005 char **ppdata, int total_data,
2006 unsigned int max_data_bytes)
2008 /* We must be careful here that we don't return more than the
2009 allowed number of data bytes. If this means returning fewer than
2010 maxentries then so be it. We assume that the redirector has
2011 enough room for the fixed number of parameter bytes it has
2013 struct smb_filename *smb_dname = NULL;
2014 char *params = *pparams;
2015 char *pdata = *ppdata;
2019 uint16 findfirst_flags;
2020 bool close_after_first;
2022 bool requires_resume_key;
2024 char *directory = NULL;
2027 int last_entry_off=0;
2031 bool finished = False;
2032 bool dont_descend = False;
2033 bool out_of_space = False;
2034 int space_remaining;
2035 bool mask_contains_wcard = False;
2036 struct ea_list *ea_list = NULL;
2037 NTSTATUS ntstatus = NT_STATUS_OK;
2038 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2039 TALLOC_CTX *ctx = talloc_tos();
2041 if (total_params < 13) {
2042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2046 dirtype = SVAL(params,0);
2047 maxentries = SVAL(params,2);
2048 findfirst_flags = SVAL(params,4);
2049 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2050 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2051 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2052 info_level = SVAL(params,6);
2054 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2055 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2056 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2057 info_level, max_data_bytes));
2060 /* W2K3 seems to treat zero as 1. */
2064 switch (info_level) {
2065 case SMB_FIND_INFO_STANDARD:
2066 case SMB_FIND_EA_SIZE:
2067 case SMB_FIND_EA_LIST:
2068 case SMB_FIND_FILE_DIRECTORY_INFO:
2069 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2070 case SMB_FIND_FILE_NAMES_INFO:
2071 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2072 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2073 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2075 case SMB_FIND_FILE_UNIX:
2076 case SMB_FIND_FILE_UNIX_INFO2:
2077 /* Always use filesystem for UNIX mtime query. */
2078 ask_sharemode = false;
2079 if (!lp_unix_extensions()) {
2080 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2085 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2089 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2090 params+12, total_params - 12,
2091 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2092 if (!NT_STATUS_IS_OK(ntstatus)) {
2093 reply_nterror(req, ntstatus);
2097 ntstatus = resolve_dfspath_wcard(ctx, conn,
2098 req->flags2 & FLAGS2_DFS_PATHNAMES,
2101 &mask_contains_wcard);
2102 if (!NT_STATUS_IS_OK(ntstatus)) {
2103 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2104 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2105 ERRSRV, ERRbadpath);
2108 reply_nterror(req, ntstatus);
2112 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2113 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2114 if (!NT_STATUS_IS_OK(ntstatus)) {
2115 reply_nterror(req, ntstatus);
2119 mask = smb_dname->original_lcomp;
2121 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2122 TALLOC_FREE(smb_dname);
2123 if (!NT_STATUS_IS_OK(ntstatus)) {
2124 reply_nterror(req, ntstatus);
2128 ntstatus = check_name(conn, directory);
2129 if (!NT_STATUS_IS_OK(ntstatus)) {
2130 reply_nterror(req, ntstatus);
2134 p = strrchr_m(directory,'/');
2136 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2137 if((directory[0] == '.') && (directory[1] == '\0')) {
2138 mask = talloc_strdup(ctx,"*");
2140 reply_nterror(req, NT_STATUS_NO_MEMORY);
2143 mask_contains_wcard = True;
2145 directory = talloc_strdup(talloc_tos(), "./");
2147 reply_nterror(req, NT_STATUS_NO_MEMORY);
2154 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2156 if (info_level == SMB_FIND_EA_LIST) {
2159 if (total_data < 4) {
2160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2164 ea_size = IVAL(pdata,0);
2165 if (ea_size != total_data) {
2166 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2167 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2172 if (!lp_ea_support(SNUM(conn))) {
2173 reply_doserror(req, ERRDOS, ERReasnotsupported);
2177 /* Pull out the list of names. */
2178 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2185 *ppdata = (char *)SMB_REALLOC(
2186 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2187 if(*ppdata == NULL ) {
2188 reply_nterror(req, NT_STATUS_NO_MEMORY);
2192 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2194 /* Realloc the params space */
2195 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2196 if (*pparams == NULL) {
2197 reply_nterror(req, NT_STATUS_NO_MEMORY);
2202 /* Save the wildcard match and attribs we are using on this directory -
2203 needed as lanman2 assumes these are being saved between calls */
2205 ntstatus = dptr_create(conn,
2211 mask_contains_wcard,
2215 if (!NT_STATUS_IS_OK(ntstatus)) {
2216 reply_nterror(req, ntstatus);
2220 dptr_num = dptr_dnum(conn->dirptr);
2221 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2223 /* Initialize per TRANS2_FIND_FIRST operation data */
2224 dptr_init_search_op(conn->dirptr);
2226 /* We don't need to check for VOL here as this is returned by
2227 a different TRANS2 call. */
2229 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2230 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2231 dont_descend = True;
2234 space_remaining = max_data_bytes;
2235 out_of_space = False;
2237 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2238 bool got_exact_match = False;
2240 /* this is a heuristic to avoid seeking the dirptr except when
2241 absolutely necessary. It allows for a filename of about 40 chars */
2242 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2243 out_of_space = True;
2246 finished = !get_lanman2_dir_entry(ctx,
2249 mask,dirtype,info_level,
2250 requires_resume_key,dont_descend,
2253 space_remaining, &out_of_space,
2255 &last_entry_off, ea_list);
2258 if (finished && out_of_space)
2261 if (!finished && !out_of_space)
2265 * As an optimisation if we know we aren't looking
2266 * for a wildcard name (ie. the name matches the wildcard exactly)
2267 * then we can finish on any (first) match.
2268 * This speeds up large directory searches. JRA.
2274 /* Ensure space_remaining never goes -ve. */
2275 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2276 space_remaining = 0;
2277 out_of_space = true;
2279 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2283 /* Check if we can close the dirptr */
2284 if(close_after_first || (finished && close_if_end)) {
2285 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2286 dptr_close(&dptr_num);
2290 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2291 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2292 * the protocol level is less than NT1. Tested with smbclient. JRA.
2293 * This should fix the OS/2 client bug #2335.
2296 if(numentries == 0) {
2297 dptr_close(&dptr_num);
2298 if (Protocol < PROTOCOL_NT1) {
2299 reply_doserror(req, ERRDOS, ERRnofiles);
2302 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2303 ERRDOS, ERRbadfile);
2308 /* At this point pdata points to numentries directory entries. */
2310 /* Set up the return parameter block */
2311 SSVAL(params,0,dptr_num);
2312 SSVAL(params,2,numentries);
2313 SSVAL(params,4,finished);
2314 SSVAL(params,6,0); /* Never an EA error */
2315 SSVAL(params,8,last_entry_off);
2317 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2320 if ((! *directory) && dptr_path(dptr_num)) {
2321 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2323 reply_nterror(req, NT_STATUS_NO_MEMORY);
2327 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2328 smb_fn_name(req->cmd),
2329 mask, directory, dirtype, numentries ) );
2332 * Force a name mangle here to ensure that the
2333 * mask as an 8.3 name is top of the mangled cache.
2334 * The reasons for this are subtle. Don't remove
2335 * this code unless you know what you are doing
2336 * (see PR#13758). JRA.
2339 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2340 char mangled_name[13];
2341 name_to_8_3(mask, mangled_name, True, conn->params);
2347 /****************************************************************************
2348 Reply to a TRANS2_FINDNEXT.
2349 ****************************************************************************/
2351 static void call_trans2findnext(connection_struct *conn,
2352 struct smb_request *req,
2353 char **pparams, int total_params,
2354 char **ppdata, int total_data,
2355 unsigned int max_data_bytes)
2357 /* We must be careful here that we don't return more than the
2358 allowed number of data bytes. If this means returning fewer than
2359 maxentries then so be it. We assume that the redirector has
2360 enough room for the fixed number of parameter bytes it has
2362 char *params = *pparams;
2363 char *pdata = *ppdata;
2369 uint16 findnext_flags;
2370 bool close_after_request;
2372 bool requires_resume_key;
2374 bool mask_contains_wcard = False;
2375 char *resume_name = NULL;
2376 const char *mask = NULL;
2377 const char *directory = NULL;
2381 int i, last_entry_off=0;
2382 bool finished = False;
2383 bool dont_descend = False;
2384 bool out_of_space = False;
2385 int space_remaining;
2386 struct ea_list *ea_list = NULL;
2387 NTSTATUS ntstatus = NT_STATUS_OK;
2388 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2389 TALLOC_CTX *ctx = talloc_tos();
2391 if (total_params < 13) {
2392 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2396 dptr_num = SVAL(params,0);
2397 maxentries = SVAL(params,2);
2398 info_level = SVAL(params,4);
2399 resume_key = IVAL(params,6);
2400 findnext_flags = SVAL(params,10);
2401 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2402 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2403 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2404 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2406 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2408 total_params - 12, STR_TERMINATE, &ntstatus,
2409 &mask_contains_wcard);
2410 if (!NT_STATUS_IS_OK(ntstatus)) {
2411 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2412 complain (it thinks we're asking for the directory above the shared
2413 path or an invalid name). Catch this as the resume name is only compared, never used in
2414 a file access. JRA. */
2415 srvstr_pull_talloc(ctx, params, req->flags2,
2416 &resume_name, params+12,
2420 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2421 reply_nterror(req, ntstatus);
2426 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2427 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2428 resume_key = %d resume name = %s continue=%d level = %d\n",
2429 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2430 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2433 /* W2K3 seems to treat zero as 1. */
2437 switch (info_level) {
2438 case SMB_FIND_INFO_STANDARD:
2439 case SMB_FIND_EA_SIZE:
2440 case SMB_FIND_EA_LIST:
2441 case SMB_FIND_FILE_DIRECTORY_INFO:
2442 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2443 case SMB_FIND_FILE_NAMES_INFO:
2444 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2445 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2446 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2448 case SMB_FIND_FILE_UNIX:
2449 case SMB_FIND_FILE_UNIX_INFO2:
2450 /* Always use filesystem for UNIX mtime query. */
2451 ask_sharemode = false;
2452 if (!lp_unix_extensions()) {
2453 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2458 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2462 if (info_level == SMB_FIND_EA_LIST) {
2465 if (total_data < 4) {
2466 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2470 ea_size = IVAL(pdata,0);
2471 if (ea_size != total_data) {
2472 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2473 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2474 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2478 if (!lp_ea_support(SNUM(conn))) {
2479 reply_doserror(req, ERRDOS, ERReasnotsupported);
2483 /* Pull out the list of names. */
2484 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2491 *ppdata = (char *)SMB_REALLOC(
2492 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2493 if(*ppdata == NULL) {
2494 reply_nterror(req, NT_STATUS_NO_MEMORY);
2499 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2501 /* Realloc the params space */
2502 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2503 if(*pparams == NULL ) {
2504 reply_nterror(req, NT_STATUS_NO_MEMORY);
2510 /* Check that the dptr is valid */
2511 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2512 reply_doserror(req, ERRDOS, ERRnofiles);
2516 string_set(&conn->dirpath,dptr_path(dptr_num));
2518 /* Get the wildcard mask from the dptr */
2519 if((p = dptr_wcard(dptr_num))== NULL) {
2520 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2521 reply_doserror(req, ERRDOS, ERRnofiles);
2526 directory = conn->dirpath;
2528 /* Get the attr mask from the dptr */
2529 dirtype = dptr_attr(dptr_num);
2531 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2532 dptr_num, mask, dirtype,
2534 dptr_TellDir(conn->dirptr)));
2536 /* Initialize per TRANS2_FIND_NEXT operation data */
2537 dptr_init_search_op(conn->dirptr);
2539 /* We don't need to check for VOL here as this is returned by
2540 a different TRANS2 call. */
2542 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2543 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2544 dont_descend = True;
2547 space_remaining = max_data_bytes;
2548 out_of_space = False;
2551 * Seek to the correct position. We no longer use the resume key but
2552 * depend on the last file name instead.
2555 if(*resume_name && !continue_bit) {
2558 long current_pos = 0;
2560 * Remember, name_to_8_3 is called by
2561 * get_lanman2_dir_entry(), so the resume name
2562 * could be mangled. Ensure we check the unmangled name.
2565 if (mangle_is_mangled(resume_name, conn->params)) {
2566 char *new_resume_name = NULL;
2567 mangle_lookup_name_from_8_3(ctx,
2571 if (new_resume_name) {
2572 resume_name = new_resume_name;
2577 * Fix for NT redirector problem triggered by resume key indexes
2578 * changing between directory scans. We now return a resume key of 0
2579 * and instead look for the filename to continue from (also given
2580 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2581 * findfirst/findnext (as is usual) then the directory pointer
2582 * should already be at the correct place.
2585 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2586 } /* end if resume_name && !continue_bit */
2588 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2589 bool got_exact_match = False;
2591 /* this is a heuristic to avoid seeking the dirptr except when
2592 absolutely necessary. It allows for a filename of about 40 chars */
2593 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2594 out_of_space = True;
2597 finished = !get_lanman2_dir_entry(ctx,
2600 mask,dirtype,info_level,
2601 requires_resume_key,dont_descend,
2604 space_remaining, &out_of_space,
2606 &last_entry_off, ea_list);
2609 if (finished && out_of_space)
2612 if (!finished && !out_of_space)
2616 * As an optimisation if we know we aren't looking
2617 * for a wildcard name (ie. the name matches the wildcard exactly)
2618 * then we can finish on any (first) match.
2619 * This speeds up large directory searches. JRA.
2625 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2628 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2629 smb_fn_name(req->cmd),
2630 mask, directory, dirtype, numentries ) );
2632 /* Check if we can close the dirptr */
2633 if(close_after_request || (finished && close_if_end)) {
2634 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2635 dptr_close(&dptr_num); /* This frees up the saved mask */
2638 /* Set up the return parameter block */
2639 SSVAL(params,0,numentries);
2640 SSVAL(params,2,finished);
2641 SSVAL(params,4,0); /* Never an EA error */
2642 SSVAL(params,6,last_entry_off);
2644 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2650 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2652 E_md4hash(lp_servicename(SNUM(conn)),objid);
2656 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2658 SMB_ASSERT(extended_info != NULL);
2660 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2661 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2662 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2663 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2664 #ifdef SAMBA_VERSION_REVISION
2665 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2667 extended_info->samba_subversion = 0;
2668 #ifdef SAMBA_VERSION_RC_RELEASE
2669 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2671 #ifdef SAMBA_VERSION_PRE_RELEASE
2672 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2675 #ifdef SAMBA_VERSION_VENDOR_PATCH
2676 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2678 extended_info->samba_gitcommitdate = 0;
2679 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2680 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2683 memset(extended_info->samba_version_string, 0,
2684 sizeof(extended_info->samba_version_string));
2686 snprintf (extended_info->samba_version_string,
2687 sizeof(extended_info->samba_version_string),
2688 "%s", samba_version_string());
2691 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2692 TALLOC_CTX *mem_ctx,
2693 uint16_t info_level,
2696 unsigned int max_data_bytes,
2700 char *pdata, *end_data;
2701 int data_len = 0, len;
2702 const char *vname = volume_label(SNUM(conn));
2703 int snum = SNUM(conn);
2704 char *fstype = lp_fstype(SNUM(conn));
2705 uint32 additional_flags = 0;
2708 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2709 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2710 "info level (0x%x) on IPC$.\n",
2711 (unsigned int)info_level));
2712 return NT_STATUS_ACCESS_DENIED;
2716 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2718 *ppdata = (char *)SMB_REALLOC(
2719 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2720 if (*ppdata == NULL) {
2721 return NT_STATUS_NO_MEMORY;
2725 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2726 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2728 switch (info_level) {
2729 case SMB_INFO_ALLOCATION:
2731 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2733 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2734 return map_nt_error_from_unix(errno);
2737 block_size = lp_block_size(snum);
2738 if (bsize < block_size) {
2739 uint64_t factor = block_size/bsize;
2744 if (bsize > block_size) {
2745 uint64_t factor = bsize/block_size;
2750 bytes_per_sector = 512;
2751 sectors_per_unit = bsize/bytes_per_sector;
2753 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2754 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2755 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2757 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2758 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2759 SIVAL(pdata,l1_cUnit,dsize);
2760 SIVAL(pdata,l1_cUnitAvail,dfree);
2761 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2765 case SMB_INFO_VOLUME:
2766 /* Return volume name */
2768 * Add volume serial number - hash of a combination of
2769 * the called hostname and the service name.
2771 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2773 * Win2k3 and previous mess this up by sending a name length
2774 * one byte short. I believe only older clients (OS/2 Win9x) use
2775 * this call so try fixing this by adding a terminating null to
2776 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2780 pdata+l2_vol_szVolLabel, vname,
2781 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2782 STR_NOALIGN|STR_TERMINATE);
2783 SCVAL(pdata,l2_vol_cch,len);
2784 data_len = l2_vol_szVolLabel + len;
2785 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2786 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2790 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2791 case SMB_FS_ATTRIBUTE_INFORMATION:
2793 additional_flags = 0;
2794 #if defined(HAVE_SYS_QUOTAS)
2795 additional_flags |= FILE_VOLUME_QUOTAS;
2798 if(lp_nt_acl_support(SNUM(conn))) {
2799 additional_flags |= FILE_PERSISTENT_ACLS;
2802 /* Capabilities are filled in at connection time through STATVFS call */
2803 additional_flags |= conn->fs_capabilities;
2805 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2806 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2807 additional_flags); /* FS ATTRIBUTES */
2809 SIVAL(pdata,4,255); /* Max filename component length */
2810 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2811 and will think we can't do long filenames */
2812 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2813 PTR_DIFF(end_data, pdata+12),
2816 data_len = 12 + len;
2819 case SMB_QUERY_FS_LABEL_INFO:
2820 case SMB_FS_LABEL_INFORMATION:
2821 len = srvstr_push(pdata, flags2, pdata+4, vname,
2822 PTR_DIFF(end_data, pdata+4), 0);
2827 case SMB_QUERY_FS_VOLUME_INFO:
2828 case SMB_FS_VOLUME_INFORMATION:
2831 * Add volume serial number - hash of a combination of
2832 * the called hostname and the service name.
2834 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2835 (str_checksum(get_local_machine_name())<<16));
2837 /* Max label len is 32 characters. */
2838 len = srvstr_push(pdata, flags2, pdata+18, vname,
2839 PTR_DIFF(end_data, pdata+18),
2841 SIVAL(pdata,12,len);
2844 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2845 (int)strlen(vname),vname, lp_servicename(snum)));
2848 case SMB_QUERY_FS_SIZE_INFO:
2849 case SMB_FS_SIZE_INFORMATION:
2851 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2853 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2854 return map_nt_error_from_unix(errno);
2856 block_size = lp_block_size(snum);
2857 if (bsize < block_size) {
2858 uint64_t factor = block_size/bsize;
2863 if (bsize > block_size) {
2864 uint64_t factor = bsize/block_size;
2869 bytes_per_sector = 512;
2870 sectors_per_unit = bsize/bytes_per_sector;
2871 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2872 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2873 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2874 SBIG_UINT(pdata,0,dsize);
2875 SBIG_UINT(pdata,8,dfree);
2876 SIVAL(pdata,16,sectors_per_unit);
2877 SIVAL(pdata,20,bytes_per_sector);
2881 case SMB_FS_FULL_SIZE_INFORMATION:
2883 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2885 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2886 return map_nt_error_from_unix(errno);
2888 block_size = lp_block_size(snum);
2889 if (bsize < block_size) {
2890 uint64_t factor = block_size/bsize;
2895 if (bsize > block_size) {
2896 uint64_t factor = bsize/block_size;
2901 bytes_per_sector = 512;
2902 sectors_per_unit = bsize/bytes_per_sector;
2903 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2904 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2905 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2906 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2907 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2908 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2909 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2910 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2914 case SMB_QUERY_FS_DEVICE_INFO:
2915 case SMB_FS_DEVICE_INFORMATION:
2917 SIVAL(pdata,0,0); /* dev type */
2918 SIVAL(pdata,4,0); /* characteristics */
2921 #ifdef HAVE_SYS_QUOTAS
2922 case SMB_FS_QUOTA_INFORMATION:
2924 * what we have to send --metze:
2926 * Unknown1: 24 NULL bytes
2927 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2928 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2929 * Quota Flags: 2 byte :
2930 * Unknown3: 6 NULL bytes
2934 * details for Quota Flags:
2936 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2937 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2938 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2939 * 0x0001 Enable Quotas: enable quota for this fs
2943 /* we need to fake up a fsp here,
2944 * because its not send in this call
2947 SMB_NTQUOTA_STRUCT quotas;
2950 ZERO_STRUCT(quotas);
2956 if (conn->server_info->utok.uid != sec_initial_uid()) {
2957 DEBUG(0,("set_user_quota: access_denied "
2958 "service [%s] user [%s]\n",
2959 lp_servicename(SNUM(conn)),
2960 conn->server_info->unix_name));
2961 return NT_STATUS_ACCESS_DENIED;
2964 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2965 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2966 return map_nt_error_from_unix(errno);
2971 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2972 lp_servicename(SNUM(conn))));
2974 /* Unknown1 24 NULL bytes*/
2975 SBIG_UINT(pdata,0,(uint64_t)0);
2976 SBIG_UINT(pdata,8,(uint64_t)0);
2977 SBIG_UINT(pdata,16,(uint64_t)0);
2979 /* Default Soft Quota 8 bytes */
2980 SBIG_UINT(pdata,24,quotas.softlim);
2982 /* Default Hard Quota 8 bytes */
2983 SBIG_UINT(pdata,32,quotas.hardlim);
2985 /* Quota flag 2 bytes */
2986 SSVAL(pdata,40,quotas.qflags);
2988 /* Unknown3 6 NULL bytes */
2994 #endif /* HAVE_SYS_QUOTAS */
2995 case SMB_FS_OBJECTID_INFORMATION:
2997 unsigned char objid[16];
2998 struct smb_extended_info extended_info;
2999 memcpy(pdata,create_volume_objectid(conn, objid),16);
3000 samba_extended_info_version (&extended_info);
3001 SIVAL(pdata,16,extended_info.samba_magic);
3002 SIVAL(pdata,20,extended_info.samba_version);
3003 SIVAL(pdata,24,extended_info.samba_subversion);
3004 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3005 memcpy(pdata+36,extended_info.samba_version_string,28);
3011 * Query the version and capabilities of the CIFS UNIX extensions
3015 case SMB_QUERY_CIFS_UNIX_INFO:
3017 bool large_write = lp_min_receive_file_size() &&
3018 !srv_is_signing_active(smbd_server_conn);
3019 bool large_read = !srv_is_signing_active(smbd_server_conn);
3020 int encrypt_caps = 0;
3022 if (!lp_unix_extensions()) {
3023 return NT_STATUS_INVALID_LEVEL;
3026 switch (conn->encrypt_level) {
3032 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3035 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3036 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3037 large_write = false;
3043 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3044 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3046 /* We have POSIX ACLs, pathname, encryption,
3047 * large read/write, and locking capability. */
3049 SBIG_UINT(pdata,4,((uint64_t)(
3050 CIFS_UNIX_POSIX_ACLS_CAP|
3051 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3052 CIFS_UNIX_FCNTL_LOCKS_CAP|
3053 CIFS_UNIX_EXTATTR_CAP|
3054 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3056 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3058 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3062 case SMB_QUERY_POSIX_FS_INFO:
3065 vfs_statvfs_struct svfs;
3067 if (!lp_unix_extensions()) {
3068 return NT_STATUS_INVALID_LEVEL;
3071 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3075 SIVAL(pdata,0,svfs.OptimalTransferSize);
3076 SIVAL(pdata,4,svfs.BlockSize);
3077 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3078 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3079 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3080 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3081 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3082 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3083 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3085 } else if (rc == EOPNOTSUPP) {
3086 return NT_STATUS_INVALID_LEVEL;
3087 #endif /* EOPNOTSUPP */
3089 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3090 return NT_STATUS_DOS(ERRSRV, ERRerror);
3095 case SMB_QUERY_POSIX_WHOAMI:
3101 if (!lp_unix_extensions()) {
3102 return NT_STATUS_INVALID_LEVEL;
3105 if (max_data_bytes < 40) {
3106 return NT_STATUS_BUFFER_TOO_SMALL;
3109 /* We ARE guest if global_sid_Builtin_Guests is
3110 * in our list of SIDs.
3112 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3113 conn->server_info->ptok)) {
3114 flags |= SMB_WHOAMI_GUEST;
3117 /* We are NOT guest if global_sid_Authenticated_Users
3118 * is in our list of SIDs.
3120 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3121 conn->server_info->ptok)) {
3122 flags &= ~SMB_WHOAMI_GUEST;
3125 /* NOTE: 8 bytes for UID/GID, irrespective of native
3126 * platform size. This matches
3127 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3129 data_len = 4 /* flags */
3136 + 4 /* pad/reserved */
3137 + (conn->server_info->utok.ngroups * 8)
3139 + (conn->server_info->ptok->num_sids *
3143 SIVAL(pdata, 0, flags);
3144 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3146 (uint64_t)conn->server_info->utok.uid);
3147 SBIG_UINT(pdata, 16,
3148 (uint64_t)conn->server_info->utok.gid);
3151 if (data_len >= max_data_bytes) {
3152 /* Potential overflow, skip the GIDs and SIDs. */
3154 SIVAL(pdata, 24, 0); /* num_groups */
3155 SIVAL(pdata, 28, 0); /* num_sids */
3156 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3157 SIVAL(pdata, 36, 0); /* reserved */
3163 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3164 SIVAL(pdata, 28, conn->server_info->num_sids);
3166 /* We walk the SID list twice, but this call is fairly
3167 * infrequent, and I don't expect that it's performance
3168 * sensitive -- jpeach
3170 for (i = 0, sid_bytes = 0;
3171 i < conn->server_info->ptok->num_sids; ++i) {
3172 sid_bytes += ndr_size_dom_sid(
3173 &conn->server_info->ptok->user_sids[i],
3178 /* SID list byte count */
3179 SIVAL(pdata, 32, sid_bytes);
3181 /* 4 bytes pad/reserved - must be zero */
3182 SIVAL(pdata, 36, 0);
3186 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3187 SBIG_UINT(pdata, data_len,
3188 (uint64_t)conn->server_info->utok.groups[i]);
3194 i < conn->server_info->ptok->num_sids; ++i) {
3195 int sid_len = ndr_size_dom_sid(
3196 &conn->server_info->ptok->user_sids[i],
3200 sid_linearize(pdata + data_len, sid_len,
3201 &conn->server_info->ptok->user_sids[i]);
3202 data_len += sid_len;
3208 case SMB_MAC_QUERY_FS_INFO:
3210 * Thursby MAC extension... ONLY on NTFS filesystems
3211 * once we do streams then we don't need this
3213 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3215 SIVAL(pdata,84,0x100); /* Don't support mac... */
3220 return NT_STATUS_INVALID_LEVEL;
3223 *ret_data_len = data_len;
3224 return NT_STATUS_OK;
3227 /****************************************************************************
3228 Reply to a TRANS2_QFSINFO (query filesystem info).
3229 ****************************************************************************/
3231 static void call_trans2qfsinfo(connection_struct *conn,
3232 struct smb_request *req,
3233 char **pparams, int total_params,
3234 char **ppdata, int total_data,
3235 unsigned int max_data_bytes)
3237 char *params = *pparams;
3238 uint16_t info_level;
3243 if (total_params < 2) {
3244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3248 info_level = SVAL(params,0);
3250 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3251 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3252 DEBUG(0,("call_trans2qfsinfo: encryption required "
3253 "and info level 0x%x sent.\n",
3254 (unsigned int)info_level));
3255 exit_server_cleanly("encryption required "
3261 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3263 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
3264 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
3265 reply_doserror(req, ERRSRV, ERRinvdevice);
3269 status = smbd_do_qfsinfo(conn, req,
3274 if (!NT_STATUS_IS_OK(status)) {
3275 reply_nterror(req, status);
3279 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3282 DEBUG( 4, ( "%s info_level = %d\n",
3283 smb_fn_name(req->cmd), info_level) );
3288 /****************************************************************************
3289 Reply to a TRANS2_SETFSINFO (set filesystem info).
3290 ****************************************************************************/
3292 static void call_trans2setfsinfo(connection_struct *conn,
3293 struct smb_request *req,
3294 char **pparams, int total_params,
3295 char **ppdata, int total_data,
3296 unsigned int max_data_bytes)
3298 char *pdata = *ppdata;
3299 char *params = *pparams;
3302 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3305 if (total_params < 4) {
3306 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3312 info_level = SVAL(params,2);
3315 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3316 info_level != SMB_SET_CIFS_UNIX_INFO) {
3317 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3318 "info level (0x%x) on IPC$.\n",
3319 (unsigned int)info_level));
3320 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3325 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3326 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3327 DEBUG(0,("call_trans2setfsinfo: encryption required "
3328 "and info level 0x%x sent.\n",
3329 (unsigned int)info_level));
3330 exit_server_cleanly("encryption required "
3336 switch(info_level) {
3337 case SMB_SET_CIFS_UNIX_INFO:
3339 uint16 client_unix_major;
3340 uint16 client_unix_minor;
3341 uint32 client_unix_cap_low;
3342 uint32 client_unix_cap_high;
3344 if (!lp_unix_extensions()) {
3346 NT_STATUS_INVALID_LEVEL);
3350 /* There should be 12 bytes of capabilities set. */
3351 if (total_data < 8) {
3354 NT_STATUS_INVALID_PARAMETER);
3357 client_unix_major = SVAL(pdata,0);
3358 client_unix_minor = SVAL(pdata,2);
3359 client_unix_cap_low = IVAL(pdata,4);
3360 client_unix_cap_high = IVAL(pdata,8);
3361 /* Just print these values for now. */
3362 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3363 cap_low = 0x%x, cap_high = 0x%x\n",
3364 (unsigned int)client_unix_major,
3365 (unsigned int)client_unix_minor,
3366 (unsigned int)client_unix_cap_low,
3367 (unsigned int)client_unix_cap_high ));
3369 /* Here is where we must switch to posix pathname processing... */
3370 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3371 lp_set_posix_pathnames();
3372 mangle_change_to_posix();
3375 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3376 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3377 /* Client that knows how to do posix locks,
3378 * but not posix open/mkdir operations. Set a
3379 * default type for read/write checks. */
3381 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3387 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3390 size_t param_len = 0;
3391 size_t data_len = total_data;
3393 if (!lp_unix_extensions()) {
3396 NT_STATUS_INVALID_LEVEL);
3400 if (lp_smb_encrypt(SNUM(conn)) == false) {
3403 NT_STATUS_NOT_SUPPORTED);
3407 DEBUG( 4,("call_trans2setfsinfo: "
3408 "request transport encryption.\n"));
3410 status = srv_request_encryption_setup(conn,
3411 (unsigned char **)ppdata,
3413 (unsigned char **)pparams,
3416 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3417 !NT_STATUS_IS_OK(status)) {
3418 reply_nterror(req, status);
3422 send_trans2_replies(conn, req,
3429 if (NT_STATUS_IS_OK(status)) {
3430 /* Server-side transport
3431 * encryption is now *on*. */
3432 status = srv_encryption_start(conn);
3433 if (!NT_STATUS_IS_OK(status)) {
3434 exit_server_cleanly(
3435 "Failure in setting "
3436 "up encrypted transport");
3442 case SMB_FS_QUOTA_INFORMATION:
3444 files_struct *fsp = NULL;
3445 SMB_NTQUOTA_STRUCT quotas;
3447 ZERO_STRUCT(quotas);
3450 if ((conn->server_info->utok.uid != sec_initial_uid())
3451 ||!CAN_WRITE(conn)) {
3452 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3453 lp_servicename(SNUM(conn)),
3454 conn->server_info->unix_name));
3455 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3459 /* note: normaly there're 48 bytes,
3460 * but we didn't use the last 6 bytes for now
3463 fsp = file_fsp(req, SVAL(params,0));
3465 if (!check_fsp_ntquota_handle(conn, req,
3467 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3469 req, NT_STATUS_INVALID_HANDLE);
3473 if (total_data < 42) {
3474 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3478 NT_STATUS_INVALID_PARAMETER);
3482 /* unknown_1 24 NULL bytes in pdata*/
3484 /* the soft quotas 8 bytes (uint64_t)*/
3485 quotas.softlim = (uint64_t)IVAL(pdata,24);
3486 #ifdef LARGE_SMB_OFF_T
3487 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3488 #else /* LARGE_SMB_OFF_T */
3489 if ((IVAL(pdata,28) != 0)&&
3490 ((quotas.softlim != 0xFFFFFFFF)||
3491 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3492 /* more than 32 bits? */
3495 NT_STATUS_INVALID_PARAMETER);
3498 #endif /* LARGE_SMB_OFF_T */
3500 /* the hard quotas 8 bytes (uint64_t)*/
3501 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3502 #ifdef LARGE_SMB_OFF_T
3503 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3504 #else /* LARGE_SMB_OFF_T */
3505 if ((IVAL(pdata,36) != 0)&&
3506 ((quotas.hardlim != 0xFFFFFFFF)||
3507 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3508 /* more than 32 bits? */
3511 NT_STATUS_INVALID_PARAMETER);
3514 #endif /* LARGE_SMB_OFF_T */
3516 /* quota_flags 2 bytes **/
3517 quotas.qflags = SVAL(pdata,40);
3519 /* unknown_2 6 NULL bytes follow*/
3521 /* now set the quotas */
3522 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3523 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3524 reply_nterror(req, map_nt_error_from_unix(errno));
3531 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3533 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3539 * sending this reply works fine,
3540 * but I'm not sure it's the same
3541 * like windows do...
3544 reply_outbuf(req, 10, 0);
3547 #if defined(HAVE_POSIX_ACLS)
3548 /****************************************************************************
3549 Utility function to count the number of entries in a POSIX acl.
3550 ****************************************************************************/
3552 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3554 unsigned int ace_count = 0;
3555 int entry_id = SMB_ACL_FIRST_ENTRY;
3556 SMB_ACL_ENTRY_T entry;
3558 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3560 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3561 entry_id = SMB_ACL_NEXT_ENTRY;
3568 /****************************************************************************
3569 Utility function to marshall a POSIX acl into wire format.
3570 ****************************************************************************/
3572 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3574 int entry_id = SMB_ACL_FIRST_ENTRY;
3575 SMB_ACL_ENTRY_T entry;
3577 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3578 SMB_ACL_TAG_T tagtype;
3579 SMB_ACL_PERMSET_T permset;
3580 unsigned char perms = 0;
3581 unsigned int own_grp;
3584 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3585 entry_id = SMB_ACL_NEXT_ENTRY;
3588 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3589 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3593 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3594 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3598 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3599 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3600 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3602 SCVAL(pdata,1,perms);
3605 case SMB_ACL_USER_OBJ:
3606 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3607 own_grp = (unsigned int)pst->st_ex_uid;
3608 SIVAL(pdata,2,own_grp);
3613 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3615 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3618 own_grp = (unsigned int)*puid;
3619 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3620 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3621 SIVAL(pdata,2,own_grp);
3625 case SMB_ACL_GROUP_OBJ:
3626 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3627 own_grp = (unsigned int)pst->st_ex_gid;
3628 SIVAL(pdata,2,own_grp);
3633 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3635 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3638 own_grp = (unsigned int)*pgid;
3639 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3640 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3641 SIVAL(pdata,2,own_grp);
3646 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3647 SIVAL(pdata,2,0xFFFFFFFF);
3648 SIVAL(pdata,6,0xFFFFFFFF);
3651 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3652 SIVAL(pdata,2,0xFFFFFFFF);
3653 SIVAL(pdata,6,0xFFFFFFFF);
3656 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3659 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3666 /****************************************************************************
3667 Store the FILE_UNIX_BASIC info.
3668 ****************************************************************************/
3670 static char *store_file_unix_basic(connection_struct *conn,
3673 const SMB_STRUCT_STAT *psbuf)
3675 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3676 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3678 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3681 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3684 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3685 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3686 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3689 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3693 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3697 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3700 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3704 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3708 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3711 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3715 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3722 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3723 * the chflags(2) (or equivalent) flags.
3725 * XXX: this really should be behind the VFS interface. To do this, we would
3726 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3727 * Each VFS module could then implement its own mapping as appropriate for the
3728 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3730 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3734 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3738 { UF_IMMUTABLE, EXT_IMMUTABLE },
3742 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3746 { UF_HIDDEN, EXT_HIDDEN },
3749 /* Do not remove. We need to guarantee that this array has at least one
3750 * entry to build on HP-UX.
3756 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3757 uint32 *smb_fflags, uint32 *smb_fmask)
3761 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3762 *smb_fmask |= info2_flags_map[i].smb_fflag;
3763 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3764 *smb_fflags |= info2_flags_map[i].smb_fflag;
3769 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3770 const uint32 smb_fflags,
3771 const uint32 smb_fmask,
3774 uint32 max_fmask = 0;
3777 *stat_fflags = psbuf->st_ex_flags;
3779 /* For each flags requested in smb_fmask, check the state of the
3780 * corresponding flag in smb_fflags and set or clear the matching
3784 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3785 max_fmask |= info2_flags_map[i].smb_fflag;
3786 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3787 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3788 *stat_fflags |= info2_flags_map[i].stat_fflag;
3790 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3795 /* If smb_fmask is asking to set any bits that are not supported by
3796 * our flag mappings, we should fail.
3798 if ((smb_fmask & max_fmask) != smb_fmask) {
3806 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3807 * of file flags and birth (create) time.
3809 static char *store_file_unix_basic_info2(connection_struct *conn,
3812 const SMB_STRUCT_STAT *psbuf)
3814 uint32 file_flags = 0;
3815 uint32 flags_mask = 0;
3817 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3819 /* Create (birth) time 64 bit */
3820 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3823 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3824 SIVAL(pdata, 0, file_flags); /* flags */
3825 SIVAL(pdata, 4, flags_mask); /* mask */
3831 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3832 const struct stream_struct *streams,
3834 unsigned int max_data_bytes,
3835 unsigned int *data_size)
3838 unsigned int ofs = 0;
3840 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3841 unsigned int next_offset;
3843 smb_ucs2_t *namebuf;
3845 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3846 streams[i].name, &namelen) ||
3849 return NT_STATUS_INVALID_PARAMETER;
3853 * name_buf is now null-terminated, we need to marshall as not
3859 SIVAL(data, ofs+4, namelen);
3860 SOFF_T(data, ofs+8, streams[i].size);
3861 SOFF_T(data, ofs+16, streams[i].alloc_size);
3862 memcpy(data+ofs+24, namebuf, namelen);
3863 TALLOC_FREE(namebuf);
3865 next_offset = ofs + 24 + namelen;
3867 if (i == num_streams-1) {
3868 SIVAL(data, ofs, 0);
3871 unsigned int align = ndr_align_size(next_offset, 8);
3873 memset(data+next_offset, 0, align);
3874 next_offset += align;
3876 SIVAL(data, ofs, next_offset - ofs);
3885 return NT_STATUS_OK;
3888 /****************************************************************************
3889 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3890 ****************************************************************************/
3892 static void call_trans2qpipeinfo(connection_struct *conn,
3893 struct smb_request *req,
3894 unsigned int tran_call,
3895 char **pparams, int total_params,
3896 char **ppdata, int total_data,
3897 unsigned int max_data_bytes)
3899 char *params = *pparams;
3900 char *pdata = *ppdata;
3901 unsigned int data_size = 0;
3902 unsigned int param_size = 2;
3907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3911 if (total_params < 4) {
3912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3916 fsp = file_fsp(req, SVAL(params,0));
3917 if (!fsp_is_np(fsp)) {
3918 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3922 info_level = SVAL(params,2);
3924 *pparams = (char *)SMB_REALLOC(*pparams,2);
3925 if (*pparams == NULL) {
3926 reply_nterror(req, NT_STATUS_NO_MEMORY);
3931 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3932 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3933 if (*ppdata == NULL ) {
3934 reply_nterror(req, NT_STATUS_NO_MEMORY);
3939 switch (info_level) {
3940 case SMB_FILE_STANDARD_INFORMATION:
3942 SOFF_T(pdata,0,4096LL);
3949 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3953 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3959 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3960 TALLOC_CTX *mem_ctx,
3961 uint16_t info_level,
3963 const struct smb_filename *smb_fname,
3964 bool delete_pending,
3965 struct timespec write_time_ts,
3967 struct ea_list *ea_list,
3968 int lock_data_count,
3971 unsigned int max_data_bytes,
3973 unsigned int *pdata_size)
3975 char *pdata = *ppdata;
3976 char *dstart, *dend;
3977 unsigned int data_size;
3978 struct timespec create_time_ts, mtime_ts, atime_ts;
3979 time_t create_time, mtime, atime;
3980 SMB_STRUCT_STAT sbuf;
3988 uint64_t file_size = 0;
3990 uint64_t allocation_size = 0;
3991 uint64_t file_index = 0;
3992 uint32_t access_mask = 0;
3994 sbuf = smb_fname->st;
3996 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3997 return NT_STATUS_INVALID_LEVEL;
4000 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
4001 if (!NT_STATUS_IS_OK(status)) {
4005 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4006 fname, fsp ? fsp->fnum : -1, info_level, max_data_bytes));
4009 mode = dos_mode_msdfs(conn, smb_fname);
4011 mode = dos_mode(conn, smb_fname);
4014 mode = FILE_ATTRIBUTE_NORMAL;
4016 nlink = sbuf.st_ex_nlink;
4018 if (nlink && (mode&aDIR)) {
4022 if ((nlink > 0) && delete_pending) {
4026 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4027 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4028 if (*ppdata == NULL) {
4029 return NT_STATUS_NO_MEMORY;
4033 dend = dstart + data_size - 1;
4035 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4036 update_stat_ex_mtime(&sbuf, write_time_ts);
4039 create_time_ts = sbuf.st_ex_btime;
4040 mtime_ts = sbuf.st_ex_mtime;
4041 atime_ts = sbuf.st_ex_atime;
4043 if (lp_dos_filetime_resolution(SNUM(conn))) {
4044 dos_filetime_timespec(&create_time_ts);
4045 dos_filetime_timespec(&mtime_ts);
4046 dos_filetime_timespec(&atime_ts);
4049 create_time = convert_timespec_to_time_t(create_time_ts);
4050 mtime = convert_timespec_to_time_t(mtime_ts);
4051 atime = convert_timespec_to_time_t(atime_ts);
4053 p = strrchr_m(smb_fname->base_name,'/');
4055 base_name = smb_fname->base_name;
4059 /* NT expects the name to be in an exact form of the *full*
4060 filename. See the trans2 torture test */
4061 if (ISDOT(base_name)) {
4062 dos_fname = talloc_strdup(mem_ctx, "\\");
4064 return NT_STATUS_NO_MEMORY;
4067 dos_fname = talloc_asprintf(mem_ctx,
4071 return NT_STATUS_NO_MEMORY;
4073 string_replace(dos_fname, '/', '\\');
4076 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4079 /* Do we have this path open ? */
4081 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4082 fsp1 = file_find_di_first(fileid);
4083 if (fsp1 && fsp1->initial_allocation_size) {
4084 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4088 if (!(mode & aDIR)) {
4089 file_size = get_file_size_stat(&sbuf);
4093 pos = fsp->fh->position_information;
4097 access_mask = fsp->access_mask;
4099 /* GENERIC_EXECUTE mapping from Windows */
4100 access_mask = 0x12019F;
4103 /* This should be an index number - looks like
4106 I think this causes us to fail the IFSKIT
4107 BasicFileInformationTest. -tpot */
4108 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4109 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4111 switch (info_level) {
4112 case SMB_INFO_STANDARD:
4113 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4115 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4116 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4117 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4118 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4119 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4120 SSVAL(pdata,l1_attrFile,mode);
4123 case SMB_INFO_QUERY_EA_SIZE:
4125 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4126 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4128 srv_put_dos_date2(pdata,0,create_time);
4129 srv_put_dos_date2(pdata,4,atime);
4130 srv_put_dos_date2(pdata,8,mtime); /* write time */
4131 SIVAL(pdata,12,(uint32)file_size);
4132 SIVAL(pdata,16,(uint32)allocation_size);
4133 SSVAL(pdata,20,mode);
4134 SIVAL(pdata,22,ea_size);
4138 case SMB_INFO_IS_NAME_VALID:
4139 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4141 /* os/2 needs this ? really ?*/
4142 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4144 /* This is only reached for qpathinfo */
4148 case SMB_INFO_QUERY_EAS_FROM_LIST:
4150 size_t total_ea_len = 0;
4151 struct ea_list *ea_file_list = NULL;
4153 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4155 ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4156 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4158 if (!ea_list || (total_ea_len > data_size)) {
4160 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4164 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4168 case SMB_INFO_QUERY_ALL_EAS:
4170 /* We have data_size bytes to put EA's into. */
4171 size_t total_ea_len = 0;
4173 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4175 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4176 if (!ea_list || (total_ea_len > data_size)) {
4178 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4182 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4186 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4188 /* We have data_size bytes to put EA's into. */
4189 size_t total_ea_len = 0;
4190 struct ea_list *ea_file_list = NULL;
4192 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4194 /*TODO: add filtering and index handling */
4196 ea_file_list = get_ea_list_from_file(mem_ctx,
4200 if (!ea_file_list) {
4201 return NT_STATUS_NO_EAS_ON_FILE;
4204 status = fill_ea_chained_buffer(mem_ctx,
4208 conn, ea_file_list);
4209 if (!NT_STATUS_IS_OK(status)) {
4215 case SMB_FILE_BASIC_INFORMATION:
4216 case SMB_QUERY_FILE_BASIC_INFO:
4218 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4219 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4220 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4222 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4226 put_long_date_timespec(pdata,create_time_ts);
4227 put_long_date_timespec(pdata+8,atime_ts);
4228 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4229 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4230 SIVAL(pdata,32,mode);
4232 DEBUG(5,("SMB_QFBI - "));
4233 DEBUG(5,("create: %s ", ctime(&create_time)));
4234 DEBUG(5,("access: %s ", ctime(&atime)));
4235 DEBUG(5,("write: %s ", ctime(&mtime)));
4236 DEBUG(5,("change: %s ", ctime(&mtime)));
4237 DEBUG(5,("mode: %x\n", mode));
4240 case SMB_FILE_STANDARD_INFORMATION:
4241 case SMB_QUERY_FILE_STANDARD_INFO:
4243 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4245 SOFF_T(pdata,0,allocation_size);
4246 SOFF_T(pdata,8,file_size);
4247 SIVAL(pdata,16,nlink);
4248 SCVAL(pdata,20,delete_pending?1:0);
4249 SCVAL(pdata,21,(mode&aDIR)?1:0);
4250 SSVAL(pdata,22,0); /* Padding. */
4253 case SMB_FILE_EA_INFORMATION:
4254 case SMB_QUERY_FILE_EA_INFO:
4256 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4257 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4259 SIVAL(pdata,0,ea_size);
4263 /* Get the 8.3 name - used if NT SMB was negotiated. */
4264 case SMB_QUERY_FILE_ALT_NAME_INFO:
4265 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4268 char mangled_name[13];
4269 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4270 if (!name_to_8_3(base_name,mangled_name,
4271 True,conn->params)) {
4272 return NT_STATUS_NO_MEMORY;
4274 len = srvstr_push(dstart, flags2,
4275 pdata+4, mangled_name,
4276 PTR_DIFF(dend, pdata+4),
4278 data_size = 4 + len;
4283 case SMB_QUERY_FILE_NAME_INFO:
4287 this must be *exactly* right for ACLs on mapped drives to work
4289 len = srvstr_push(dstart, flags2,
4291 PTR_DIFF(dend, pdata+4),
4293 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4294 data_size = 4 + len;
4299 case SMB_FILE_ALLOCATION_INFORMATION:
4300 case SMB_QUERY_FILE_ALLOCATION_INFO:
4301 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4303 SOFF_T(pdata,0,allocation_size);
4306 case SMB_FILE_END_OF_FILE_INFORMATION:
4307 case SMB_QUERY_FILE_END_OF_FILEINFO:
4308 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4310 SOFF_T(pdata,0,file_size);
4313 case SMB_QUERY_FILE_ALL_INFO:
4314 case SMB_FILE_ALL_INFORMATION:
4317 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4318 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4319 put_long_date_timespec(pdata,create_time_ts);
4320 put_long_date_timespec(pdata+8,atime_ts);
4321 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4322 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4323 SIVAL(pdata,32,mode);
4324 SIVAL(pdata,36,0); /* padding. */
4326 SOFF_T(pdata,0,allocation_size);
4327 SOFF_T(pdata,8,file_size);
4328 SIVAL(pdata,16,nlink);
4329 SCVAL(pdata,20,delete_pending);
4330 SCVAL(pdata,21,(mode&aDIR)?1:0);
4333 SIVAL(pdata,0,ea_size);
4334 pdata += 4; /* EA info */
4335 len = srvstr_push(dstart, flags2,
4337 PTR_DIFF(dend, pdata+4),
4341 data_size = PTR_DIFF(pdata,(*ppdata));
4345 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4348 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4349 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4350 put_long_date_timespec(pdata+0x00,create_time_ts);
4351 put_long_date_timespec(pdata+0x08,atime_ts);
4352 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4353 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4354 SIVAL(pdata, 0x20, mode);
4355 SIVAL(pdata, 0x24, 0); /* padding. */
4356 SBVAL(pdata, 0x28, allocation_size);
4357 SBVAL(pdata, 0x30, file_size);
4358 SIVAL(pdata, 0x38, nlink);
4359 SCVAL(pdata, 0x3C, delete_pending);
4360 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4361 SSVAL(pdata, 0x3E, 0); /* padding */
4362 SBVAL(pdata, 0x40, file_index);
4363 SIVAL(pdata, 0x48, ea_size);
4364 SIVAL(pdata, 0x4C, access_mask);
4365 SBVAL(pdata, 0x50, pos);
4366 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4367 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4371 len = srvstr_push(dstart, flags2,
4373 PTR_DIFF(dend, pdata+4),
4377 data_size = PTR_DIFF(pdata,(*ppdata));
4380 case SMB_FILE_INTERNAL_INFORMATION:
4382 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4383 SBVAL(pdata, 0, file_index);
4387 case SMB_FILE_ACCESS_INFORMATION:
4388 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4389 SIVAL(pdata, 0, access_mask);
4393 case SMB_FILE_NAME_INFORMATION:
4394 /* Pathname with leading '\'. */
4397 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4398 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4399 SIVAL(pdata,0,byte_len);
4400 data_size = 4 + byte_len;
4404 case SMB_FILE_DISPOSITION_INFORMATION:
4405 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4407 SCVAL(pdata,0,delete_pending);
4410 case SMB_FILE_POSITION_INFORMATION:
4411 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4413 SOFF_T(pdata,0,pos);
4416 case SMB_FILE_MODE_INFORMATION:
4417 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4418 SIVAL(pdata,0,mode);
4422 case SMB_FILE_ALIGNMENT_INFORMATION:
4423 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4424 SIVAL(pdata,0,0); /* No alignment needed. */
4429 * NT4 server just returns "invalid query" to this - if we try
4430 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4433 /* The first statement above is false - verified using Thursby
4434 * client against NT4 -- gcolley.
4436 case SMB_QUERY_FILE_STREAM_INFO:
4437 case SMB_FILE_STREAM_INFORMATION: {
4438 unsigned int num_streams;
4439 struct stream_struct *streams;
4441 DEBUG(10,("smbd_do_qfilepathinfo: "
4442 "SMB_FILE_STREAM_INFORMATION\n"));
4444 status = SMB_VFS_STREAMINFO(
4445 conn, fsp, fname, talloc_tos(),
4446 &num_streams, &streams);
4448 if (!NT_STATUS_IS_OK(status)) {
4449 DEBUG(10, ("could not get stream info: %s\n",
4450 nt_errstr(status)));
4454 status = marshall_stream_info(num_streams, streams,
4455 pdata, max_data_bytes,
4458 if (!NT_STATUS_IS_OK(status)) {
4459 DEBUG(10, ("marshall_stream_info failed: %s\n",
4460 nt_errstr(status)));
4464 TALLOC_FREE(streams);
4468 case SMB_QUERY_COMPRESSION_INFO:
4469 case SMB_FILE_COMPRESSION_INFORMATION:
4470 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4471 SOFF_T(pdata,0,file_size);
4472 SIVAL(pdata,8,0); /* ??? */
4473 SIVAL(pdata,12,0); /* ??? */
4477 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4478 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4479 put_long_date_timespec(pdata,create_time_ts);
4480 put_long_date_timespec(pdata+8,atime_ts);
4481 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4482 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4483 SOFF_T(pdata,32,allocation_size);
4484 SOFF_T(pdata,40,file_size);
4485 SIVAL(pdata,48,mode);
4486 SIVAL(pdata,52,0); /* ??? */
4490 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4491 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4492 SIVAL(pdata,0,mode);
4498 * CIFS UNIX Extensions.
4501 case SMB_QUERY_FILE_UNIX_BASIC:
4503 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4504 data_size = PTR_DIFF(pdata,(*ppdata));
4508 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4510 for (i=0; i<100; i++)
4511 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4517 case SMB_QUERY_FILE_UNIX_INFO2:
4519 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4520 data_size = PTR_DIFF(pdata,(*ppdata));
4524 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4526 for (i=0; i<100; i++)
4527 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4533 case SMB_QUERY_FILE_UNIX_LINK:
4536 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4539 return NT_STATUS_NO_MEMORY;
4542 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4544 if(!S_ISLNK(sbuf.st_ex_mode)) {
4545 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4548 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4550 len = SMB_VFS_READLINK(conn,fname,
4553 return map_nt_error_from_unix(errno);
4556 len = srvstr_push(dstart, flags2,
4558 PTR_DIFF(dend, pdata),
4561 data_size = PTR_DIFF(pdata,(*ppdata));
4566 #if defined(HAVE_POSIX_ACLS)
4567 case SMB_QUERY_POSIX_ACL:
4569 SMB_ACL_T file_acl = NULL;
4570 SMB_ACL_T def_acl = NULL;
4571 uint16 num_file_acls = 0;
4572 uint16 num_def_acls = 0;
4574 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4575 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4577 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4580 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4581 DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4583 return NT_STATUS_NOT_IMPLEMENTED;
4586 if (S_ISDIR(sbuf.st_ex_mode)) {
4587 if (fsp && fsp->is_directory) {
4589 SMB_VFS_SYS_ACL_GET_FILE(
4591 fsp->fsp_name->base_name,
4592 SMB_ACL_TYPE_DEFAULT);
4594 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4596 def_acl = free_empty_sys_acl(conn, def_acl);
4599 num_file_acls = count_acl_entries(conn, file_acl);
4600 num_def_acls = count_acl_entries(conn, def_acl);
4602 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4603 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4605 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4606 SMB_POSIX_ACL_HEADER_SIZE) ));
4608 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4611 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4613 return NT_STATUS_BUFFER_TOO_SMALL;
4616 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4617 SSVAL(pdata,2,num_file_acls);
4618 SSVAL(pdata,4,num_def_acls);
4619 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4621 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4624 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4626 return NT_STATUS_INTERNAL_ERROR;
4628 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4630 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4633 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4635 return NT_STATUS_INTERNAL_ERROR;
4639 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4642 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4644 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4650 case SMB_QUERY_POSIX_LOCK:
4655 enum brl_type lock_type;
4657 /* We need an open file with a real fd for this. */
4658 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4659 return NT_STATUS_INVALID_LEVEL;
4662 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4663 return NT_STATUS_INVALID_PARAMETER;
4666 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4667 case POSIX_LOCK_TYPE_READ:
4668 lock_type = READ_LOCK;
4670 case POSIX_LOCK_TYPE_WRITE:
4671 lock_type = WRITE_LOCK;
4673 case POSIX_LOCK_TYPE_UNLOCK:
4675 /* There's no point in asking for an unlock... */
4676 return NT_STATUS_INVALID_PARAMETER;
4679 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4680 #if defined(HAVE_LONGLONG)
4681 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4682 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4683 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4684 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4685 #else /* HAVE_LONGLONG */
4686 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4687 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4688 #endif /* HAVE_LONGLONG */
4690 status = query_lock(fsp,
4697 if (ERROR_WAS_LOCK_DENIED(status)) {
4698 /* Here we need to report who has it locked... */
4699 data_size = POSIX_LOCK_DATA_SIZE;
4701 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4702 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4703 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4704 #if defined(HAVE_LONGLONG)
4705 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4706 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4707 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4708 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4709 #else /* HAVE_LONGLONG */
4710 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4711 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4712 #endif /* HAVE_LONGLONG */
4714 } else if (NT_STATUS_IS_OK(status)) {
4715 /* For success we just return a copy of what we sent
4716 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4717 data_size = POSIX_LOCK_DATA_SIZE;
4718 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4719 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4727 return NT_STATUS_INVALID_LEVEL;
4730 *pdata_size = data_size;
4731 return NT_STATUS_OK;
4734 /****************************************************************************
4735 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4736 file name or file id).
4737 ****************************************************************************/
4739 static void call_trans2qfilepathinfo(connection_struct *conn,
4740 struct smb_request *req,
4741 unsigned int tran_call,
4742 char **pparams, int total_params,
4743 char **ppdata, int total_data,
4744 unsigned int max_data_bytes)
4746 char *params = *pparams;
4747 char *pdata = *ppdata;
4749 unsigned int data_size = 0;
4750 unsigned int param_size = 2;
4751 struct smb_filename *smb_fname = NULL;
4752 bool delete_pending = False;
4753 struct timespec write_time_ts;
4754 files_struct *fsp = NULL;
4755 struct file_id fileid;
4756 struct ea_list *ea_list = NULL;
4757 int lock_data_count = 0;
4758 char *lock_data = NULL;
4759 bool ms_dfs_link = false;
4760 NTSTATUS status = NT_STATUS_OK;
4763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4767 ZERO_STRUCT(write_time_ts);
4769 if (tran_call == TRANSACT2_QFILEINFO) {
4770 if (total_params < 4) {
4771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4776 call_trans2qpipeinfo(conn, req, tran_call,
4777 pparams, total_params,
4783 fsp = file_fsp(req, SVAL(params,0));
4784 info_level = SVAL(params,2);
4786 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4788 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4789 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4793 /* Initial check for valid fsp ptr. */
4794 if (!check_fsp_open(conn, req, fsp)) {
4798 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4800 if (!NT_STATUS_IS_OK(status)) {
4801 reply_nterror(req, status);
4805 if(fsp->fake_file_handle) {
4807 * This is actually for the QUOTA_FAKE_FILE --metze
4810 /* We know this name is ok, it's already passed the checks. */
4812 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4814 * This is actually a QFILEINFO on a directory
4815 * handle (returned from an NT SMB). NT5.0 seems
4816 * to do this call. JRA.
4819 if (INFO_LEVEL_IS_UNIX(info_level)) {
4820 /* Always do lstat for UNIX calls. */
4821 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4822 DEBUG(3,("call_trans2qfilepathinfo: "
4823 "SMB_VFS_LSTAT of %s failed "
4825 smb_fname_str_dbg(smb_fname),
4828 map_nt_error_from_unix(errno));
4831 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4832 DEBUG(3,("call_trans2qfilepathinfo: "
4833 "SMB_VFS_STAT of %s failed (%s)\n",
4834 smb_fname_str_dbg(smb_fname),
4837 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);
4845 * Original code - this is an open file.
4847 if (!check_fsp(conn, req, fsp)) {
4851 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4852 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4853 fsp->fnum, strerror(errno)));
4855 map_nt_error_from_unix(errno));
4858 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4859 get_file_infos(fileid, &delete_pending, &write_time_ts);
4866 if (total_params < 7) {
4867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4871 info_level = SVAL(params,0);
4873 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4875 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4876 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4880 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4882 STR_TERMINATE, &status);
4883 if (!NT_STATUS_IS_OK(status)) {
4884 reply_nterror(req, status);
4888 status = filename_convert(req,
4890 req->flags2 & FLAGS2_DFS_PATHNAMES,
4894 if (!NT_STATUS_IS_OK(status)) {
4895 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4896 reply_botherror(req,
4897 NT_STATUS_PATH_NOT_COVERED,
4898 ERRSRV, ERRbadpath);
4901 reply_nterror(req, status);
4905 /* If this is a stream, check if there is a delete_pending. */
4906 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4907 && is_ntfs_stream_smb_fname(smb_fname)) {
4908 struct smb_filename *smb_fname_base = NULL;
4910 /* Create an smb_filename with stream_name == NULL. */
4912 create_synthetic_smb_fname(talloc_tos(),
4913 smb_fname->base_name,
4916 if (!NT_STATUS_IS_OK(status)) {
4917 reply_nterror(req, status);
4921 if (INFO_LEVEL_IS_UNIX(info_level)) {
4922 /* Always do lstat for UNIX calls. */
4923 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4924 DEBUG(3,("call_trans2qfilepathinfo: "
4925 "SMB_VFS_LSTAT of %s failed "
4927 smb_fname_str_dbg(smb_fname_base),
4929 TALLOC_FREE(smb_fname_base);
4931 map_nt_error_from_unix(errno));
4935 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4936 DEBUG(3,("call_trans2qfilepathinfo: "
4937 "fileinfo of %s failed "
4939 smb_fname_str_dbg(smb_fname_base),
4941 TALLOC_FREE(smb_fname_base);
4943 map_nt_error_from_unix(errno));
4948 fileid = vfs_file_id_from_sbuf(conn,
4949 &smb_fname_base->st);
4950 TALLOC_FREE(smb_fname_base);
4951 get_file_infos(fileid, &delete_pending, NULL);
4952 if (delete_pending) {
4953 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4958 if (INFO_LEVEL_IS_UNIX(info_level)) {
4959 /* Always do lstat for UNIX calls. */
4960 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4961 DEBUG(3,("call_trans2qfilepathinfo: "
4962 "SMB_VFS_LSTAT of %s failed (%s)\n",
4963 smb_fname_str_dbg(smb_fname),
4966 map_nt_error_from_unix(errno));
4970 } else if (!VALID_STAT(smb_fname->st) &&
4971 SMB_VFS_STAT(conn, smb_fname) &&
4972 (info_level != SMB_INFO_IS_NAME_VALID)) {
4973 ms_dfs_link = check_msdfs_link(conn,
4974 smb_fname->base_name,
4978 DEBUG(3,("call_trans2qfilepathinfo: "
4979 "SMB_VFS_STAT of %s failed (%s)\n",
4980 smb_fname_str_dbg(smb_fname),
4983 map_nt_error_from_unix(errno));
4988 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4989 get_file_infos(fileid, &delete_pending, &write_time_ts);
4990 if (delete_pending) {
4991 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4996 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
4997 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
4998 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5000 /* Pull out any data sent here before we realloc. */
5001 switch (info_level) {
5002 case SMB_INFO_QUERY_EAS_FROM_LIST:
5004 /* Pull any EA list from the data portion. */
5007 if (total_data < 4) {
5009 req, NT_STATUS_INVALID_PARAMETER);
5012 ea_size = IVAL(pdata,0);
5014 if (total_data > 0 && ea_size != total_data) {
5015 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5016 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5018 req, NT_STATUS_INVALID_PARAMETER);
5022 if (!lp_ea_support(SNUM(conn))) {
5023 reply_doserror(req, ERRDOS,
5024 ERReasnotsupported);
5028 /* Pull out the list of names. */
5029 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5032 req, NT_STATUS_INVALID_PARAMETER);
5038 case SMB_QUERY_POSIX_LOCK:
5040 if (fsp == NULL || fsp->fh->fd == -1) {
5041 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5045 if (total_data != POSIX_LOCK_DATA_SIZE) {
5047 req, NT_STATUS_INVALID_PARAMETER);
5051 /* Copy the lock range data. */
5052 lock_data = (char *)TALLOC_MEMDUP(
5053 req, pdata, total_data);
5055 reply_nterror(req, NT_STATUS_NO_MEMORY);
5058 lock_data_count = total_data;
5064 *pparams = (char *)SMB_REALLOC(*pparams,2);
5065 if (*pparams == NULL) {
5066 reply_nterror(req, NT_STATUS_NO_MEMORY);
5073 * draft-leach-cifs-v1-spec-02.txt
5074 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5077 * The requested information is placed in the Data portion of the
5078 * transaction response. For the information levels greater than 0x100,
5079 * the transaction response has 1 parameter word which should be
5080 * ignored by the client.
5082 * However Windows only follows this rule for the IS_NAME_VALID call.
5084 switch (info_level) {
5085 case SMB_INFO_IS_NAME_VALID:
5090 if ((info_level & 0xFF00) == 0xFF00) {
5092 * We use levels that start with 0xFF00
5093 * internally to represent SMB2 specific levels
5095 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5099 status = smbd_do_qfilepathinfo(conn, req, info_level,
5101 delete_pending, write_time_ts,
5102 ms_dfs_link, ea_list,
5103 lock_data_count, lock_data,
5104 req->flags2, max_data_bytes,
5105 ppdata, &data_size);
5106 if (!NT_STATUS_IS_OK(status)) {
5107 reply_nterror(req, status);
5111 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5117 /****************************************************************************
5118 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5120 ****************************************************************************/
5122 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5123 connection_struct *conn,
5124 const struct smb_filename *smb_fname_old,
5125 const struct smb_filename *smb_fname_new)
5127 char *oldname = NULL;
5128 char *newname = NULL;
5129 NTSTATUS status = NT_STATUS_OK;
5131 /* source must already exist. */
5132 if (!VALID_STAT(smb_fname_old->st)) {
5133 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5136 /* Disallow if newname already exists. */
5137 if (VALID_STAT(smb_fname_new->st)) {
5138 return NT_STATUS_OBJECT_NAME_COLLISION;
5141 /* No links from a directory. */
5142 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5143 return NT_STATUS_FILE_IS_A_DIRECTORY;
5146 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
5147 if (!NT_STATUS_IS_OK(status)) {
5150 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
5151 if (!NT_STATUS_IS_OK(status)) {
5155 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
5157 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
5158 status = map_nt_error_from_unix(errno);
5159 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5160 nt_errstr(status), newname, oldname));
5163 TALLOC_FREE(newname);
5164 TALLOC_FREE(oldname);
5168 /****************************************************************************
5169 Deal with setting the time from any of the setfilepathinfo functions.
5170 ****************************************************************************/
5172 NTSTATUS smb_set_file_time(connection_struct *conn,
5174 const struct smb_filename *smb_fname,
5175 struct smb_file_time *ft,
5176 bool setting_write_time)
5178 struct smb_filename *smb_fname_base = NULL;
5180 FILE_NOTIFY_CHANGE_LAST_ACCESS
5181 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5184 if (!VALID_STAT(smb_fname->st)) {
5185 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5188 /* get some defaults (no modifications) if any info is zero or -1. */
5189 if (null_timespec(ft->atime)) {
5190 ft->atime= smb_fname->st.st_ex_atime;
5191 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5194 if (null_timespec(ft->mtime)) {
5195 ft->mtime = smb_fname->st.st_ex_mtime;
5196 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5199 if (!setting_write_time) {
5200 /* ft->mtime comes from change time, not write time. */
5201 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5204 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5205 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5206 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5207 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5208 if (!null_timespec(ft->create_time)) {
5209 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5210 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5214 * Try and set the times of this file if
5215 * they are different from the current values.
5219 struct timespec mts = smb_fname->st.st_ex_mtime;
5220 struct timespec ats = smb_fname->st.st_ex_atime;
5221 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5222 (timespec_compare(&ft->mtime, &mts) == 0)) {
5223 return NT_STATUS_OK;
5227 if (setting_write_time) {
5229 * This was a Windows setfileinfo on an open file.
5230 * NT does this a lot. We also need to
5231 * set the time here, as it can be read by
5232 * FindFirst/FindNext and with the patch for bug #2045
5233 * in smbd/fileio.c it ensures that this timestamp is
5234 * kept sticky even after a write. We save the request
5235 * away and will set it on file close and after a write. JRA.
5238 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5239 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5242 if (fsp->base_fsp) {
5243 set_sticky_write_time_fsp(fsp->base_fsp,
5246 set_sticky_write_time_fsp(fsp, ft->mtime);
5249 set_sticky_write_time_path(
5250 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5255 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5257 /* Always call ntimes on the base, even if a stream was passed in. */
5258 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5259 NULL, &smb_fname->st,
5261 if (!NT_STATUS_IS_OK(status)) {
5265 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5266 TALLOC_FREE(smb_fname_base);
5267 return map_nt_error_from_unix(errno);
5269 TALLOC_FREE(smb_fname_base);
5271 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5272 smb_fname->base_name);
5273 return NT_STATUS_OK;
5276 /****************************************************************************
5277 Deal with setting the dosmode from any of the setfilepathinfo functions.
5278 ****************************************************************************/
5280 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5281 const struct smb_filename *smb_fname,
5284 struct smb_filename *smb_fname_base = NULL;
5287 if (!VALID_STAT(smb_fname->st)) {
5288 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5291 /* Always operate on the base_name, even if a stream was passed in. */
5292 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5293 NULL, &smb_fname->st,
5295 if (!NT_STATUS_IS_OK(status)) {
5300 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5307 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5309 /* check the mode isn't different, before changing it */
5310 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5311 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5312 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5313 (unsigned int)dosmode));
5315 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5317 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5319 smb_fname_str_dbg(smb_fname_base),
5321 status = map_nt_error_from_unix(errno);
5325 status = NT_STATUS_OK;
5327 TALLOC_FREE(smb_fname_base);
5331 /****************************************************************************
5332 Deal with setting the size from any of the setfilepathinfo functions.
5333 ****************************************************************************/
5335 static NTSTATUS smb_set_file_size(connection_struct *conn,
5336 struct smb_request *req,
5338 const struct smb_filename *smb_fname,
5339 const SMB_STRUCT_STAT *psbuf,
5342 NTSTATUS status = NT_STATUS_OK;
5343 struct smb_filename *smb_fname_tmp = NULL;
5344 files_struct *new_fsp = NULL;
5346 if (!VALID_STAT(*psbuf)) {
5347 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5350 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5352 if (size == get_file_size_stat(psbuf)) {
5353 return NT_STATUS_OK;
5356 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5357 smb_fname_str_dbg(smb_fname), (double)size));
5359 if (fsp && fsp->fh->fd != -1) {
5360 /* Handle based call. */
5361 if (vfs_set_filelen(fsp, size) == -1) {
5362 return map_nt_error_from_unix(errno);
5364 trigger_write_time_update_immediate(fsp);
5365 return NT_STATUS_OK;
5368 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5369 if (!NT_STATUS_IS_OK(status)) {
5373 smb_fname_tmp->st = *psbuf;
5375 status = SMB_VFS_CREATE_FILE(
5378 0, /* root_dir_fid */
5379 smb_fname_tmp, /* fname */
5380 FILE_WRITE_ATTRIBUTES, /* access_mask */
5381 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5383 FILE_OPEN, /* create_disposition*/
5384 0, /* create_options */
5385 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5386 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5387 0, /* allocation_size */
5390 &new_fsp, /* result */
5393 TALLOC_FREE(smb_fname_tmp);
5395 if (!NT_STATUS_IS_OK(status)) {
5396 /* NB. We check for open_was_deferred in the caller. */
5400 if (vfs_set_filelen(new_fsp, size) == -1) {
5401 status = map_nt_error_from_unix(errno);
5402 close_file(req, new_fsp,NORMAL_CLOSE);
5406 trigger_write_time_update_immediate(new_fsp);
5407 close_file(req, new_fsp,NORMAL_CLOSE);
5408 return NT_STATUS_OK;
5411 /****************************************************************************
5412 Deal with SMB_INFO_SET_EA.
5413 ****************************************************************************/
5415 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5419 const struct smb_filename *smb_fname)
5421 struct ea_list *ea_list = NULL;
5422 TALLOC_CTX *ctx = NULL;
5423 NTSTATUS status = NT_STATUS_OK;
5425 if (total_data < 10) {
5427 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5428 length. They seem to have no effect. Bug #3212. JRA */
5430 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5431 /* We're done. We only get EA info in this call. */
5432 return NT_STATUS_OK;
5435 return NT_STATUS_INVALID_PARAMETER;
5438 if (IVAL(pdata,0) > total_data) {
5439 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5440 IVAL(pdata,0), (unsigned int)total_data));
5441 return NT_STATUS_INVALID_PARAMETER;
5445 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5447 return NT_STATUS_INVALID_PARAMETER;
5449 status = set_ea(conn, fsp, smb_fname, ea_list);
5454 /****************************************************************************
5455 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5456 ****************************************************************************/
5458 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5462 const struct smb_filename *smb_fname)
5464 NTSTATUS status = NT_STATUS_OK;
5465 bool delete_on_close;
5468 if (total_data < 1) {
5469 return NT_STATUS_INVALID_PARAMETER;
5473 return NT_STATUS_INVALID_HANDLE;
5476 delete_on_close = (CVAL(pdata,0) ? True : False);
5477 dosmode = dos_mode(conn, smb_fname);
5479 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5480 "delete_on_close = %u\n",
5481 smb_fname_str_dbg(smb_fname),
5482 (unsigned int)dosmode,
5483 (unsigned int)delete_on_close ));
5485 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5487 if (!NT_STATUS_IS_OK(status)) {
5491 /* The set is across all open files on this dev/inode pair. */
5492 if (!set_delete_on_close(fsp, delete_on_close,
5493 &conn->server_info->utok)) {
5494 return NT_STATUS_ACCESS_DENIED;
5496 return NT_STATUS_OK;
5499 /****************************************************************************
5500 Deal with SMB_FILE_POSITION_INFORMATION.
5501 ****************************************************************************/
5503 static NTSTATUS smb_file_position_information(connection_struct *conn,
5508 uint64_t position_information;
5510 if (total_data < 8) {
5511 return NT_STATUS_INVALID_PARAMETER;
5515 /* Ignore on pathname based set. */
5516 return NT_STATUS_OK;
5519 position_information = (uint64_t)IVAL(pdata,0);
5520 #ifdef LARGE_SMB_OFF_T
5521 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5522 #else /* LARGE_SMB_OFF_T */
5523 if (IVAL(pdata,4) != 0) {
5524 /* more than 32 bits? */
5525 return NT_STATUS_INVALID_PARAMETER;
5527 #endif /* LARGE_SMB_OFF_T */
5529 DEBUG(10,("smb_file_position_information: Set file position "
5530 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5531 (double)position_information));
5532 fsp->fh->position_information = position_information;
5533 return NT_STATUS_OK;
5536 /****************************************************************************
5537 Deal with SMB_FILE_MODE_INFORMATION.
5538 ****************************************************************************/
5540 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5546 if (total_data < 4) {
5547 return NT_STATUS_INVALID_PARAMETER;
5549 mode = IVAL(pdata,0);
5550 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5551 return NT_STATUS_INVALID_PARAMETER;
5553 return NT_STATUS_OK;
5556 /****************************************************************************
5557 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5558 ****************************************************************************/
5560 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5561 struct smb_request *req,
5566 char *link_target = NULL;
5567 const char *newname = fname;
5568 NTSTATUS status = NT_STATUS_OK;
5569 TALLOC_CTX *ctx = talloc_tos();
5571 /* Set a symbolic link. */
5572 /* Don't allow this if follow links is false. */
5574 if (total_data == 0) {
5575 return NT_STATUS_INVALID_PARAMETER;
5578 if (!lp_symlinks(SNUM(conn))) {
5579 return NT_STATUS_ACCESS_DENIED;
5582 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5583 total_data, STR_TERMINATE);
5586 return NT_STATUS_INVALID_PARAMETER;
5589 /* !widelinks forces the target path to be within the share. */
5590 /* This means we can interpret the target as a pathname. */
5591 if (!lp_widelinks(SNUM(conn))) {
5592 char *rel_name = NULL;
5593 char *last_dirp = NULL;
5595 if (*link_target == '/') {
5596 /* No absolute paths allowed. */
5597 return NT_STATUS_ACCESS_DENIED;
5599 rel_name = talloc_strdup(ctx,newname);
5601 return NT_STATUS_NO_MEMORY;
5603 last_dirp = strrchr_m(rel_name, '/');
5605 last_dirp[1] = '\0';
5607 rel_name = talloc_strdup(ctx,"./");
5609 return NT_STATUS_NO_MEMORY;
5612 rel_name = talloc_asprintf_append(rel_name,
5616 return NT_STATUS_NO_MEMORY;
5619 status = check_name(conn, rel_name);
5620 if (!NT_STATUS_IS_OK(status)) {
5625 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5626 newname, link_target ));
5628 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5629 return map_nt_error_from_unix(errno);
5632 return NT_STATUS_OK;
5635 /****************************************************************************
5636 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5637 ****************************************************************************/
5639 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5640 struct smb_request *req,
5641 const char *pdata, int total_data,
5642 const struct smb_filename *smb_fname_new)
5644 char *oldname = NULL;
5645 struct smb_filename *smb_fname_old = NULL;
5646 TALLOC_CTX *ctx = talloc_tos();
5647 NTSTATUS status = NT_STATUS_OK;
5649 /* Set a hard link. */
5650 if (total_data == 0) {
5651 return NT_STATUS_INVALID_PARAMETER;
5654 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5655 total_data, STR_TERMINATE, &status);
5656 if (!NT_STATUS_IS_OK(status)) {
5660 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5661 smb_fname_str_dbg(smb_fname_new), oldname));
5663 status = filename_convert(ctx,
5665 req->flags2 & FLAGS2_DFS_PATHNAMES,
5669 if (!NT_STATUS_IS_OK(status)) {
5673 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5676 /****************************************************************************
5677 Deal with SMB_FILE_RENAME_INFORMATION.
5678 ****************************************************************************/
5680 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5681 struct smb_request *req,
5690 char *newname = NULL;
5691 char *base_name = NULL;
5692 struct smb_filename *smb_fname = NULL;
5693 bool dest_has_wcard = False;
5694 NTSTATUS status = NT_STATUS_OK;
5696 TALLOC_CTX *ctx = talloc_tos();
5698 if (total_data < 13) {
5699 return NT_STATUS_INVALID_PARAMETER;
5702 overwrite = (CVAL(pdata,0) ? True : False);
5703 root_fid = IVAL(pdata,4);
5704 len = IVAL(pdata,8);
5706 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5707 return NT_STATUS_INVALID_PARAMETER;
5710 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5713 if (!NT_STATUS_IS_OK(status)) {
5717 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5720 status = resolve_dfspath_wcard(ctx, conn,
5721 req->flags2 & FLAGS2_DFS_PATHNAMES,
5725 if (!NT_STATUS_IS_OK(status)) {
5729 /* Check the new name has no '/' characters. */
5730 if (strchr_m(newname, '/')) {
5731 return NT_STATUS_NOT_SUPPORTED;
5734 if (fsp && fsp->base_fsp) {
5735 /* newname must be a stream name. */
5736 if (newname[0] != ':') {
5737 return NT_STATUS_NOT_SUPPORTED;
5740 /* Create an smb_fname to call rename_internals_fsp() with. */
5741 status = create_synthetic_smb_fname(talloc_tos(),
5742 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5744 if (!NT_STATUS_IS_OK(status)) {
5749 * Set the original last component, since
5750 * rename_internals_fsp() requires it.
5752 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5753 if (smb_fname->original_lcomp == NULL) {
5754 status = NT_STATUS_NO_MEMORY;
5758 /* Create a char * to call rename_internals() with. */
5759 base_name = talloc_asprintf(ctx, "%s%s",
5760 fsp->base_fsp->fsp_name->base_name,
5763 status = NT_STATUS_NO_MEMORY;
5767 /* newname must *not* be a stream name. */
5768 if (newname[0] == ':') {
5769 return NT_STATUS_NOT_SUPPORTED;
5772 /* Create the base directory. */
5773 base_name = talloc_strdup(ctx, fname);
5775 return NT_STATUS_NO_MEMORY;
5777 p = strrchr_m(base_name, '/');
5781 base_name = talloc_strdup(ctx, "./");
5783 return NT_STATUS_NO_MEMORY;
5786 /* Append the new name. */
5787 base_name = talloc_asprintf_append(base_name,
5791 return NT_STATUS_NO_MEMORY;
5794 status = unix_convert(ctx, conn, base_name, &smb_fname,
5797 /* If an error we expect this to be
5798 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5800 if (!NT_STATUS_IS_OK(status)) {
5801 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5805 /* Create an smb_fname to call rename_internals_fsp() */
5806 status = create_synthetic_smb_fname(talloc_tos(),
5809 if (!NT_STATUS_IS_OK(status)) {
5817 DEBUG(10,("smb_file_rename_information: "
5818 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5819 fsp->fnum, fsp_str_dbg(fsp), base_name));
5820 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5823 DEBUG(10,("smb_file_rename_information: "
5824 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5826 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5827 overwrite, False, dest_has_wcard,
5828 FILE_WRITE_ATTRIBUTES);
5831 TALLOC_FREE(smb_fname);
5835 /****************************************************************************
5836 Deal with SMB_SET_POSIX_ACL.
5837 ****************************************************************************/
5839 #if defined(HAVE_POSIX_ACLS)
5840 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5845 SMB_STRUCT_STAT *psbuf)
5847 uint16 posix_acl_version;
5848 uint16 num_file_acls;
5849 uint16 num_def_acls;
5850 bool valid_file_acls = True;
5851 bool valid_def_acls = True;
5853 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5854 return NT_STATUS_INVALID_PARAMETER;
5856 posix_acl_version = SVAL(pdata,0);
5857 num_file_acls = SVAL(pdata,2);
5858 num_def_acls = SVAL(pdata,4);
5860 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5861 valid_file_acls = False;
5865 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5866 valid_def_acls = False;
5870 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5871 return NT_STATUS_INVALID_PARAMETER;
5874 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5875 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5876 return NT_STATUS_INVALID_PARAMETER;
5879 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5880 fname ? fname : fsp_str_dbg(fsp),
5881 (unsigned int)num_file_acls,
5882 (unsigned int)num_def_acls));
5884 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5885 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5886 return map_nt_error_from_unix(errno);
5889 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5890 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5891 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5892 return map_nt_error_from_unix(errno);
5894 return NT_STATUS_OK;
5898 /****************************************************************************
5899 Deal with SMB_SET_POSIX_LOCK.
5900 ****************************************************************************/
5902 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5903 struct smb_request *req,
5911 bool blocking_lock = False;
5912 enum brl_type lock_type;
5914 NTSTATUS status = NT_STATUS_OK;
5916 if (fsp == NULL || fsp->fh->fd == -1) {
5917 return NT_STATUS_INVALID_HANDLE;
5920 if (total_data != POSIX_LOCK_DATA_SIZE) {
5921 return NT_STATUS_INVALID_PARAMETER;
5924 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5925 case POSIX_LOCK_TYPE_READ:
5926 lock_type = READ_LOCK;
5928 case POSIX_LOCK_TYPE_WRITE:
5929 /* Return the right POSIX-mappable error code for files opened read-only. */
5930 if (!fsp->can_write) {
5931 return NT_STATUS_INVALID_HANDLE;
5933 lock_type = WRITE_LOCK;
5935 case POSIX_LOCK_TYPE_UNLOCK:
5936 lock_type = UNLOCK_LOCK;
5939 return NT_STATUS_INVALID_PARAMETER;
5942 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5943 blocking_lock = False;
5944 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5945 blocking_lock = True;
5947 return NT_STATUS_INVALID_PARAMETER;
5950 if (!lp_blocking_locks(SNUM(conn))) {
5951 blocking_lock = False;
5954 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5955 #if defined(HAVE_LONGLONG)
5956 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5957 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5958 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5959 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5960 #else /* HAVE_LONGLONG */
5961 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5962 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5963 #endif /* HAVE_LONGLONG */
5965 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5966 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5968 (unsigned int)lock_type,
5969 (unsigned int)lock_pid,
5973 if (lock_type == UNLOCK_LOCK) {
5974 status = do_unlock(smbd_messaging_context(),
5981 uint32 block_smbpid;
5983 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5995 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5997 * A blocking lock was requested. Package up
5998 * this smb into a queued request and push it
5999 * onto the blocking lock queue.
6001 if(push_blocking_lock_request(br_lck,
6004 -1, /* infinite timeout. */
6012 TALLOC_FREE(br_lck);
6016 TALLOC_FREE(br_lck);
6022 /****************************************************************************
6023 Deal with SMB_INFO_STANDARD.
6024 ****************************************************************************/
6026 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6030 const struct smb_filename *smb_fname)
6032 struct smb_file_time ft;
6035 if (total_data < 12) {
6036 return NT_STATUS_INVALID_PARAMETER;
6040 ft.create_time = interpret_long_date(pdata);
6043 ft.atime = interpret_long_date(pdata + 8);
6046 ft.mtime = interpret_long_date(pdata + 16);
6048 DEBUG(10,("smb_set_info_standard: file %s\n",
6049 smb_fname_str_dbg(smb_fname)));
6051 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
6054 /****************************************************************************
6055 Deal with SMB_SET_FILE_BASIC_INFO.
6056 ****************************************************************************/
6058 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6062 const struct smb_filename *smb_fname)
6064 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6065 struct timespec write_time;
6066 struct timespec changed_time;
6067 struct smb_file_time ft;
6069 NTSTATUS status = NT_STATUS_OK;
6070 bool setting_write_time = true;
6074 if (total_data < 36) {
6075 return NT_STATUS_INVALID_PARAMETER;
6078 /* Set the attributes */
6079 dosmode = IVAL(pdata,32);
6080 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6081 if (!NT_STATUS_IS_OK(status)) {
6086 ft.atime = interpret_long_date(pdata+8);
6088 write_time = interpret_long_date(pdata+16);
6089 changed_time = interpret_long_date(pdata+24);
6092 ft.mtime = timespec_min(&write_time, &changed_time);
6095 ft.create_time = interpret_long_date(pdata);
6097 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
6098 !null_timespec(write_time)) {
6099 ft.mtime = write_time;
6102 /* Prefer a defined time to an undefined one. */
6103 if (null_timespec(ft.mtime)) {
6104 if (null_timespec(write_time)) {
6105 ft.mtime = changed_time;
6106 setting_write_time = false;
6108 ft.mtime = write_time;
6112 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6113 smb_fname_str_dbg(smb_fname)));
6115 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6116 setting_write_time);
6119 /****************************************************************************
6120 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6121 ****************************************************************************/
6123 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6124 struct smb_request *req,
6128 struct smb_filename *smb_fname)
6130 uint64_t allocation_size = 0;
6131 NTSTATUS status = NT_STATUS_OK;
6132 files_struct *new_fsp = NULL;
6134 if (!VALID_STAT(smb_fname->st)) {
6135 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6138 if (total_data < 8) {
6139 return NT_STATUS_INVALID_PARAMETER;
6142 allocation_size = (uint64_t)IVAL(pdata,0);
6143 #ifdef LARGE_SMB_OFF_T
6144 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6145 #else /* LARGE_SMB_OFF_T */
6146 if (IVAL(pdata,4) != 0) {
6147 /* more than 32 bits? */
6148 return NT_STATUS_INVALID_PARAMETER;
6150 #endif /* LARGE_SMB_OFF_T */
6152 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6153 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6154 (double)allocation_size));
6156 if (allocation_size) {
6157 allocation_size = smb_roundup(conn, allocation_size);
6160 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6161 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6162 (double)allocation_size));
6164 if (fsp && fsp->fh->fd != -1) {
6165 /* Open file handle. */
6166 /* Only change if needed. */
6167 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6168 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6169 return map_nt_error_from_unix(errno);
6172 /* But always update the time. */
6174 * This is equivalent to a write. Ensure it's seen immediately
6175 * if there are no pending writes.
6177 trigger_write_time_update_immediate(fsp);
6178 return NT_STATUS_OK;
6181 /* Pathname or stat or directory file. */
6182 status = SMB_VFS_CREATE_FILE(
6185 0, /* root_dir_fid */
6186 smb_fname, /* fname */
6187 FILE_WRITE_DATA, /* access_mask */
6188 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6190 FILE_OPEN, /* create_disposition*/
6191 0, /* create_options */
6192 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6193 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6194 0, /* allocation_size */
6197 &new_fsp, /* result */
6200 if (!NT_STATUS_IS_OK(status)) {
6201 /* NB. We check for open_was_deferred in the caller. */
6205 /* Only change if needed. */
6206 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6207 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6208 status = map_nt_error_from_unix(errno);
6209 close_file(req, new_fsp, NORMAL_CLOSE);
6214 /* Changing the allocation size should set the last mod time. */
6216 * This is equivalent to a write. Ensure it's seen immediately
6217 * if there are no pending writes.
6219 trigger_write_time_update_immediate(new_fsp);
6221 close_file(req, new_fsp, NORMAL_CLOSE);
6222 return NT_STATUS_OK;
6225 /****************************************************************************
6226 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6227 ****************************************************************************/
6229 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6230 struct smb_request *req,
6234 const struct smb_filename *smb_fname)
6238 if (total_data < 8) {
6239 return NT_STATUS_INVALID_PARAMETER;
6242 size = IVAL(pdata,0);
6243 #ifdef LARGE_SMB_OFF_T
6244 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6245 #else /* LARGE_SMB_OFF_T */
6246 if (IVAL(pdata,4) != 0) {
6247 /* more than 32 bits? */
6248 return NT_STATUS_INVALID_PARAMETER;
6250 #endif /* LARGE_SMB_OFF_T */
6251 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6252 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6255 return smb_set_file_size(conn, req,
6262 /****************************************************************************
6263 Allow a UNIX info mknod.
6264 ****************************************************************************/
6266 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6269 const struct smb_filename *smb_fname)
6271 uint32 file_type = IVAL(pdata,56);
6272 #if defined(HAVE_MAKEDEV)
6273 uint32 dev_major = IVAL(pdata,60);
6274 uint32 dev_minor = IVAL(pdata,68);
6276 SMB_DEV_T dev = (SMB_DEV_T)0;
6277 uint32 raw_unixmode = IVAL(pdata,84);
6281 if (total_data < 100) {
6282 return NT_STATUS_INVALID_PARAMETER;
6285 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6286 PERM_NEW_FILE, &unixmode);
6287 if (!NT_STATUS_IS_OK(status)) {
6291 #if defined(HAVE_MAKEDEV)
6292 dev = makedev(dev_major, dev_minor);
6295 switch (file_type) {
6296 #if defined(S_IFIFO)
6297 case UNIX_TYPE_FIFO:
6298 unixmode |= S_IFIFO;
6301 #if defined(S_IFSOCK)
6302 case UNIX_TYPE_SOCKET:
6303 unixmode |= S_IFSOCK;
6306 #if defined(S_IFCHR)
6307 case UNIX_TYPE_CHARDEV:
6308 unixmode |= S_IFCHR;
6311 #if defined(S_IFBLK)
6312 case UNIX_TYPE_BLKDEV:
6313 unixmode |= S_IFBLK;
6317 return NT_STATUS_INVALID_PARAMETER;
6320 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6321 "%.0f mode 0%o for file %s\n", (double)dev,
6322 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6324 /* Ok - do the mknod. */
6325 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6326 return map_nt_error_from_unix(errno);
6329 /* If any of the other "set" calls fail we
6330 * don't want to end up with a half-constructed mknod.
6333 if (lp_inherit_perms(SNUM(conn))) {
6335 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6337 return NT_STATUS_NO_MEMORY;
6339 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6341 TALLOC_FREE(parent);
6344 return NT_STATUS_OK;
6347 /****************************************************************************
6348 Deal with SMB_SET_FILE_UNIX_BASIC.
6349 ****************************************************************************/
6351 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6352 struct smb_request *req,
6356 const struct smb_filename *smb_fname)
6358 struct smb_file_time ft;
6359 uint32 raw_unixmode;
6362 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6363 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6364 NTSTATUS status = NT_STATUS_OK;
6365 bool delete_on_fail = False;
6366 enum perm_type ptype;
6367 files_struct *all_fsps = NULL;
6368 bool modify_mtime = true;
6370 SMB_STRUCT_STAT sbuf;
6374 if (total_data < 100) {
6375 return NT_STATUS_INVALID_PARAMETER;
6378 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6379 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6380 size=IVAL(pdata,0); /* first 8 Bytes are size */
6381 #ifdef LARGE_SMB_OFF_T
6382 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6383 #else /* LARGE_SMB_OFF_T */
6384 if (IVAL(pdata,4) != 0) {
6385 /* more than 32 bits? */
6386 return NT_STATUS_INVALID_PARAMETER;
6388 #endif /* LARGE_SMB_OFF_T */
6391 ft.atime = interpret_long_date(pdata+24); /* access_time */
6392 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6393 set_owner = (uid_t)IVAL(pdata,40);
6394 set_grp = (gid_t)IVAL(pdata,48);
6395 raw_unixmode = IVAL(pdata,84);
6397 if (VALID_STAT(smb_fname->st)) {
6398 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6399 ptype = PERM_EXISTING_DIR;
6401 ptype = PERM_EXISTING_FILE;
6404 ptype = PERM_NEW_FILE;
6407 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6409 if (!NT_STATUS_IS_OK(status)) {
6413 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6414 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6415 smb_fname_str_dbg(smb_fname), (double)size,
6416 (unsigned int)set_owner, (unsigned int)set_grp,
6417 (int)raw_unixmode));
6419 sbuf = smb_fname->st;
6421 if (!VALID_STAT(sbuf)) {
6422 struct smb_filename *smb_fname_tmp = NULL;
6424 * The only valid use of this is to create character and block
6425 * devices, and named pipes. This is deprecated (IMHO) and
6426 * a new info level should be used for mknod. JRA.
6429 status = smb_unix_mknod(conn,
6433 if (!NT_STATUS_IS_OK(status)) {
6437 status = copy_smb_filename(talloc_tos(), smb_fname,
6439 if (!NT_STATUS_IS_OK(status)) {
6443 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6444 status = map_nt_error_from_unix(errno);
6445 TALLOC_FREE(smb_fname_tmp);
6446 SMB_VFS_UNLINK(conn, smb_fname);
6450 sbuf = smb_fname_tmp->st;
6451 TALLOC_FREE(smb_fname_tmp);
6453 /* Ensure we don't try and change anything else. */
6454 raw_unixmode = SMB_MODE_NO_CHANGE;
6455 size = get_file_size_stat(&sbuf);
6456 ft.atime = sbuf.st_ex_atime;
6457 ft.mtime = sbuf.st_ex_mtime;
6459 * We continue here as we might want to change the
6462 delete_on_fail = True;
6466 /* Horrible backwards compatibility hack as an old server bug
6467 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6471 size = get_file_size_stat(&sbuf);
6476 * Deal with the UNIX specific mode set.
6479 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6480 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6481 "setting mode 0%o for file %s\n",
6482 (unsigned int)unixmode,
6483 smb_fname_str_dbg(smb_fname)));
6484 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6485 return map_nt_error_from_unix(errno);
6490 * Deal with the UNIX specific uid set.
6493 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6494 (sbuf.st_ex_uid != set_owner)) {
6497 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6498 "changing owner %u for path %s\n",
6499 (unsigned int)set_owner,
6500 smb_fname_str_dbg(smb_fname)));
6502 if (S_ISLNK(sbuf.st_ex_mode)) {
6503 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6504 set_owner, (gid_t)-1);
6506 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6507 set_owner, (gid_t)-1);
6511 status = map_nt_error_from_unix(errno);
6512 if (delete_on_fail) {
6513 SMB_VFS_UNLINK(conn, smb_fname);
6520 * Deal with the UNIX specific gid set.
6523 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6524 (sbuf.st_ex_gid != set_grp)) {
6525 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6526 "changing group %u for file %s\n",
6527 (unsigned int)set_owner,
6528 smb_fname_str_dbg(smb_fname)));
6529 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6531 status = map_nt_error_from_unix(errno);
6532 if (delete_on_fail) {
6533 SMB_VFS_UNLINK(conn, smb_fname);
6539 /* Deal with any size changes. */
6541 status = smb_set_file_size(conn, req,
6546 if (!NT_STATUS_IS_OK(status)) {
6550 /* Deal with any time changes. */
6551 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6552 /* No change, don't cancel anything. */
6556 id = vfs_file_id_from_sbuf(conn, &sbuf);
6557 for(all_fsps = file_find_di_first(id); all_fsps;
6558 all_fsps = file_find_di_next(all_fsps)) {
6560 * We're setting the time explicitly for UNIX.
6561 * Cancel any pending changes over all handles.
6563 all_fsps->update_write_time_on_close = false;
6564 TALLOC_FREE(all_fsps->update_write_time_event);
6568 * Override the "setting_write_time"
6569 * parameter here as it almost does what
6570 * we need. Just remember if we modified
6571 * mtime and send the notify ourselves.
6573 if (null_timespec(ft.mtime)) {
6574 modify_mtime = false;
6577 status = smb_set_file_time(conn,
6583 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6584 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6589 /****************************************************************************
6590 Deal with SMB_SET_FILE_UNIX_INFO2.
6591 ****************************************************************************/
6593 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6594 struct smb_request *req,
6598 const struct smb_filename *smb_fname)
6604 if (total_data < 116) {
6605 return NT_STATUS_INVALID_PARAMETER;
6608 /* Start by setting all the fields that are common between UNIX_BASIC
6611 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6613 if (!NT_STATUS_IS_OK(status)) {
6617 smb_fflags = IVAL(pdata, 108);
6618 smb_fmask = IVAL(pdata, 112);
6620 /* NB: We should only attempt to alter the file flags if the client
6621 * sends a non-zero mask.
6623 if (smb_fmask != 0) {
6624 int stat_fflags = 0;
6626 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6627 smb_fmask, &stat_fflags)) {
6628 /* Client asked to alter a flag we don't understand. */
6629 return NT_STATUS_INVALID_PARAMETER;
6632 if (fsp && fsp->fh->fd != -1) {
6633 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6634 return NT_STATUS_NOT_SUPPORTED;
6636 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6637 stat_fflags) != 0) {
6638 return map_nt_error_from_unix(errno);
6643 /* XXX: need to add support for changing the create_time here. You
6644 * can do this for paths on Darwin with setattrlist(2). The right way
6645 * to hook this up is probably by extending the VFS utimes interface.
6648 return NT_STATUS_OK;
6651 /****************************************************************************
6652 Create a directory with POSIX semantics.
6653 ****************************************************************************/
6655 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6656 struct smb_request *req,
6660 SMB_STRUCT_STAT *psbuf,
6661 int *pdata_return_size)
6663 struct smb_filename *smb_fname;
6664 NTSTATUS status = NT_STATUS_OK;
6665 uint32 raw_unixmode = 0;
6666 uint32 mod_unixmode = 0;
6667 mode_t unixmode = (mode_t)0;
6668 files_struct *fsp = NULL;
6669 uint16 info_level_return = 0;
6671 char *pdata = *ppdata;
6673 if (total_data < 18) {
6674 return NT_STATUS_INVALID_PARAMETER;
6677 raw_unixmode = IVAL(pdata,8);
6678 /* Next 4 bytes are not yet defined. */
6680 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6681 if (!NT_STATUS_IS_OK(status)) {
6685 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6687 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6688 fname, (unsigned int)unixmode ));
6690 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6692 if (!NT_STATUS_IS_OK(status)) {
6696 status = SMB_VFS_CREATE_FILE(
6699 0, /* root_dir_fid */
6700 smb_fname, /* fname */
6701 FILE_READ_ATTRIBUTES, /* access_mask */
6702 FILE_SHARE_NONE, /* share_access */
6703 FILE_CREATE, /* create_disposition*/
6704 FILE_DIRECTORY_FILE, /* create_options */
6705 mod_unixmode, /* file_attributes */
6706 0, /* oplock_request */
6707 0, /* allocation_size */
6713 *psbuf = smb_fname->st;
6714 TALLOC_FREE(smb_fname);
6716 if (NT_STATUS_IS_OK(status)) {
6717 close_file(req, fsp, NORMAL_CLOSE);
6720 info_level_return = SVAL(pdata,16);
6722 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6723 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6724 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6725 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6727 *pdata_return_size = 12;
6730 /* Realloc the data size */
6731 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6732 if (*ppdata == NULL) {
6733 *pdata_return_size = 0;
6734 return NT_STATUS_NO_MEMORY;
6738 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6739 SSVAL(pdata,2,0); /* No fnum. */
6740 SIVAL(pdata,4,info); /* Was directory created. */
6742 switch (info_level_return) {
6743 case SMB_QUERY_FILE_UNIX_BASIC:
6744 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6745 SSVAL(pdata,10,0); /* Padding. */
6746 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6748 case SMB_QUERY_FILE_UNIX_INFO2:
6749 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6750 SSVAL(pdata,10,0); /* Padding. */
6751 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6754 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6755 SSVAL(pdata,10,0); /* Padding. */
6762 /****************************************************************************
6763 Open/Create a file with POSIX semantics.
6764 ****************************************************************************/
6766 static NTSTATUS smb_posix_open(connection_struct *conn,
6767 struct smb_request *req,
6771 SMB_STRUCT_STAT *psbuf,
6772 int *pdata_return_size)
6774 struct smb_filename *smb_fname = NULL;
6775 bool extended_oplock_granted = False;
6776 char *pdata = *ppdata;
6778 uint32 wire_open_mode = 0;
6779 uint32 raw_unixmode = 0;
6780 uint32 mod_unixmode = 0;
6781 uint32 create_disp = 0;
6782 uint32 access_mask = 0;
6783 uint32 create_options = 0;
6784 NTSTATUS status = NT_STATUS_OK;
6785 mode_t unixmode = (mode_t)0;
6786 files_struct *fsp = NULL;
6787 int oplock_request = 0;
6789 uint16 info_level_return = 0;
6791 if (total_data < 18) {
6792 return NT_STATUS_INVALID_PARAMETER;
6795 flags = IVAL(pdata,0);
6796 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6797 if (oplock_request) {
6798 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6801 wire_open_mode = IVAL(pdata,4);
6803 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6804 return smb_posix_mkdir(conn, req,
6812 switch (wire_open_mode & SMB_ACCMODE) {
6814 access_mask = FILE_READ_DATA;
6817 access_mask = FILE_WRITE_DATA;
6820 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6823 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6824 (unsigned int)wire_open_mode ));
6825 return NT_STATUS_INVALID_PARAMETER;
6828 wire_open_mode &= ~SMB_ACCMODE;
6830 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6831 create_disp = FILE_CREATE;
6832 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6833 create_disp = FILE_OVERWRITE_IF;
6834 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6835 create_disp = FILE_OPEN_IF;
6836 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6837 create_disp = FILE_OPEN;
6839 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6840 (unsigned int)wire_open_mode ));
6841 return NT_STATUS_INVALID_PARAMETER;
6844 raw_unixmode = IVAL(pdata,8);
6845 /* Next 4 bytes are not yet defined. */
6847 status = unix_perms_from_wire(conn,
6850 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6853 if (!NT_STATUS_IS_OK(status)) {
6857 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6859 if (wire_open_mode & SMB_O_SYNC) {
6860 create_options |= FILE_WRITE_THROUGH;
6862 if (wire_open_mode & SMB_O_APPEND) {
6863 access_mask |= FILE_APPEND_DATA;
6865 if (wire_open_mode & SMB_O_DIRECT) {
6866 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6869 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6871 (unsigned int)wire_open_mode,
6872 (unsigned int)unixmode ));
6874 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6876 if (!NT_STATUS_IS_OK(status)) {
6880 status = SMB_VFS_CREATE_FILE(
6883 0, /* root_dir_fid */
6884 smb_fname, /* fname */
6885 access_mask, /* access_mask */
6886 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6888 create_disp, /* create_disposition*/
6889 FILE_NON_DIRECTORY_FILE, /* create_options */
6890 mod_unixmode, /* file_attributes */
6891 oplock_request, /* oplock_request */
6892 0, /* allocation_size */
6898 *psbuf = smb_fname->st;
6899 TALLOC_FREE(smb_fname);
6901 if (!NT_STATUS_IS_OK(status)) {
6905 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6906 extended_oplock_granted = True;
6909 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6910 extended_oplock_granted = True;
6913 info_level_return = SVAL(pdata,16);
6915 /* Allocate the correct return size. */
6917 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6918 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6919 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6920 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6922 *pdata_return_size = 12;
6925 /* Realloc the data size */
6926 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6927 if (*ppdata == NULL) {
6928 close_file(req, fsp, ERROR_CLOSE);
6929 *pdata_return_size = 0;
6930 return NT_STATUS_NO_MEMORY;
6934 if (extended_oplock_granted) {
6935 if (flags & REQUEST_BATCH_OPLOCK) {
6936 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6938 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6940 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6941 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6943 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6946 SSVAL(pdata,2,fsp->fnum);
6947 SIVAL(pdata,4,info); /* Was file created etc. */
6949 switch (info_level_return) {
6950 case SMB_QUERY_FILE_UNIX_BASIC:
6951 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6952 SSVAL(pdata,10,0); /* padding. */
6953 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6955 case SMB_QUERY_FILE_UNIX_INFO2:
6956 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6957 SSVAL(pdata,10,0); /* padding. */
6958 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6961 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6962 SSVAL(pdata,10,0); /* padding. */
6965 return NT_STATUS_OK;
6968 /****************************************************************************
6969 Delete a file with POSIX semantics.
6970 ****************************************************************************/
6972 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6973 struct smb_request *req,
6976 struct smb_filename *smb_fname)
6978 NTSTATUS status = NT_STATUS_OK;
6979 files_struct *fsp = NULL;
6983 int create_options = 0;
6985 struct share_mode_lock *lck = NULL;
6987 if (total_data < 2) {
6988 return NT_STATUS_INVALID_PARAMETER;
6991 flags = SVAL(pdata,0);
6993 if (!VALID_STAT(smb_fname->st)) {
6994 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6997 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6998 !VALID_STAT_OF_DIR(smb_fname->st)) {
6999 return NT_STATUS_NOT_A_DIRECTORY;
7002 DEBUG(10,("smb_posix_unlink: %s %s\n",
7003 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7004 smb_fname_str_dbg(smb_fname)));
7006 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7007 create_options |= FILE_DIRECTORY_FILE;
7010 status = SMB_VFS_CREATE_FILE(
7013 0, /* root_dir_fid */
7014 smb_fname, /* fname */
7015 DELETE_ACCESS, /* access_mask */
7016 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7018 FILE_OPEN, /* create_disposition*/
7019 create_options, /* create_options */
7020 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7021 0, /* oplock_request */
7022 0, /* allocation_size */
7028 if (!NT_STATUS_IS_OK(status)) {
7033 * Don't lie to client. If we can't really delete due to
7034 * non-POSIX opens return SHARING_VIOLATION.
7037 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7040 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7041 "lock for file %s\n", fsp_str_dbg(fsp)));
7042 close_file(req, fsp, NORMAL_CLOSE);
7043 return NT_STATUS_INVALID_PARAMETER;
7047 * See if others still have the file open. If this is the case, then
7048 * don't delete. If all opens are POSIX delete we can set the delete
7049 * on close disposition.
7051 for (i=0; i<lck->num_share_modes; i++) {
7052 struct share_mode_entry *e = &lck->share_modes[i];
7053 if (is_valid_share_mode_entry(e)) {
7054 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7057 /* Fail with sharing violation. */
7058 close_file(req, fsp, NORMAL_CLOSE);
7060 return NT_STATUS_SHARING_VIOLATION;
7065 * Set the delete on close.
7067 status = smb_set_file_disposition_info(conn,
7073 if (!NT_STATUS_IS_OK(status)) {
7074 close_file(req, fsp, NORMAL_CLOSE);
7079 return close_file(req, fsp, NORMAL_CLOSE);
7082 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7083 struct smb_request *req,
7084 TALLOC_CTX *mem_ctx,
7085 uint16_t info_level,
7087 struct smb_filename *smb_fname,
7088 char **ppdata, int total_data,
7091 char *pdata = *ppdata;
7092 SMB_STRUCT_STAT sbuf;
7094 NTSTATUS status = NT_STATUS_OK;
7095 int data_return_size = 0;
7099 /* Set sbuf for use below. */
7100 sbuf = smb_fname->st;
7102 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7103 return NT_STATUS_INVALID_LEVEL;
7106 if (!CAN_WRITE(conn)) {
7107 /* Allow POSIX opens. The open path will deny
7108 * any non-readonly opens. */
7109 if (info_level != SMB_POSIX_PATH_OPEN) {
7110 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7114 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
7115 if (!NT_STATUS_IS_OK(status)) {
7119 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d totdata=%d\n",
7120 fname, fsp ? fsp->fnum : -1, info_level, total_data));
7122 switch (info_level) {
7124 case SMB_INFO_STANDARD:
7126 status = smb_set_info_standard(conn,
7134 case SMB_INFO_SET_EA:
7136 status = smb_info_set_ea(conn,
7144 case SMB_SET_FILE_BASIC_INFO:
7145 case SMB_FILE_BASIC_INFORMATION:
7147 status = smb_set_file_basic_info(conn,
7155 case SMB_FILE_ALLOCATION_INFORMATION:
7156 case SMB_SET_FILE_ALLOCATION_INFO:
7158 status = smb_set_file_allocation_info(conn, req,
7166 case SMB_FILE_END_OF_FILE_INFORMATION:
7167 case SMB_SET_FILE_END_OF_FILE_INFO:
7169 status = smb_set_file_end_of_file_info(conn, req,
7177 case SMB_FILE_DISPOSITION_INFORMATION:
7178 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7181 /* JRA - We used to just ignore this on a path ?
7182 * Shouldn't this be invalid level on a pathname
7185 if (tran_call != TRANSACT2_SETFILEINFO) {
7186 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7189 status = smb_set_file_disposition_info(conn,
7197 case SMB_FILE_POSITION_INFORMATION:
7199 status = smb_file_position_information(conn,
7206 /* From tridge Samba4 :
7207 * MODE_INFORMATION in setfileinfo (I have no
7208 * idea what "mode information" on a file is - it takes a value of 0,
7209 * 2, 4 or 6. What could it be?).
7212 case SMB_FILE_MODE_INFORMATION:
7214 status = smb_file_mode_information(conn,
7221 * CIFS UNIX extensions.
7224 case SMB_SET_FILE_UNIX_BASIC:
7226 status = smb_set_file_unix_basic(conn, req,
7234 case SMB_SET_FILE_UNIX_INFO2:
7236 status = smb_set_file_unix_info2(conn, req,
7244 case SMB_SET_FILE_UNIX_LINK:
7247 /* We must have a pathname for this. */
7248 return NT_STATUS_INVALID_LEVEL;
7250 status = smb_set_file_unix_link(conn, req, pdata,
7255 case SMB_SET_FILE_UNIX_HLINK:
7258 /* We must have a pathname for this. */
7259 return NT_STATUS_INVALID_LEVEL;
7261 status = smb_set_file_unix_hlink(conn, req,
7267 case SMB_FILE_RENAME_INFORMATION:
7269 status = smb_file_rename_information(conn, req,
7275 #if defined(HAVE_POSIX_ACLS)
7276 case SMB_SET_POSIX_ACL:
7278 status = smb_set_posix_acl(conn,
7288 case SMB_SET_POSIX_LOCK:
7291 return NT_STATUS_INVALID_LEVEL;
7293 status = smb_set_posix_lock(conn, req,
7294 pdata, total_data, fsp);
7298 case SMB_POSIX_PATH_OPEN:
7301 /* We must have a pathname for this. */
7302 return NT_STATUS_INVALID_LEVEL;
7305 status = smb_posix_open(conn, req,
7314 case SMB_POSIX_PATH_UNLINK:
7317 /* We must have a pathname for this. */
7318 return NT_STATUS_INVALID_LEVEL;
7321 status = smb_posix_unlink(conn, req,
7329 return NT_STATUS_INVALID_LEVEL;
7332 if (!NT_STATUS_IS_OK(status)) {
7336 *ret_data_size = data_return_size;
7337 return NT_STATUS_OK;
7340 /****************************************************************************
7341 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7342 ****************************************************************************/
7344 static void call_trans2setfilepathinfo(connection_struct *conn,
7345 struct smb_request *req,
7346 unsigned int tran_call,
7347 char **pparams, int total_params,
7348 char **ppdata, int total_data,
7349 unsigned int max_data_bytes)
7351 char *params = *pparams;
7352 char *pdata = *ppdata;
7354 struct smb_filename *smb_fname = NULL;
7355 files_struct *fsp = NULL;
7356 NTSTATUS status = NT_STATUS_OK;
7357 int data_return_size = 0;
7360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7364 if (tran_call == TRANSACT2_SETFILEINFO) {
7365 if (total_params < 4) {
7366 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7370 fsp = file_fsp(req, SVAL(params,0));
7371 /* Basic check for non-null fsp. */
7372 if (!check_fsp_open(conn, req, fsp)) {
7375 info_level = SVAL(params,2);
7377 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7379 if (!NT_STATUS_IS_OK(status)) {
7380 reply_nterror(req, status);
7384 if(fsp->is_directory || fsp->fh->fd == -1) {
7386 * This is actually a SETFILEINFO on a directory
7387 * handle (returned from an NT SMB). NT5.0 seems
7388 * to do this call. JRA.
7390 if (INFO_LEVEL_IS_UNIX(info_level)) {
7391 /* Always do lstat for UNIX calls. */
7392 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7393 DEBUG(3,("call_trans2setfilepathinfo: "
7394 "SMB_VFS_LSTAT of %s failed "
7396 smb_fname_str_dbg(smb_fname),
7398 reply_nterror(req, map_nt_error_from_unix(errno));
7402 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7403 DEBUG(3,("call_trans2setfilepathinfo: "
7404 "fileinfo of %s failed (%s)\n",
7405 smb_fname_str_dbg(smb_fname),
7407 reply_nterror(req, map_nt_error_from_unix(errno));
7411 } else if (fsp->print_file) {
7413 * Doing a DELETE_ON_CLOSE should cancel a print job.
7415 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7416 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7418 DEBUG(3,("call_trans2setfilepathinfo: "
7419 "Cancelling print job (%s)\n",
7423 send_trans2_replies(conn, req, params, 2,
7428 reply_doserror(req, ERRDOS, ERRbadpath);
7433 * Original code - this is an open file.
7435 if (!check_fsp(conn, req, fsp)) {
7439 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7440 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7441 "of fnum %d failed (%s)\n", fsp->fnum,
7443 reply_nterror(req, map_nt_error_from_unix(errno));
7451 if (total_params < 7) {
7452 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7456 info_level = SVAL(params,0);
7457 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7458 total_params - 6, STR_TERMINATE,
7460 if (!NT_STATUS_IS_OK(status)) {
7461 reply_nterror(req, status);
7465 status = filename_convert(req, conn,
7466 req->flags2 & FLAGS2_DFS_PATHNAMES,
7470 if (!NT_STATUS_IS_OK(status)) {
7471 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7472 reply_botherror(req,
7473 NT_STATUS_PATH_NOT_COVERED,
7474 ERRSRV, ERRbadpath);
7477 reply_nterror(req, status);
7481 if (INFO_LEVEL_IS_UNIX(info_level)) {
7483 * For CIFS UNIX extensions the target name may not exist.
7486 /* Always do lstat for UNIX calls. */
7487 SMB_VFS_LSTAT(conn, smb_fname);
7489 } else if (!VALID_STAT(smb_fname->st) &&
7490 SMB_VFS_STAT(conn, smb_fname)) {
7491 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7493 smb_fname_str_dbg(smb_fname),
7495 reply_nterror(req, map_nt_error_from_unix(errno));
7500 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7501 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7502 fsp ? fsp->fnum : -1, info_level,total_data));
7504 /* Realloc the parameter size */
7505 *pparams = (char *)SMB_REALLOC(*pparams,2);
7506 if (*pparams == NULL) {
7507 reply_nterror(req, NT_STATUS_NO_MEMORY);
7514 status = smbd_do_setfilepathinfo(conn, req, req,
7520 if (!NT_STATUS_IS_OK(status)) {
7521 if (open_was_deferred(req->mid)) {
7522 /* We have re-scheduled this call. */
7525 if (blocking_lock_was_deferred(req->mid)) {
7526 /* We have re-scheduled this call. */
7529 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7530 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7531 ERRSRV, ERRbadpath);
7534 if (info_level == SMB_POSIX_PATH_OPEN) {
7535 reply_openerror(req, status);
7539 reply_nterror(req, status);
7543 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7549 /****************************************************************************
7550 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7551 ****************************************************************************/
7553 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7554 char **pparams, int total_params,
7555 char **ppdata, int total_data,
7556 unsigned int max_data_bytes)
7558 struct smb_filename *smb_dname = NULL;
7559 char *params = *pparams;
7560 char *pdata = *ppdata;
7561 char *directory = NULL;
7562 NTSTATUS status = NT_STATUS_OK;
7563 struct ea_list *ea_list = NULL;
7564 TALLOC_CTX *ctx = talloc_tos();
7566 if (!CAN_WRITE(conn)) {
7567 reply_doserror(req, ERRSRV, ERRaccess);
7571 if (total_params < 5) {
7572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7576 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7577 total_params - 4, STR_TERMINATE,
7579 if (!NT_STATUS_IS_OK(status)) {
7580 reply_nterror(req, status);
7584 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7586 status = filename_convert(ctx,
7588 req->flags2 & FLAGS2_DFS_PATHNAMES,
7593 if (!NT_STATUS_IS_OK(status)) {
7594 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7595 reply_botherror(req,
7596 NT_STATUS_PATH_NOT_COVERED,
7597 ERRSRV, ERRbadpath);
7600 reply_nterror(req, status);
7604 /* Any data in this call is an EA list. */
7605 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7606 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7611 * OS/2 workplace shell seems to send SET_EA requests of "null"
7612 * length (4 bytes containing IVAL 4).
7613 * They seem to have no effect. Bug #3212. JRA.
7616 if (total_data != 4) {
7617 if (total_data < 10) {
7618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7622 if (IVAL(pdata,0) > total_data) {
7623 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7624 IVAL(pdata,0), (unsigned int)total_data));
7625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7629 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7636 /* If total_data == 4 Windows doesn't care what values
7637 * are placed in that field, it just ignores them.
7638 * The System i QNTC IBM SMB client puts bad values here,
7639 * so ignore them. */
7641 status = create_directory(conn, req, smb_dname);
7643 if (!NT_STATUS_IS_OK(status)) {
7644 reply_nterror(req, status);
7648 /* Try and set any given EA. */
7650 status = set_ea(conn, NULL, smb_dname, ea_list);
7651 if (!NT_STATUS_IS_OK(status)) {
7652 reply_nterror(req, status);
7657 /* Realloc the parameter and data sizes */
7658 *pparams = (char *)SMB_REALLOC(*pparams,2);
7659 if(*pparams == NULL) {
7660 reply_nterror(req, NT_STATUS_NO_MEMORY);
7667 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7670 TALLOC_FREE(smb_dname);
7674 /****************************************************************************
7675 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7676 We don't actually do this - we just send a null response.
7677 ****************************************************************************/
7679 static void call_trans2findnotifyfirst(connection_struct *conn,
7680 struct smb_request *req,
7681 char **pparams, int total_params,
7682 char **ppdata, int total_data,
7683 unsigned int max_data_bytes)
7685 char *params = *pparams;
7688 if (total_params < 6) {
7689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7693 info_level = SVAL(params,4);
7694 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7696 switch (info_level) {
7701 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7705 /* Realloc the parameter and data sizes */
7706 *pparams = (char *)SMB_REALLOC(*pparams,6);
7707 if (*pparams == NULL) {
7708 reply_nterror(req, NT_STATUS_NO_MEMORY);
7713 SSVAL(params,0,fnf_handle);
7714 SSVAL(params,2,0); /* No changes */
7715 SSVAL(params,4,0); /* No EA errors */
7722 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7727 /****************************************************************************
7728 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7729 changes). Currently this does nothing.
7730 ****************************************************************************/
7732 static void call_trans2findnotifynext(connection_struct *conn,
7733 struct smb_request *req,
7734 char **pparams, int total_params,
7735 char **ppdata, int total_data,
7736 unsigned int max_data_bytes)
7738 char *params = *pparams;
7740 DEBUG(3,("call_trans2findnotifynext\n"));
7742 /* Realloc the parameter and data sizes */
7743 *pparams = (char *)SMB_REALLOC(*pparams,4);
7744 if (*pparams == NULL) {
7745 reply_nterror(req, NT_STATUS_NO_MEMORY);
7750 SSVAL(params,0,0); /* No changes */
7751 SSVAL(params,2,0); /* No EA errors */
7753 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7758 /****************************************************************************
7759 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7760 ****************************************************************************/
7762 static void call_trans2getdfsreferral(connection_struct *conn,
7763 struct smb_request *req,
7764 char **pparams, int total_params,
7765 char **ppdata, int total_data,
7766 unsigned int max_data_bytes)
7768 char *params = *pparams;
7769 char *pathname = NULL;
7771 int max_referral_level;
7772 NTSTATUS status = NT_STATUS_OK;
7773 TALLOC_CTX *ctx = talloc_tos();
7775 DEBUG(10,("call_trans2getdfsreferral\n"));
7777 if (total_params < 3) {
7778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7782 max_referral_level = SVAL(params,0);
7784 if(!lp_host_msdfs()) {
7785 reply_doserror(req, ERRDOS, ERRbadfunc);
7789 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7790 total_params - 2, STR_TERMINATE);
7792 reply_nterror(req, NT_STATUS_NOT_FOUND);
7795 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7796 ppdata,&status)) < 0) {
7797 reply_nterror(req, status);
7801 SSVAL(req->inbuf, smb_flg2,
7802 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7803 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7808 #define LMCAT_SPL 0x53
7809 #define LMFUNC_GETJOBID 0x60
7811 /****************************************************************************
7812 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7813 ****************************************************************************/
7815 static void call_trans2ioctl(connection_struct *conn,
7816 struct smb_request *req,
7817 char **pparams, int total_params,
7818 char **ppdata, int total_data,
7819 unsigned int max_data_bytes)
7821 char *pdata = *ppdata;
7822 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7824 /* check for an invalid fid before proceeding */
7827 reply_doserror(req, ERRDOS, ERRbadfid);
7831 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7832 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7833 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7834 if (*ppdata == NULL) {
7835 reply_nterror(req, NT_STATUS_NO_MEMORY);
7840 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7841 CAN ACCEPT THIS IN UNICODE. JRA. */
7843 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7844 srvstr_push(pdata, req->flags2, pdata + 2,
7845 global_myname(), 15,
7846 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7847 srvstr_push(pdata, req->flags2, pdata+18,
7848 lp_servicename(SNUM(conn)), 13,
7849 STR_ASCII|STR_TERMINATE); /* Service name */
7850 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7855 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7856 reply_doserror(req, ERRSRV, ERRerror);
7859 /****************************************************************************
7860 Reply to a SMBfindclose (stop trans2 directory search).
7861 ****************************************************************************/
7863 void reply_findclose(struct smb_request *req)
7867 START_PROFILE(SMBfindclose);
7870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7871 END_PROFILE(SMBfindclose);
7875 dptr_num = SVALS(req->vwv+0, 0);
7877 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7879 dptr_close(&dptr_num);
7881 reply_outbuf(req, 0, 0);
7883 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7885 END_PROFILE(SMBfindclose);
7889 /****************************************************************************
7890 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7891 ****************************************************************************/
7893 void reply_findnclose(struct smb_request *req)
7897 START_PROFILE(SMBfindnclose);
7900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7901 END_PROFILE(SMBfindnclose);
7905 dptr_num = SVAL(req->vwv+0, 0);
7907 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7909 /* We never give out valid handles for a
7910 findnotifyfirst - so any dptr_num is ok here.
7913 reply_outbuf(req, 0, 0);
7915 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7917 END_PROFILE(SMBfindnclose);
7921 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7922 struct trans_state *state)
7924 if (Protocol >= PROTOCOL_NT1) {
7925 req->flags2 |= 0x40; /* IS_LONG_NAME */
7926 SSVAL(req->inbuf,smb_flg2,req->flags2);
7929 if (conn->encrypt_level == Required && !req->encrypted) {
7930 if (state->call != TRANSACT2_QFSINFO &&
7931 state->call != TRANSACT2_SETFSINFO) {
7932 DEBUG(0,("handle_trans2: encryption required "
7934 (unsigned int)state->call));
7935 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7940 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7942 /* Now we must call the relevant TRANS2 function */
7943 switch(state->call) {
7944 case TRANSACT2_OPEN:
7946 START_PROFILE(Trans2_open);
7947 call_trans2open(conn, req,
7948 &state->param, state->total_param,
7949 &state->data, state->total_data,
7950 state->max_data_return);
7951 END_PROFILE(Trans2_open);
7955 case TRANSACT2_FINDFIRST:
7957 START_PROFILE(Trans2_findfirst);
7958 call_trans2findfirst(conn, req,
7959 &state->param, state->total_param,
7960 &state->data, state->total_data,
7961 state->max_data_return);
7962 END_PROFILE(Trans2_findfirst);
7966 case TRANSACT2_FINDNEXT:
7968 START_PROFILE(Trans2_findnext);
7969 call_trans2findnext(conn, req,
7970 &state->param, state->total_param,
7971 &state->data, state->total_data,
7972 state->max_data_return);
7973 END_PROFILE(Trans2_findnext);
7977 case TRANSACT2_QFSINFO:
7979 START_PROFILE(Trans2_qfsinfo);
7980 call_trans2qfsinfo(conn, req,
7981 &state->param, state->total_param,
7982 &state->data, state->total_data,
7983 state->max_data_return);
7984 END_PROFILE(Trans2_qfsinfo);
7988 case TRANSACT2_SETFSINFO:
7990 START_PROFILE(Trans2_setfsinfo);
7991 call_trans2setfsinfo(conn, req,
7992 &state->param, state->total_param,
7993 &state->data, state->total_data,
7994 state->max_data_return);
7995 END_PROFILE(Trans2_setfsinfo);
7999 case TRANSACT2_QPATHINFO:
8000 case TRANSACT2_QFILEINFO:
8002 START_PROFILE(Trans2_qpathinfo);
8003 call_trans2qfilepathinfo(conn, req, state->call,
8004 &state->param, state->total_param,
8005 &state->data, state->total_data,
8006 state->max_data_return);
8007 END_PROFILE(Trans2_qpathinfo);
8011 case TRANSACT2_SETPATHINFO:
8012 case TRANSACT2_SETFILEINFO:
8014 START_PROFILE(Trans2_setpathinfo);
8015 call_trans2setfilepathinfo(conn, req, state->call,
8016 &state->param, state->total_param,
8017 &state->data, state->total_data,
8018 state->max_data_return);
8019 END_PROFILE(Trans2_setpathinfo);
8023 case TRANSACT2_FINDNOTIFYFIRST:
8025 START_PROFILE(Trans2_findnotifyfirst);
8026 call_trans2findnotifyfirst(conn, req,
8027 &state->param, state->total_param,
8028 &state->data, state->total_data,
8029 state->max_data_return);
8030 END_PROFILE(Trans2_findnotifyfirst);
8034 case TRANSACT2_FINDNOTIFYNEXT:
8036 START_PROFILE(Trans2_findnotifynext);
8037 call_trans2findnotifynext(conn, req,
8038 &state->param, state->total_param,
8039 &state->data, state->total_data,
8040 state->max_data_return);
8041 END_PROFILE(Trans2_findnotifynext);
8045 case TRANSACT2_MKDIR:
8047 START_PROFILE(Trans2_mkdir);
8048 call_trans2mkdir(conn, req,
8049 &state->param, state->total_param,
8050 &state->data, state->total_data,
8051 state->max_data_return);
8052 END_PROFILE(Trans2_mkdir);
8056 case TRANSACT2_GET_DFS_REFERRAL:
8058 START_PROFILE(Trans2_get_dfs_referral);
8059 call_trans2getdfsreferral(conn, req,
8060 &state->param, state->total_param,
8061 &state->data, state->total_data,
8062 state->max_data_return);
8063 END_PROFILE(Trans2_get_dfs_referral);
8067 case TRANSACT2_IOCTL:
8069 START_PROFILE(Trans2_ioctl);
8070 call_trans2ioctl(conn, req,
8071 &state->param, state->total_param,
8072 &state->data, state->total_data,
8073 state->max_data_return);
8074 END_PROFILE(Trans2_ioctl);
8079 /* Error in request */
8080 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8081 reply_doserror(req, ERRSRV,ERRerror);
8085 /****************************************************************************
8086 Reply to a SMBtrans2.
8087 ****************************************************************************/
8089 void reply_trans2(struct smb_request *req)
8091 connection_struct *conn = req->conn;
8096 unsigned int tran_call;
8097 struct trans_state *state;
8100 START_PROFILE(SMBtrans2);
8102 if (req->wct < 14) {
8103 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8104 END_PROFILE(SMBtrans2);
8108 dsoff = SVAL(req->vwv+12, 0);
8109 dscnt = SVAL(req->vwv+11, 0);
8110 psoff = SVAL(req->vwv+10, 0);
8111 pscnt = SVAL(req->vwv+9, 0);
8112 tran_call = SVAL(req->vwv+14, 0);
8114 result = allow_new_trans(conn->pending_trans, req->mid);
8115 if (!NT_STATUS_IS_OK(result)) {
8116 DEBUG(2, ("Got invalid trans2 request: %s\n",
8117 nt_errstr(result)));
8118 reply_nterror(req, result);
8119 END_PROFILE(SMBtrans2);
8124 switch (tran_call) {
8125 /* List the allowed trans2 calls on IPC$ */
8126 case TRANSACT2_OPEN:
8127 case TRANSACT2_GET_DFS_REFERRAL:
8128 case TRANSACT2_QFILEINFO:
8129 case TRANSACT2_QFSINFO:
8130 case TRANSACT2_SETFSINFO:
8133 reply_doserror(req, ERRSRV, ERRaccess);
8134 END_PROFILE(SMBtrans2);
8139 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8140 DEBUG(0, ("talloc failed\n"));
8141 reply_nterror(req, NT_STATUS_NO_MEMORY);
8142 END_PROFILE(SMBtrans2);
8146 state->cmd = SMBtrans2;
8148 state->mid = req->mid;
8149 state->vuid = req->vuid;
8150 state->setup_count = SVAL(req->vwv+13, 0);
8151 state->setup = NULL;
8152 state->total_param = SVAL(req->vwv+0, 0);
8153 state->param = NULL;
8154 state->total_data = SVAL(req->vwv+1, 0);
8156 state->max_param_return = SVAL(req->vwv+2, 0);
8157 state->max_data_return = SVAL(req->vwv+3, 0);
8158 state->max_setup_return = SVAL(req->vwv+4, 0);
8159 state->close_on_completion = BITSETW(req->vwv+5, 0);
8160 state->one_way = BITSETW(req->vwv+5, 1);
8162 state->call = tran_call;
8164 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8165 is so as a sanity check */
8166 if (state->setup_count != 1) {
8168 * Need to have rc=0 for ioctl to get job id for OS/2.
8169 * Network printing will fail if function is not successful.
8170 * Similar function in reply.c will be used if protocol
8171 * is LANMAN1.0 instead of LM1.2X002.
8172 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8173 * outbuf doesn't have to be set(only job id is used).
8175 if ( (state->setup_count == 4)
8176 && (tran_call == TRANSACT2_IOCTL)
8177 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8178 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8179 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8181 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8182 DEBUG(2,("Transaction is %d\n",tran_call));
8184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8185 END_PROFILE(SMBtrans2);
8190 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8193 if (state->total_data) {
8195 if (trans_oob(state->total_data, 0, dscnt)
8196 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8200 /* Can't use talloc here, the core routines do realloc on the
8201 * params and data. */
8202 state->data = (char *)SMB_MALLOC(state->total_data);
8203 if (state->data == NULL) {
8204 DEBUG(0,("reply_trans2: data malloc fail for %u "
8205 "bytes !\n", (unsigned int)state->total_data));
8207 reply_nterror(req, NT_STATUS_NO_MEMORY);
8208 END_PROFILE(SMBtrans2);
8212 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8215 if (state->total_param) {
8217 if (trans_oob(state->total_param, 0, pscnt)
8218 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8222 /* Can't use talloc here, the core routines do realloc on the
8223 * params and data. */
8224 state->param = (char *)SMB_MALLOC(state->total_param);
8225 if (state->param == NULL) {
8226 DEBUG(0,("reply_trans: param malloc fail for %u "
8227 "bytes !\n", (unsigned int)state->total_param));
8228 SAFE_FREE(state->data);
8230 reply_nterror(req, NT_STATUS_NO_MEMORY);
8231 END_PROFILE(SMBtrans2);
8235 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8238 state->received_data = dscnt;
8239 state->received_param = pscnt;
8241 if ((state->received_param == state->total_param) &&
8242 (state->received_data == state->total_data)) {
8244 handle_trans2(conn, req, state);
8246 SAFE_FREE(state->data);
8247 SAFE_FREE(state->param);
8249 END_PROFILE(SMBtrans2);
8253 DLIST_ADD(conn->pending_trans, state);
8255 /* We need to send an interim response then receive the rest
8256 of the parameter/data bytes */
8257 reply_outbuf(req, 0, 0);
8258 show_msg((char *)req->outbuf);
8259 END_PROFILE(SMBtrans2);
8264 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8265 SAFE_FREE(state->data);
8266 SAFE_FREE(state->param);
8268 END_PROFILE(SMBtrans2);
8269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8273 /****************************************************************************
8274 Reply to a SMBtranss2
8275 ****************************************************************************/
8277 void reply_transs2(struct smb_request *req)
8279 connection_struct *conn = req->conn;
8280 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8281 struct trans_state *state;
8283 START_PROFILE(SMBtranss2);
8285 show_msg((char *)req->inbuf);
8288 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8289 END_PROFILE(SMBtranss2);
8293 for (state = conn->pending_trans; state != NULL;
8294 state = state->next) {
8295 if (state->mid == req->mid) {
8300 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8302 END_PROFILE(SMBtranss2);
8306 /* Revise state->total_param and state->total_data in case they have
8307 changed downwards */
8309 if (SVAL(req->vwv+0, 0) < state->total_param)
8310 state->total_param = SVAL(req->vwv+0, 0);
8311 if (SVAL(req->vwv+1, 0) < state->total_data)
8312 state->total_data = SVAL(req->vwv+1, 0);
8314 pcnt = SVAL(req->vwv+2, 0);
8315 poff = SVAL(req->vwv+3, 0);
8316 pdisp = SVAL(req->vwv+4, 0);
8318 dcnt = SVAL(req->vwv+5, 0);
8319 doff = SVAL(req->vwv+6, 0);
8320 ddisp = SVAL(req->vwv+7, 0);
8322 state->received_param += pcnt;
8323 state->received_data += dcnt;
8325 if ((state->received_data > state->total_data) ||
8326 (state->received_param > state->total_param))
8330 if (trans_oob(state->total_param, pdisp, pcnt)
8331 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8334 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8338 if (trans_oob(state->total_data, ddisp, dcnt)
8339 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8342 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8345 if ((state->received_param < state->total_param) ||
8346 (state->received_data < state->total_data)) {
8347 END_PROFILE(SMBtranss2);
8351 handle_trans2(conn, req, state);
8353 DLIST_REMOVE(conn->pending_trans, state);
8354 SAFE_FREE(state->data);
8355 SAFE_FREE(state->param);
8358 END_PROFILE(SMBtranss2);
8363 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8364 DLIST_REMOVE(conn->pending_trans, state);
8365 SAFE_FREE(state->data);
8366 SAFE_FREE(state->param);
8368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8369 END_PROFILE(SMBtranss2);