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->base_name, deny_mode,
1053 &create_disposition,
1055 reply_doserror(req, ERRDOS, ERRbadaccess);
1059 /* Any data in this call is an EA list. */
1060 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1061 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1065 if (total_data != 4) {
1066 if (total_data < 10) {
1067 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1071 if (IVAL(pdata,0) > total_data) {
1072 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1073 IVAL(pdata,0), (unsigned int)total_data));
1074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1078 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1084 } else if (IVAL(pdata,0) != 4) {
1085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1089 status = SMB_VFS_CREATE_FILE(
1092 0, /* root_dir_fid */
1093 smb_fname, /* fname */
1094 access_mask, /* access_mask */
1095 share_mode, /* share_access */
1096 create_disposition, /* create_disposition*/
1097 create_options, /* create_options */
1098 open_attr, /* file_attributes */
1099 oplock_request, /* oplock_request */
1100 open_size, /* allocation_size */
1102 ea_list, /* ea_list */
1104 &smb_action); /* psbuf */
1106 if (!NT_STATUS_IS_OK(status)) {
1107 if (open_was_deferred(req->mid)) {
1108 /* We have re-scheduled this call. */
1111 reply_openerror(req, status);
1115 size = get_file_size_stat(&smb_fname->st);
1116 fattr = dos_mode(conn, smb_fname);
1117 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1118 inode = smb_fname->st.st_ex_ino;
1120 close_file(req, fsp, ERROR_CLOSE);
1121 reply_doserror(req, ERRDOS,ERRnoaccess);
1125 /* Realloc the size of parameters and data we will return */
1126 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1127 if(*pparams == NULL ) {
1128 reply_nterror(req, NT_STATUS_NO_MEMORY);
1133 SSVAL(params,0,fsp->fnum);
1134 SSVAL(params,2,fattr);
1135 srv_put_dos_date2(params,4, mtime);
1136 SIVAL(params,8, (uint32)size);
1137 SSVAL(params,12,deny_mode);
1138 SSVAL(params,14,0); /* open_type - file or directory. */
1139 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1141 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1142 smb_action |= EXTENDED_OPLOCK_GRANTED;
1145 SSVAL(params,18,smb_action);
1148 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1150 SIVAL(params,20,inode);
1151 SSVAL(params,24,0); /* Padding. */
1153 uint32 ea_size = estimate_ea_size(conn, fsp,
1154 fsp->fsp_name->base_name);
1155 SIVAL(params, 26, ea_size);
1157 SIVAL(params, 26, 0);
1160 /* Send the required number of replies */
1161 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1163 TALLOC_FREE(smb_fname);
1166 /*********************************************************
1167 Routine to check if a given string matches exactly.
1168 as a special case a mask of "." does NOT match. That
1169 is required for correct wildcard semantics
1170 Case can be significant or not.
1171 **********************************************************/
1173 static bool exact_match(connection_struct *conn,
1177 if (mask[0] == '.' && mask[1] == 0)
1179 if (dptr_has_wild(conn->dirptr)) {
1182 if (conn->case_sensitive)
1183 return strcmp(str,mask)==0;
1185 return StrCaseCmp(str,mask) == 0;
1188 /****************************************************************************
1189 Return the filetype for UNIX extensions.
1190 ****************************************************************************/
1192 static uint32 unix_filetype(mode_t mode)
1195 return UNIX_TYPE_FILE;
1196 else if(S_ISDIR(mode))
1197 return UNIX_TYPE_DIR;
1199 else if(S_ISLNK(mode))
1200 return UNIX_TYPE_SYMLINK;
1203 else if(S_ISCHR(mode))
1204 return UNIX_TYPE_CHARDEV;
1207 else if(S_ISBLK(mode))
1208 return UNIX_TYPE_BLKDEV;
1211 else if(S_ISFIFO(mode))
1212 return UNIX_TYPE_FIFO;
1215 else if(S_ISSOCK(mode))
1216 return UNIX_TYPE_SOCKET;
1219 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1220 return UNIX_TYPE_UNKNOWN;
1223 /****************************************************************************
1224 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1225 ****************************************************************************/
1227 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1229 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1230 const SMB_STRUCT_STAT *psbuf,
1232 enum perm_type ptype,
1237 if (perms == SMB_MODE_NO_CHANGE) {
1238 if (!VALID_STAT(*psbuf)) {
1239 return NT_STATUS_INVALID_PARAMETER;
1241 *ret_perms = psbuf->st_ex_mode;
1242 return NT_STATUS_OK;
1246 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1247 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1248 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1249 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1250 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1251 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1252 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1253 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1254 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1256 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1259 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1262 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1267 /* Apply mode mask */
1268 ret &= lp_create_mask(SNUM(conn));
1269 /* Add in force bits */
1270 ret |= lp_force_create_mode(SNUM(conn));
1273 ret &= lp_dir_mask(SNUM(conn));
1274 /* Add in force bits */
1275 ret |= lp_force_dir_mode(SNUM(conn));
1277 case PERM_EXISTING_FILE:
1278 /* Apply mode mask */
1279 ret &= lp_security_mask(SNUM(conn));
1280 /* Add in force bits */
1281 ret |= lp_force_security_mode(SNUM(conn));
1283 case PERM_EXISTING_DIR:
1284 /* Apply mode mask */
1285 ret &= lp_dir_security_mask(SNUM(conn));
1286 /* Add in force bits */
1287 ret |= lp_force_dir_security_mode(SNUM(conn));
1292 return NT_STATUS_OK;
1295 /****************************************************************************
1296 Needed to show the msdfs symlinks as directories. Modifies psbuf
1297 to be a directory if it's a msdfs link.
1298 ****************************************************************************/
1300 static bool check_msdfs_link(connection_struct *conn,
1301 const char *pathname,
1302 SMB_STRUCT_STAT *psbuf)
1304 int saved_errno = errno;
1305 if(lp_host_msdfs() &&
1306 lp_msdfs_root(SNUM(conn)) &&
1307 is_msdfs_link(conn, pathname, psbuf)) {
1309 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1312 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1313 errno = saved_errno;
1316 errno = saved_errno;
1321 /****************************************************************************
1322 Get a level dependent lanman2 dir entry.
1323 ****************************************************************************/
1325 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1326 connection_struct *conn,
1328 const char *path_mask,
1331 int requires_resume_key,
1337 int space_remaining,
1339 bool *got_exact_match,
1340 int *last_entry_off,
1341 struct ea_list *name_list)
1345 SMB_STRUCT_STAT sbuf;
1346 const char *mask = NULL;
1347 char *pathreal = NULL;
1349 char *p, *q, *pdata = *ppdata;
1353 SMB_OFF_T file_size = 0;
1354 uint64_t allocation_size = 0;
1356 struct timespec mdate_ts, adate_ts, create_date_ts;
1357 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1359 char *last_entry_ptr;
1361 uint32 nt_extmode; /* Used for NT connections instead of mode */
1362 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1363 bool check_mangled_names = lp_manglednames(conn->params);
1364 char mangled_name[13]; /* mangled 8.3 name. */
1366 *out_of_space = False;
1367 *got_exact_match = False;
1369 ZERO_STRUCT(mdate_ts);
1370 ZERO_STRUCT(adate_ts);
1371 ZERO_STRUCT(create_date_ts);
1373 if (!conn->dirptr) {
1377 p = strrchr_m(path_mask,'/');
1380 mask = talloc_strdup(ctx,"*.*");
1390 bool ms_dfs_link = False;
1392 /* Needed if we run out of space */
1393 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1394 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1397 * Due to bugs in NT client redirectors we are not using
1398 * resume keys any more - set them to zero.
1399 * Check out the related comments in findfirst/findnext.
1405 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1406 (long)conn->dirptr,curr_dirpos));
1413 * fname may get mangled, dname is never mangled.
1414 * Whenever we're accessing the filesystem we use
1415 * pathreal which is composed from dname.
1421 /* Mangle fname if it's an illegal name. */
1422 if (mangle_must_mangle(dname,conn->params)) {
1423 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1425 continue; /* Error - couldn't mangle. */
1427 fname = talloc_strdup(ctx, mangled_name);
1433 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1434 got_match = mask_match(fname, mask, conn->case_sensitive);
1437 if(!got_match && check_mangled_names &&
1438 !mangle_is_8_3(fname, False, conn->params)) {
1440 * It turns out that NT matches wildcards against
1441 * both long *and* short names. This may explain some
1442 * of the wildcard wierdness from old DOS clients
1443 * that some people have been seeing.... JRA.
1445 /* Force the mangling into 8.3. */
1446 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1448 continue; /* Error - couldn't mangle. */
1451 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1452 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1457 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1458 struct smb_filename *smb_fname = NULL;
1461 if (dont_descend && !isdots) {
1468 pathreal = talloc_asprintf(ctx,
1473 pathreal = talloc_asprintf(ctx,
1484 /* A dirent from dptr_ReadDirName isn't a stream. */
1485 status = create_synthetic_smb_fname(ctx, pathreal,
1488 if (!NT_STATUS_IS_OK(status)) {
1493 if (INFO_LEVEL_IS_UNIX(info_level)) {
1494 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
1495 DEBUG(5,("get_lanman2_dir_entry: "
1496 "Couldn't lstat [%s] (%s)\n",
1497 smb_fname_str_dbg(smb_fname),
1499 TALLOC_FREE(smb_fname);
1500 TALLOC_FREE(pathreal);
1504 } else if (!VALID_STAT(smb_fname->st) &&
1505 SMB_VFS_STAT(conn, smb_fname) != 0) {
1506 /* Needed to show the msdfs symlinks as
1510 check_msdfs_link(conn,
1511 smb_fname->base_name,
1514 DEBUG(5,("get_lanman2_dir_entry: "
1515 "Couldn't stat [%s] (%s)\n",
1516 smb_fname_str_dbg(smb_fname),
1518 TALLOC_FREE(smb_fname);
1519 TALLOC_FREE(pathreal);
1526 mode = dos_mode_msdfs(conn, smb_fname);
1528 mode = dos_mode(conn, smb_fname);
1531 if (!dir_check_ftype(conn,mode,dirtype)) {
1532 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1533 TALLOC_FREE(smb_fname);
1534 TALLOC_FREE(pathreal);
1539 if (!(mode & aDIR)) {
1540 file_size = get_file_size_stat(&smb_fname->st);
1543 SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1545 if (ask_sharemode) {
1546 struct timespec write_time_ts;
1547 struct file_id fileid;
1549 ZERO_STRUCT(write_time_ts);
1550 fileid = vfs_file_id_from_sbuf(conn,
1552 get_file_infos(fileid, NULL, &write_time_ts);
1553 if (!null_timespec(write_time_ts)) {
1554 update_stat_ex_mtime(&smb_fname->st,
1559 mdate_ts = smb_fname->st.st_ex_mtime;
1560 adate_ts = smb_fname->st.st_ex_atime;
1561 create_date_ts = smb_fname->st.st_ex_btime;
1563 if (lp_dos_filetime_resolution(SNUM(conn))) {
1564 dos_filetime_timespec(&create_date_ts);
1565 dos_filetime_timespec(&mdate_ts);
1566 dos_filetime_timespec(&adate_ts);
1569 create_date = convert_timespec_to_time_t(create_date_ts);
1570 mdate = convert_timespec_to_time_t(mdate_ts);
1571 adate = convert_timespec_to_time_t(adate_ts);
1573 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1574 smb_fname_str_dbg(smb_fname), fname));
1578 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1579 sbuf = smb_fname->st;
1581 TALLOC_FREE(smb_fname);
1591 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1593 switch (info_level) {
1594 case SMB_FIND_INFO_STANDARD:
1595 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1596 if(requires_resume_key) {
1600 srv_put_dos_date2(p,0,create_date);
1601 srv_put_dos_date2(p,4,adate);
1602 srv_put_dos_date2(p,8,mdate);
1603 SIVAL(p,12,(uint32)file_size);
1604 SIVAL(p,16,(uint32)allocation_size);
1608 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1609 p += ucs2_align(base_data, p, 0);
1611 len = srvstr_push(base_data, flags2, p,
1612 fname, PTR_DIFF(end_data, p),
1614 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1616 SCVAL(nameptr, -1, len - 2);
1618 SCVAL(nameptr, -1, 0);
1622 SCVAL(nameptr, -1, len - 1);
1624 SCVAL(nameptr, -1, 0);
1630 case SMB_FIND_EA_SIZE:
1631 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1632 if(requires_resume_key) {
1636 srv_put_dos_date2(p,0,create_date);
1637 srv_put_dos_date2(p,4,adate);
1638 srv_put_dos_date2(p,8,mdate);
1639 SIVAL(p,12,(uint32)file_size);
1640 SIVAL(p,16,(uint32)allocation_size);
1643 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1644 SIVAL(p,22,ea_size); /* Extended attributes */
1648 len = srvstr_push(base_data, flags2,
1649 p, fname, PTR_DIFF(end_data, p),
1650 STR_TERMINATE | STR_NOALIGN);
1651 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1664 SCVAL(nameptr,0,len);
1666 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1669 case SMB_FIND_EA_LIST:
1671 struct ea_list *file_list = NULL;
1674 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1678 if(requires_resume_key) {
1682 srv_put_dos_date2(p,0,create_date);
1683 srv_put_dos_date2(p,4,adate);
1684 srv_put_dos_date2(p,8,mdate);
1685 SIVAL(p,12,(uint32)file_size);
1686 SIVAL(p,16,(uint32)allocation_size);
1688 p += 22; /* p now points to the EA area. */
1690 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1691 name_list = ea_list_union(name_list, file_list, &ea_len);
1693 /* We need to determine if this entry will fit in the space available. */
1694 /* Max string size is 255 bytes. */
1695 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1696 /* Move the dirptr back to prev_dirpos */
1697 dptr_SeekDir(conn->dirptr, prev_dirpos);
1698 *out_of_space = True;
1699 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1700 return False; /* Not finished - just out of space */
1703 /* Push the ea_data followed by the name. */
1704 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1706 len = srvstr_push(base_data, flags2,
1707 p + 1, fname, PTR_DIFF(end_data, p+1),
1708 STR_TERMINATE | STR_NOALIGN);
1709 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1722 SCVAL(nameptr,0,len);
1724 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1728 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1729 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1730 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1732 SIVAL(p,0,reskey); p += 4;
1733 put_long_date_timespec(p,create_date_ts); p += 8;
1734 put_long_date_timespec(p,adate_ts); p += 8;
1735 put_long_date_timespec(p,mdate_ts); p += 8;
1736 put_long_date_timespec(p,mdate_ts); p += 8;
1737 SOFF_T(p,0,file_size); p += 8;
1738 SOFF_T(p,0,allocation_size); p += 8;
1739 SIVAL(p,0,nt_extmode); p += 4;
1740 q = p; p += 4; /* q is placeholder for name length. */
1742 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1743 SIVAL(p,0,ea_size); /* Extended attributes */
1746 /* Clear the short name buffer. This is
1747 * IMPORTANT as not doing so will trigger
1748 * a Win2k client bug. JRA.
1750 if (!was_8_3 && check_mangled_names) {
1751 if (!name_to_8_3(fname,mangled_name,True,
1753 /* Error - mangle failed ! */
1754 memset(mangled_name,'\0',12);
1756 mangled_name[12] = 0;
1757 len = srvstr_push(base_data, flags2,
1758 p+2, mangled_name, 24,
1759 STR_UPPER|STR_UNICODE);
1761 memset(p + 2 + len,'\0',24 - len);
1768 len = srvstr_push(base_data, flags2, p,
1769 fname, PTR_DIFF(end_data, p),
1770 STR_TERMINATE_ASCII);
1773 SIVAL(p,0,0); /* Ensure any padding is null. */
1774 len = PTR_DIFF(p, pdata);
1775 len = (len + 3) & ~3;
1780 case SMB_FIND_FILE_DIRECTORY_INFO:
1781 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1783 SIVAL(p,0,reskey); p += 4;
1784 put_long_date_timespec(p,create_date_ts); p += 8;
1785 put_long_date_timespec(p,adate_ts); p += 8;
1786 put_long_date_timespec(p,mdate_ts); p += 8;
1787 put_long_date_timespec(p,mdate_ts); p += 8;
1788 SOFF_T(p,0,file_size); p += 8;
1789 SOFF_T(p,0,allocation_size); p += 8;
1790 SIVAL(p,0,nt_extmode); p += 4;
1791 len = srvstr_push(base_data, flags2,
1792 p + 4, fname, PTR_DIFF(end_data, p+4),
1793 STR_TERMINATE_ASCII);
1796 SIVAL(p,0,0); /* Ensure any padding is null. */
1797 len = PTR_DIFF(p, pdata);
1798 len = (len + 3) & ~3;
1803 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1804 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1806 SIVAL(p,0,reskey); p += 4;
1807 put_long_date_timespec(p,create_date_ts); p += 8;
1808 put_long_date_timespec(p,adate_ts); p += 8;
1809 put_long_date_timespec(p,mdate_ts); p += 8;
1810 put_long_date_timespec(p,mdate_ts); p += 8;
1811 SOFF_T(p,0,file_size); p += 8;
1812 SOFF_T(p,0,allocation_size); p += 8;
1813 SIVAL(p,0,nt_extmode); p += 4;
1814 q = p; p += 4; /* q is placeholder for name length. */
1816 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1817 SIVAL(p,0,ea_size); /* Extended attributes */
1820 len = srvstr_push(base_data, flags2, p,
1821 fname, PTR_DIFF(end_data, p),
1822 STR_TERMINATE_ASCII);
1826 SIVAL(p,0,0); /* Ensure any padding is null. */
1827 len = PTR_DIFF(p, pdata);
1828 len = (len + 3) & ~3;
1833 case SMB_FIND_FILE_NAMES_INFO:
1834 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1836 SIVAL(p,0,reskey); p += 4;
1838 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1839 acl on a dir (tridge) */
1840 len = srvstr_push(base_data, flags2, p,
1841 fname, PTR_DIFF(end_data, p),
1842 STR_TERMINATE_ASCII);
1845 SIVAL(p,0,0); /* Ensure any padding is null. */
1846 len = PTR_DIFF(p, pdata);
1847 len = (len + 3) & ~3;
1852 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1853 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1855 SIVAL(p,0,reskey); p += 4;
1856 put_long_date_timespec(p,create_date_ts); p += 8;
1857 put_long_date_timespec(p,adate_ts); p += 8;
1858 put_long_date_timespec(p,mdate_ts); p += 8;
1859 put_long_date_timespec(p,mdate_ts); p += 8;
1860 SOFF_T(p,0,file_size); p += 8;
1861 SOFF_T(p,0,allocation_size); p += 8;
1862 SIVAL(p,0,nt_extmode); p += 4;
1863 q = p; p += 4; /* q is placeholder for name length. */
1865 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1866 SIVAL(p,0,ea_size); /* Extended attributes */
1869 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1870 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1871 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1872 len = srvstr_push(base_data, flags2, p,
1873 fname, PTR_DIFF(end_data, p),
1874 STR_TERMINATE_ASCII);
1877 SIVAL(p,0,0); /* Ensure any padding is null. */
1878 len = PTR_DIFF(p, pdata);
1879 len = (len + 3) & ~3;
1884 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1885 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1886 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1888 SIVAL(p,0,reskey); p += 4;
1889 put_long_date_timespec(p,create_date_ts); p += 8;
1890 put_long_date_timespec(p,adate_ts); p += 8;
1891 put_long_date_timespec(p,mdate_ts); p += 8;
1892 put_long_date_timespec(p,mdate_ts); p += 8;
1893 SOFF_T(p,0,file_size); p += 8;
1894 SOFF_T(p,0,allocation_size); p += 8;
1895 SIVAL(p,0,nt_extmode); p += 4;
1896 q = p; p += 4; /* q is placeholder for name length */
1898 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1899 SIVAL(p,0,ea_size); /* Extended attributes */
1902 /* Clear the short name buffer. This is
1903 * IMPORTANT as not doing so will trigger
1904 * a Win2k client bug. JRA.
1906 if (!was_8_3 && check_mangled_names) {
1907 if (!name_to_8_3(fname,mangled_name,True,
1909 /* Error - mangle failed ! */
1910 memset(mangled_name,'\0',12);
1912 mangled_name[12] = 0;
1913 len = srvstr_push(base_data, flags2,
1914 p+2, mangled_name, 24,
1915 STR_UPPER|STR_UNICODE);
1918 memset(p + 2 + len,'\0',24 - len);
1925 SSVAL(p,0,0); p += 2; /* Reserved ? */
1926 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1927 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1928 len = srvstr_push(base_data, flags2, p,
1929 fname, PTR_DIFF(end_data, p),
1930 STR_TERMINATE_ASCII);
1933 SIVAL(p,0,0); /* Ensure any padding is null. */
1934 len = PTR_DIFF(p, pdata);
1935 len = (len + 3) & ~3;
1940 /* CIFS UNIX Extension. */
1942 case SMB_FIND_FILE_UNIX:
1943 case SMB_FIND_FILE_UNIX_INFO2:
1945 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1947 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1949 if (info_level == SMB_FIND_FILE_UNIX) {
1950 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1951 p = store_file_unix_basic(conn, p,
1953 len = srvstr_push(base_data, flags2, p,
1954 fname, PTR_DIFF(end_data, p),
1957 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1958 p = store_file_unix_basic_info2(conn, p,
1962 len = srvstr_push(base_data, flags2, p, fname,
1963 PTR_DIFF(end_data, p), 0);
1964 SIVAL(nameptr, 0, len);
1968 SIVAL(p,0,0); /* Ensure any padding is null. */
1970 len = PTR_DIFF(p, pdata);
1971 len = (len + 3) & ~3;
1972 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1974 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1984 if (PTR_DIFF(p,pdata) > space_remaining) {
1985 /* Move the dirptr back to prev_dirpos */
1986 dptr_SeekDir(conn->dirptr, prev_dirpos);
1987 *out_of_space = True;
1988 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1989 return False; /* Not finished - just out of space */
1992 /* Setup the last entry pointer, as an offset from base_data */
1993 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1994 /* Advance the data pointer to the next slot */
2000 /****************************************************************************
2001 Reply to a TRANS2_FINDFIRST.
2002 ****************************************************************************/
2004 static void call_trans2findfirst(connection_struct *conn,
2005 struct smb_request *req,
2006 char **pparams, int total_params,
2007 char **ppdata, int total_data,
2008 unsigned int max_data_bytes)
2010 /* We must be careful here that we don't return more than the
2011 allowed number of data bytes. If this means returning fewer than
2012 maxentries then so be it. We assume that the redirector has
2013 enough room for the fixed number of parameter bytes it has
2015 struct smb_filename *smb_dname = NULL;
2016 char *params = *pparams;
2017 char *pdata = *ppdata;
2021 uint16 findfirst_flags;
2022 bool close_after_first;
2024 bool requires_resume_key;
2026 char *directory = NULL;
2029 int last_entry_off=0;
2033 bool finished = False;
2034 bool dont_descend = False;
2035 bool out_of_space = False;
2036 int space_remaining;
2037 bool mask_contains_wcard = False;
2038 struct ea_list *ea_list = NULL;
2039 NTSTATUS ntstatus = NT_STATUS_OK;
2040 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2041 TALLOC_CTX *ctx = talloc_tos();
2043 if (total_params < 13) {
2044 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2048 dirtype = SVAL(params,0);
2049 maxentries = SVAL(params,2);
2050 findfirst_flags = SVAL(params,4);
2051 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2052 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2053 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2054 info_level = SVAL(params,6);
2056 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2057 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2058 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2059 info_level, max_data_bytes));
2062 /* W2K3 seems to treat zero as 1. */
2066 switch (info_level) {
2067 case SMB_FIND_INFO_STANDARD:
2068 case SMB_FIND_EA_SIZE:
2069 case SMB_FIND_EA_LIST:
2070 case SMB_FIND_FILE_DIRECTORY_INFO:
2071 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2072 case SMB_FIND_FILE_NAMES_INFO:
2073 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2074 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2075 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2077 case SMB_FIND_FILE_UNIX:
2078 case SMB_FIND_FILE_UNIX_INFO2:
2079 /* Always use filesystem for UNIX mtime query. */
2080 ask_sharemode = false;
2081 if (!lp_unix_extensions()) {
2082 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2087 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2091 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2092 params+12, total_params - 12,
2093 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2094 if (!NT_STATUS_IS_OK(ntstatus)) {
2095 reply_nterror(req, ntstatus);
2099 ntstatus = resolve_dfspath_wcard(ctx, conn,
2100 req->flags2 & FLAGS2_DFS_PATHNAMES,
2103 &mask_contains_wcard);
2104 if (!NT_STATUS_IS_OK(ntstatus)) {
2105 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2106 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2107 ERRSRV, ERRbadpath);
2110 reply_nterror(req, ntstatus);
2114 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2115 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2116 if (!NT_STATUS_IS_OK(ntstatus)) {
2117 reply_nterror(req, ntstatus);
2121 mask = smb_dname->original_lcomp;
2123 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2124 TALLOC_FREE(smb_dname);
2125 if (!NT_STATUS_IS_OK(ntstatus)) {
2126 reply_nterror(req, ntstatus);
2130 ntstatus = check_name(conn, directory);
2131 if (!NT_STATUS_IS_OK(ntstatus)) {
2132 reply_nterror(req, ntstatus);
2136 p = strrchr_m(directory,'/');
2138 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2139 if((directory[0] == '.') && (directory[1] == '\0')) {
2140 mask = talloc_strdup(ctx,"*");
2142 reply_nterror(req, NT_STATUS_NO_MEMORY);
2145 mask_contains_wcard = True;
2147 directory = talloc_strdup(talloc_tos(), "./");
2149 reply_nterror(req, NT_STATUS_NO_MEMORY);
2156 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2158 if (info_level == SMB_FIND_EA_LIST) {
2161 if (total_data < 4) {
2162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2166 ea_size = IVAL(pdata,0);
2167 if (ea_size != total_data) {
2168 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2169 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2174 if (!lp_ea_support(SNUM(conn))) {
2175 reply_doserror(req, ERRDOS, ERReasnotsupported);
2179 /* Pull out the list of names. */
2180 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2187 *ppdata = (char *)SMB_REALLOC(
2188 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2189 if(*ppdata == NULL ) {
2190 reply_nterror(req, NT_STATUS_NO_MEMORY);
2194 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2196 /* Realloc the params space */
2197 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2198 if (*pparams == NULL) {
2199 reply_nterror(req, NT_STATUS_NO_MEMORY);
2204 /* Save the wildcard match and attribs we are using on this directory -
2205 needed as lanman2 assumes these are being saved between calls */
2207 ntstatus = dptr_create(conn,
2213 mask_contains_wcard,
2217 if (!NT_STATUS_IS_OK(ntstatus)) {
2218 reply_nterror(req, ntstatus);
2222 dptr_num = dptr_dnum(conn->dirptr);
2223 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2225 /* Initialize per TRANS2_FIND_FIRST operation data */
2226 dptr_init_search_op(conn->dirptr);
2228 /* We don't need to check for VOL here as this is returned by
2229 a different TRANS2 call. */
2231 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2232 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2233 dont_descend = True;
2236 space_remaining = max_data_bytes;
2237 out_of_space = False;
2239 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2240 bool got_exact_match = False;
2242 /* this is a heuristic to avoid seeking the dirptr except when
2243 absolutely necessary. It allows for a filename of about 40 chars */
2244 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2245 out_of_space = True;
2248 finished = !get_lanman2_dir_entry(ctx,
2251 mask,dirtype,info_level,
2252 requires_resume_key,dont_descend,
2255 space_remaining, &out_of_space,
2257 &last_entry_off, ea_list);
2260 if (finished && out_of_space)
2263 if (!finished && !out_of_space)
2267 * As an optimisation if we know we aren't looking
2268 * for a wildcard name (ie. the name matches the wildcard exactly)
2269 * then we can finish on any (first) match.
2270 * This speeds up large directory searches. JRA.
2276 /* Ensure space_remaining never goes -ve. */
2277 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2278 space_remaining = 0;
2279 out_of_space = true;
2281 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2285 /* Check if we can close the dirptr */
2286 if(close_after_first || (finished && close_if_end)) {
2287 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2288 dptr_close(&dptr_num);
2292 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2293 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2294 * the protocol level is less than NT1. Tested with smbclient. JRA.
2295 * This should fix the OS/2 client bug #2335.
2298 if(numentries == 0) {
2299 dptr_close(&dptr_num);
2300 if (Protocol < PROTOCOL_NT1) {
2301 reply_doserror(req, ERRDOS, ERRnofiles);
2304 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2305 ERRDOS, ERRbadfile);
2310 /* At this point pdata points to numentries directory entries. */
2312 /* Set up the return parameter block */
2313 SSVAL(params,0,dptr_num);
2314 SSVAL(params,2,numentries);
2315 SSVAL(params,4,finished);
2316 SSVAL(params,6,0); /* Never an EA error */
2317 SSVAL(params,8,last_entry_off);
2319 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2322 if ((! *directory) && dptr_path(dptr_num)) {
2323 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2325 reply_nterror(req, NT_STATUS_NO_MEMORY);
2329 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2330 smb_fn_name(req->cmd),
2331 mask, directory, dirtype, numentries ) );
2334 * Force a name mangle here to ensure that the
2335 * mask as an 8.3 name is top of the mangled cache.
2336 * The reasons for this are subtle. Don't remove
2337 * this code unless you know what you are doing
2338 * (see PR#13758). JRA.
2341 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2342 char mangled_name[13];
2343 name_to_8_3(mask, mangled_name, True, conn->params);
2349 /****************************************************************************
2350 Reply to a TRANS2_FINDNEXT.
2351 ****************************************************************************/
2353 static void call_trans2findnext(connection_struct *conn,
2354 struct smb_request *req,
2355 char **pparams, int total_params,
2356 char **ppdata, int total_data,
2357 unsigned int max_data_bytes)
2359 /* We must be careful here that we don't return more than the
2360 allowed number of data bytes. If this means returning fewer than
2361 maxentries then so be it. We assume that the redirector has
2362 enough room for the fixed number of parameter bytes it has
2364 char *params = *pparams;
2365 char *pdata = *ppdata;
2371 uint16 findnext_flags;
2372 bool close_after_request;
2374 bool requires_resume_key;
2376 bool mask_contains_wcard = False;
2377 char *resume_name = NULL;
2378 const char *mask = NULL;
2379 const char *directory = NULL;
2383 int i, last_entry_off=0;
2384 bool finished = False;
2385 bool dont_descend = False;
2386 bool out_of_space = False;
2387 int space_remaining;
2388 struct ea_list *ea_list = NULL;
2389 NTSTATUS ntstatus = NT_STATUS_OK;
2390 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2391 TALLOC_CTX *ctx = talloc_tos();
2393 if (total_params < 13) {
2394 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2398 dptr_num = SVAL(params,0);
2399 maxentries = SVAL(params,2);
2400 info_level = SVAL(params,4);
2401 resume_key = IVAL(params,6);
2402 findnext_flags = SVAL(params,10);
2403 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2404 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2405 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2406 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2408 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2410 total_params - 12, STR_TERMINATE, &ntstatus,
2411 &mask_contains_wcard);
2412 if (!NT_STATUS_IS_OK(ntstatus)) {
2413 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2414 complain (it thinks we're asking for the directory above the shared
2415 path or an invalid name). Catch this as the resume name is only compared, never used in
2416 a file access. JRA. */
2417 srvstr_pull_talloc(ctx, params, req->flags2,
2418 &resume_name, params+12,
2422 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2423 reply_nterror(req, ntstatus);
2428 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2429 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2430 resume_key = %d resume name = %s continue=%d level = %d\n",
2431 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2432 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2435 /* W2K3 seems to treat zero as 1. */
2439 switch (info_level) {
2440 case SMB_FIND_INFO_STANDARD:
2441 case SMB_FIND_EA_SIZE:
2442 case SMB_FIND_EA_LIST:
2443 case SMB_FIND_FILE_DIRECTORY_INFO:
2444 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2445 case SMB_FIND_FILE_NAMES_INFO:
2446 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2447 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2448 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2450 case SMB_FIND_FILE_UNIX:
2451 case SMB_FIND_FILE_UNIX_INFO2:
2452 /* Always use filesystem for UNIX mtime query. */
2453 ask_sharemode = false;
2454 if (!lp_unix_extensions()) {
2455 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2460 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2464 if (info_level == SMB_FIND_EA_LIST) {
2467 if (total_data < 4) {
2468 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2472 ea_size = IVAL(pdata,0);
2473 if (ea_size != total_data) {
2474 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2475 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2480 if (!lp_ea_support(SNUM(conn))) {
2481 reply_doserror(req, ERRDOS, ERReasnotsupported);
2485 /* Pull out the list of names. */
2486 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2493 *ppdata = (char *)SMB_REALLOC(
2494 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2495 if(*ppdata == NULL) {
2496 reply_nterror(req, NT_STATUS_NO_MEMORY);
2501 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2503 /* Realloc the params space */
2504 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2505 if(*pparams == NULL ) {
2506 reply_nterror(req, NT_STATUS_NO_MEMORY);
2512 /* Check that the dptr is valid */
2513 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2514 reply_doserror(req, ERRDOS, ERRnofiles);
2518 string_set(&conn->dirpath,dptr_path(dptr_num));
2520 /* Get the wildcard mask from the dptr */
2521 if((p = dptr_wcard(dptr_num))== NULL) {
2522 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2523 reply_doserror(req, ERRDOS, ERRnofiles);
2528 directory = conn->dirpath;
2530 /* Get the attr mask from the dptr */
2531 dirtype = dptr_attr(dptr_num);
2533 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2534 dptr_num, mask, dirtype,
2536 dptr_TellDir(conn->dirptr)));
2538 /* Initialize per TRANS2_FIND_NEXT operation data */
2539 dptr_init_search_op(conn->dirptr);
2541 /* We don't need to check for VOL here as this is returned by
2542 a different TRANS2 call. */
2544 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2545 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2546 dont_descend = True;
2549 space_remaining = max_data_bytes;
2550 out_of_space = False;
2553 * Seek to the correct position. We no longer use the resume key but
2554 * depend on the last file name instead.
2557 if(*resume_name && !continue_bit) {
2560 long current_pos = 0;
2562 * Remember, name_to_8_3 is called by
2563 * get_lanman2_dir_entry(), so the resume name
2564 * could be mangled. Ensure we check the unmangled name.
2567 if (mangle_is_mangled(resume_name, conn->params)) {
2568 char *new_resume_name = NULL;
2569 mangle_lookup_name_from_8_3(ctx,
2573 if (new_resume_name) {
2574 resume_name = new_resume_name;
2579 * Fix for NT redirector problem triggered by resume key indexes
2580 * changing between directory scans. We now return a resume key of 0
2581 * and instead look for the filename to continue from (also given
2582 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2583 * findfirst/findnext (as is usual) then the directory pointer
2584 * should already be at the correct place.
2587 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2588 } /* end if resume_name && !continue_bit */
2590 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2591 bool got_exact_match = False;
2593 /* this is a heuristic to avoid seeking the dirptr except when
2594 absolutely necessary. It allows for a filename of about 40 chars */
2595 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2596 out_of_space = True;
2599 finished = !get_lanman2_dir_entry(ctx,
2602 mask,dirtype,info_level,
2603 requires_resume_key,dont_descend,
2606 space_remaining, &out_of_space,
2608 &last_entry_off, ea_list);
2611 if (finished && out_of_space)
2614 if (!finished && !out_of_space)
2618 * As an optimisation if we know we aren't looking
2619 * for a wildcard name (ie. the name matches the wildcard exactly)
2620 * then we can finish on any (first) match.
2621 * This speeds up large directory searches. JRA.
2627 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2630 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2631 smb_fn_name(req->cmd),
2632 mask, directory, dirtype, numentries ) );
2634 /* Check if we can close the dirptr */
2635 if(close_after_request || (finished && close_if_end)) {
2636 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2637 dptr_close(&dptr_num); /* This frees up the saved mask */
2640 /* Set up the return parameter block */
2641 SSVAL(params,0,numentries);
2642 SSVAL(params,2,finished);
2643 SSVAL(params,4,0); /* Never an EA error */
2644 SSVAL(params,6,last_entry_off);
2646 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2652 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2654 E_md4hash(lp_servicename(SNUM(conn)),objid);
2658 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2660 SMB_ASSERT(extended_info != NULL);
2662 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2663 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2664 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2665 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2666 #ifdef SAMBA_VERSION_REVISION
2667 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2669 extended_info->samba_subversion = 0;
2670 #ifdef SAMBA_VERSION_RC_RELEASE
2671 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2673 #ifdef SAMBA_VERSION_PRE_RELEASE
2674 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2677 #ifdef SAMBA_VERSION_VENDOR_PATCH
2678 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2680 extended_info->samba_gitcommitdate = 0;
2681 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2682 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2685 memset(extended_info->samba_version_string, 0,
2686 sizeof(extended_info->samba_version_string));
2688 snprintf (extended_info->samba_version_string,
2689 sizeof(extended_info->samba_version_string),
2690 "%s", samba_version_string());
2693 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2694 TALLOC_CTX *mem_ctx,
2695 uint16_t info_level,
2698 unsigned int max_data_bytes,
2702 char *pdata, *end_data;
2703 int data_len = 0, len;
2704 const char *vname = volume_label(SNUM(conn));
2705 int snum = SNUM(conn);
2706 char *fstype = lp_fstype(SNUM(conn));
2707 uint32 additional_flags = 0;
2710 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2711 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2712 "info level (0x%x) on IPC$.\n",
2713 (unsigned int)info_level));
2714 return NT_STATUS_ACCESS_DENIED;
2718 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2720 *ppdata = (char *)SMB_REALLOC(
2721 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2722 if (*ppdata == NULL) {
2723 return NT_STATUS_NO_MEMORY;
2727 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2728 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2730 switch (info_level) {
2731 case SMB_INFO_ALLOCATION:
2733 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2735 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2736 return map_nt_error_from_unix(errno);
2739 block_size = lp_block_size(snum);
2740 if (bsize < block_size) {
2741 uint64_t factor = block_size/bsize;
2746 if (bsize > block_size) {
2747 uint64_t factor = bsize/block_size;
2752 bytes_per_sector = 512;
2753 sectors_per_unit = bsize/bytes_per_sector;
2755 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2756 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2757 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2759 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2760 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2761 SIVAL(pdata,l1_cUnit,dsize);
2762 SIVAL(pdata,l1_cUnitAvail,dfree);
2763 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2767 case SMB_INFO_VOLUME:
2768 /* Return volume name */
2770 * Add volume serial number - hash of a combination of
2771 * the called hostname and the service name.
2773 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2775 * Win2k3 and previous mess this up by sending a name length
2776 * one byte short. I believe only older clients (OS/2 Win9x) use
2777 * this call so try fixing this by adding a terminating null to
2778 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2782 pdata+l2_vol_szVolLabel, vname,
2783 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2784 STR_NOALIGN|STR_TERMINATE);
2785 SCVAL(pdata,l2_vol_cch,len);
2786 data_len = l2_vol_szVolLabel + len;
2787 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2788 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2792 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2793 case SMB_FS_ATTRIBUTE_INFORMATION:
2795 additional_flags = 0;
2796 #if defined(HAVE_SYS_QUOTAS)
2797 additional_flags |= FILE_VOLUME_QUOTAS;
2800 if(lp_nt_acl_support(SNUM(conn))) {
2801 additional_flags |= FILE_PERSISTENT_ACLS;
2804 /* Capabilities are filled in at connection time through STATVFS call */
2805 additional_flags |= conn->fs_capabilities;
2807 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2808 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2809 additional_flags); /* FS ATTRIBUTES */
2811 SIVAL(pdata,4,255); /* Max filename component length */
2812 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2813 and will think we can't do long filenames */
2814 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2815 PTR_DIFF(end_data, pdata+12),
2818 data_len = 12 + len;
2821 case SMB_QUERY_FS_LABEL_INFO:
2822 case SMB_FS_LABEL_INFORMATION:
2823 len = srvstr_push(pdata, flags2, pdata+4, vname,
2824 PTR_DIFF(end_data, pdata+4), 0);
2829 case SMB_QUERY_FS_VOLUME_INFO:
2830 case SMB_FS_VOLUME_INFORMATION:
2833 * Add volume serial number - hash of a combination of
2834 * the called hostname and the service name.
2836 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2837 (str_checksum(get_local_machine_name())<<16));
2839 /* Max label len is 32 characters. */
2840 len = srvstr_push(pdata, flags2, pdata+18, vname,
2841 PTR_DIFF(end_data, pdata+18),
2843 SIVAL(pdata,12,len);
2846 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2847 (int)strlen(vname),vname, lp_servicename(snum)));
2850 case SMB_QUERY_FS_SIZE_INFO:
2851 case SMB_FS_SIZE_INFORMATION:
2853 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2855 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2856 return map_nt_error_from_unix(errno);
2858 block_size = lp_block_size(snum);
2859 if (bsize < block_size) {
2860 uint64_t factor = block_size/bsize;
2865 if (bsize > block_size) {
2866 uint64_t factor = bsize/block_size;
2871 bytes_per_sector = 512;
2872 sectors_per_unit = bsize/bytes_per_sector;
2873 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2874 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2875 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2876 SBIG_UINT(pdata,0,dsize);
2877 SBIG_UINT(pdata,8,dfree);
2878 SIVAL(pdata,16,sectors_per_unit);
2879 SIVAL(pdata,20,bytes_per_sector);
2883 case SMB_FS_FULL_SIZE_INFORMATION:
2885 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2887 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2888 return map_nt_error_from_unix(errno);
2890 block_size = lp_block_size(snum);
2891 if (bsize < block_size) {
2892 uint64_t factor = block_size/bsize;
2897 if (bsize > block_size) {
2898 uint64_t factor = bsize/block_size;
2903 bytes_per_sector = 512;
2904 sectors_per_unit = bsize/bytes_per_sector;
2905 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2906 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2907 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2908 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2909 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2910 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2911 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2912 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2916 case SMB_QUERY_FS_DEVICE_INFO:
2917 case SMB_FS_DEVICE_INFORMATION:
2919 SIVAL(pdata,0,0); /* dev type */
2920 SIVAL(pdata,4,0); /* characteristics */
2923 #ifdef HAVE_SYS_QUOTAS
2924 case SMB_FS_QUOTA_INFORMATION:
2926 * what we have to send --metze:
2928 * Unknown1: 24 NULL bytes
2929 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2930 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2931 * Quota Flags: 2 byte :
2932 * Unknown3: 6 NULL bytes
2936 * details for Quota Flags:
2938 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2939 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2940 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2941 * 0x0001 Enable Quotas: enable quota for this fs
2945 /* we need to fake up a fsp here,
2946 * because its not send in this call
2949 SMB_NTQUOTA_STRUCT quotas;
2952 ZERO_STRUCT(quotas);
2958 if (conn->server_info->utok.uid != sec_initial_uid()) {
2959 DEBUG(0,("set_user_quota: access_denied "
2960 "service [%s] user [%s]\n",
2961 lp_servicename(SNUM(conn)),
2962 conn->server_info->unix_name));
2963 return NT_STATUS_ACCESS_DENIED;
2966 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2967 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2968 return map_nt_error_from_unix(errno);
2973 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2974 lp_servicename(SNUM(conn))));
2976 /* Unknown1 24 NULL bytes*/
2977 SBIG_UINT(pdata,0,(uint64_t)0);
2978 SBIG_UINT(pdata,8,(uint64_t)0);
2979 SBIG_UINT(pdata,16,(uint64_t)0);
2981 /* Default Soft Quota 8 bytes */
2982 SBIG_UINT(pdata,24,quotas.softlim);
2984 /* Default Hard Quota 8 bytes */
2985 SBIG_UINT(pdata,32,quotas.hardlim);
2987 /* Quota flag 2 bytes */
2988 SSVAL(pdata,40,quotas.qflags);
2990 /* Unknown3 6 NULL bytes */
2996 #endif /* HAVE_SYS_QUOTAS */
2997 case SMB_FS_OBJECTID_INFORMATION:
2999 unsigned char objid[16];
3000 struct smb_extended_info extended_info;
3001 memcpy(pdata,create_volume_objectid(conn, objid),16);
3002 samba_extended_info_version (&extended_info);
3003 SIVAL(pdata,16,extended_info.samba_magic);
3004 SIVAL(pdata,20,extended_info.samba_version);
3005 SIVAL(pdata,24,extended_info.samba_subversion);
3006 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3007 memcpy(pdata+36,extended_info.samba_version_string,28);
3013 * Query the version and capabilities of the CIFS UNIX extensions
3017 case SMB_QUERY_CIFS_UNIX_INFO:
3019 bool large_write = lp_min_receive_file_size() &&
3020 !srv_is_signing_active(smbd_server_conn);
3021 bool large_read = !srv_is_signing_active(smbd_server_conn);
3022 int encrypt_caps = 0;
3024 if (!lp_unix_extensions()) {
3025 return NT_STATUS_INVALID_LEVEL;
3028 switch (conn->encrypt_level) {
3034 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3037 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3038 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3039 large_write = false;
3045 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3046 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3048 /* We have POSIX ACLs, pathname, encryption,
3049 * large read/write, and locking capability. */
3051 SBIG_UINT(pdata,4,((uint64_t)(
3052 CIFS_UNIX_POSIX_ACLS_CAP|
3053 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3054 CIFS_UNIX_FCNTL_LOCKS_CAP|
3055 CIFS_UNIX_EXTATTR_CAP|
3056 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3058 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3060 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3064 case SMB_QUERY_POSIX_FS_INFO:
3067 vfs_statvfs_struct svfs;
3069 if (!lp_unix_extensions()) {
3070 return NT_STATUS_INVALID_LEVEL;
3073 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3077 SIVAL(pdata,0,svfs.OptimalTransferSize);
3078 SIVAL(pdata,4,svfs.BlockSize);
3079 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3080 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3081 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3082 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3083 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3084 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3085 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3087 } else if (rc == EOPNOTSUPP) {
3088 return NT_STATUS_INVALID_LEVEL;
3089 #endif /* EOPNOTSUPP */
3091 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3092 return NT_STATUS_DOS(ERRSRV, ERRerror);
3097 case SMB_QUERY_POSIX_WHOAMI:
3103 if (!lp_unix_extensions()) {
3104 return NT_STATUS_INVALID_LEVEL;
3107 if (max_data_bytes < 40) {
3108 return NT_STATUS_BUFFER_TOO_SMALL;
3111 /* We ARE guest if global_sid_Builtin_Guests is
3112 * in our list of SIDs.
3114 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3115 conn->server_info->ptok)) {
3116 flags |= SMB_WHOAMI_GUEST;
3119 /* We are NOT guest if global_sid_Authenticated_Users
3120 * is in our list of SIDs.
3122 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3123 conn->server_info->ptok)) {
3124 flags &= ~SMB_WHOAMI_GUEST;
3127 /* NOTE: 8 bytes for UID/GID, irrespective of native
3128 * platform size. This matches
3129 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3131 data_len = 4 /* flags */
3138 + 4 /* pad/reserved */
3139 + (conn->server_info->utok.ngroups * 8)
3141 + (conn->server_info->ptok->num_sids *
3145 SIVAL(pdata, 0, flags);
3146 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3148 (uint64_t)conn->server_info->utok.uid);
3149 SBIG_UINT(pdata, 16,
3150 (uint64_t)conn->server_info->utok.gid);
3153 if (data_len >= max_data_bytes) {
3154 /* Potential overflow, skip the GIDs and SIDs. */
3156 SIVAL(pdata, 24, 0); /* num_groups */
3157 SIVAL(pdata, 28, 0); /* num_sids */
3158 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3159 SIVAL(pdata, 36, 0); /* reserved */
3165 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3166 SIVAL(pdata, 28, conn->server_info->num_sids);
3168 /* We walk the SID list twice, but this call is fairly
3169 * infrequent, and I don't expect that it's performance
3170 * sensitive -- jpeach
3172 for (i = 0, sid_bytes = 0;
3173 i < conn->server_info->ptok->num_sids; ++i) {
3174 sid_bytes += ndr_size_dom_sid(
3175 &conn->server_info->ptok->user_sids[i],
3180 /* SID list byte count */
3181 SIVAL(pdata, 32, sid_bytes);
3183 /* 4 bytes pad/reserved - must be zero */
3184 SIVAL(pdata, 36, 0);
3188 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3189 SBIG_UINT(pdata, data_len,
3190 (uint64_t)conn->server_info->utok.groups[i]);
3196 i < conn->server_info->ptok->num_sids; ++i) {
3197 int sid_len = ndr_size_dom_sid(
3198 &conn->server_info->ptok->user_sids[i],
3202 sid_linearize(pdata + data_len, sid_len,
3203 &conn->server_info->ptok->user_sids[i]);
3204 data_len += sid_len;
3210 case SMB_MAC_QUERY_FS_INFO:
3212 * Thursby MAC extension... ONLY on NTFS filesystems
3213 * once we do streams then we don't need this
3215 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3217 SIVAL(pdata,84,0x100); /* Don't support mac... */
3222 return NT_STATUS_INVALID_LEVEL;
3225 *ret_data_len = data_len;
3226 return NT_STATUS_OK;
3229 /****************************************************************************
3230 Reply to a TRANS2_QFSINFO (query filesystem info).
3231 ****************************************************************************/
3233 static void call_trans2qfsinfo(connection_struct *conn,
3234 struct smb_request *req,
3235 char **pparams, int total_params,
3236 char **ppdata, int total_data,
3237 unsigned int max_data_bytes)
3239 char *params = *pparams;
3240 uint16_t info_level;
3245 if (total_params < 2) {
3246 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3250 info_level = SVAL(params,0);
3252 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3253 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3254 DEBUG(0,("call_trans2qfsinfo: encryption required "
3255 "and info level 0x%x sent.\n",
3256 (unsigned int)info_level));
3257 exit_server_cleanly("encryption required "
3263 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3265 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
3266 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
3267 reply_doserror(req, ERRSRV, ERRinvdevice);
3271 status = smbd_do_qfsinfo(conn, req,
3276 if (!NT_STATUS_IS_OK(status)) {
3277 reply_nterror(req, status);
3281 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3284 DEBUG( 4, ( "%s info_level = %d\n",
3285 smb_fn_name(req->cmd), info_level) );
3290 /****************************************************************************
3291 Reply to a TRANS2_SETFSINFO (set filesystem info).
3292 ****************************************************************************/
3294 static void call_trans2setfsinfo(connection_struct *conn,
3295 struct smb_request *req,
3296 char **pparams, int total_params,
3297 char **ppdata, int total_data,
3298 unsigned int max_data_bytes)
3300 char *pdata = *ppdata;
3301 char *params = *pparams;
3304 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3307 if (total_params < 4) {
3308 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3310 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3314 info_level = SVAL(params,2);
3317 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3318 info_level != SMB_SET_CIFS_UNIX_INFO) {
3319 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3320 "info level (0x%x) on IPC$.\n",
3321 (unsigned int)info_level));
3322 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3327 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3328 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3329 DEBUG(0,("call_trans2setfsinfo: encryption required "
3330 "and info level 0x%x sent.\n",
3331 (unsigned int)info_level));
3332 exit_server_cleanly("encryption required "
3338 switch(info_level) {
3339 case SMB_SET_CIFS_UNIX_INFO:
3341 uint16 client_unix_major;
3342 uint16 client_unix_minor;
3343 uint32 client_unix_cap_low;
3344 uint32 client_unix_cap_high;
3346 if (!lp_unix_extensions()) {
3348 NT_STATUS_INVALID_LEVEL);
3352 /* There should be 12 bytes of capabilities set. */
3353 if (total_data < 8) {
3356 NT_STATUS_INVALID_PARAMETER);
3359 client_unix_major = SVAL(pdata,0);
3360 client_unix_minor = SVAL(pdata,2);
3361 client_unix_cap_low = IVAL(pdata,4);
3362 client_unix_cap_high = IVAL(pdata,8);
3363 /* Just print these values for now. */
3364 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3365 cap_low = 0x%x, cap_high = 0x%x\n",
3366 (unsigned int)client_unix_major,
3367 (unsigned int)client_unix_minor,
3368 (unsigned int)client_unix_cap_low,
3369 (unsigned int)client_unix_cap_high ));
3371 /* Here is where we must switch to posix pathname processing... */
3372 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3373 lp_set_posix_pathnames();
3374 mangle_change_to_posix();
3377 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3378 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3379 /* Client that knows how to do posix locks,
3380 * but not posix open/mkdir operations. Set a
3381 * default type for read/write checks. */
3383 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3389 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3392 size_t param_len = 0;
3393 size_t data_len = total_data;
3395 if (!lp_unix_extensions()) {
3398 NT_STATUS_INVALID_LEVEL);
3402 if (lp_smb_encrypt(SNUM(conn)) == false) {
3405 NT_STATUS_NOT_SUPPORTED);
3409 DEBUG( 4,("call_trans2setfsinfo: "
3410 "request transport encryption.\n"));
3412 status = srv_request_encryption_setup(conn,
3413 (unsigned char **)ppdata,
3415 (unsigned char **)pparams,
3418 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3419 !NT_STATUS_IS_OK(status)) {
3420 reply_nterror(req, status);
3424 send_trans2_replies(conn, req,
3431 if (NT_STATUS_IS_OK(status)) {
3432 /* Server-side transport
3433 * encryption is now *on*. */
3434 status = srv_encryption_start(conn);
3435 if (!NT_STATUS_IS_OK(status)) {
3436 exit_server_cleanly(
3437 "Failure in setting "
3438 "up encrypted transport");
3444 case SMB_FS_QUOTA_INFORMATION:
3446 files_struct *fsp = NULL;
3447 SMB_NTQUOTA_STRUCT quotas;
3449 ZERO_STRUCT(quotas);
3452 if ((conn->server_info->utok.uid != sec_initial_uid())
3453 ||!CAN_WRITE(conn)) {
3454 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3455 lp_servicename(SNUM(conn)),
3456 conn->server_info->unix_name));
3457 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3461 /* note: normaly there're 48 bytes,
3462 * but we didn't use the last 6 bytes for now
3465 fsp = file_fsp(req, SVAL(params,0));
3467 if (!check_fsp_ntquota_handle(conn, req,
3469 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3471 req, NT_STATUS_INVALID_HANDLE);
3475 if (total_data < 42) {
3476 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3480 NT_STATUS_INVALID_PARAMETER);
3484 /* unknown_1 24 NULL bytes in pdata*/
3486 /* the soft quotas 8 bytes (uint64_t)*/
3487 quotas.softlim = (uint64_t)IVAL(pdata,24);
3488 #ifdef LARGE_SMB_OFF_T
3489 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3490 #else /* LARGE_SMB_OFF_T */
3491 if ((IVAL(pdata,28) != 0)&&
3492 ((quotas.softlim != 0xFFFFFFFF)||
3493 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3494 /* more than 32 bits? */
3497 NT_STATUS_INVALID_PARAMETER);
3500 #endif /* LARGE_SMB_OFF_T */
3502 /* the hard quotas 8 bytes (uint64_t)*/
3503 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3504 #ifdef LARGE_SMB_OFF_T
3505 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3506 #else /* LARGE_SMB_OFF_T */
3507 if ((IVAL(pdata,36) != 0)&&
3508 ((quotas.hardlim != 0xFFFFFFFF)||
3509 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3510 /* more than 32 bits? */
3513 NT_STATUS_INVALID_PARAMETER);
3516 #endif /* LARGE_SMB_OFF_T */
3518 /* quota_flags 2 bytes **/
3519 quotas.qflags = SVAL(pdata,40);
3521 /* unknown_2 6 NULL bytes follow*/
3523 /* now set the quotas */
3524 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3525 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3526 reply_nterror(req, map_nt_error_from_unix(errno));
3533 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3535 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3541 * sending this reply works fine,
3542 * but I'm not sure it's the same
3543 * like windows do...
3546 reply_outbuf(req, 10, 0);
3549 #if defined(HAVE_POSIX_ACLS)
3550 /****************************************************************************
3551 Utility function to count the number of entries in a POSIX acl.
3552 ****************************************************************************/
3554 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3556 unsigned int ace_count = 0;
3557 int entry_id = SMB_ACL_FIRST_ENTRY;
3558 SMB_ACL_ENTRY_T entry;
3560 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3562 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3563 entry_id = SMB_ACL_NEXT_ENTRY;
3570 /****************************************************************************
3571 Utility function to marshall a POSIX acl into wire format.
3572 ****************************************************************************/
3574 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3576 int entry_id = SMB_ACL_FIRST_ENTRY;
3577 SMB_ACL_ENTRY_T entry;
3579 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3580 SMB_ACL_TAG_T tagtype;
3581 SMB_ACL_PERMSET_T permset;
3582 unsigned char perms = 0;
3583 unsigned int own_grp;
3586 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3587 entry_id = SMB_ACL_NEXT_ENTRY;
3590 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3591 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3595 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3596 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3600 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3601 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3602 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3604 SCVAL(pdata,1,perms);
3607 case SMB_ACL_USER_OBJ:
3608 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3609 own_grp = (unsigned int)pst->st_ex_uid;
3610 SIVAL(pdata,2,own_grp);
3615 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3617 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3620 own_grp = (unsigned int)*puid;
3621 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3622 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3623 SIVAL(pdata,2,own_grp);
3627 case SMB_ACL_GROUP_OBJ:
3628 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3629 own_grp = (unsigned int)pst->st_ex_gid;
3630 SIVAL(pdata,2,own_grp);
3635 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3637 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3640 own_grp = (unsigned int)*pgid;
3641 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3642 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3643 SIVAL(pdata,2,own_grp);
3648 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3649 SIVAL(pdata,2,0xFFFFFFFF);
3650 SIVAL(pdata,6,0xFFFFFFFF);
3653 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3654 SIVAL(pdata,2,0xFFFFFFFF);
3655 SIVAL(pdata,6,0xFFFFFFFF);
3658 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3661 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3668 /****************************************************************************
3669 Store the FILE_UNIX_BASIC info.
3670 ****************************************************************************/
3672 static char *store_file_unix_basic(connection_struct *conn,
3675 const SMB_STRUCT_STAT *psbuf)
3677 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3678 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3680 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3683 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3686 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3687 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3688 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3691 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3695 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3699 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3702 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3706 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3710 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3713 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3717 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3724 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3725 * the chflags(2) (or equivalent) flags.
3727 * XXX: this really should be behind the VFS interface. To do this, we would
3728 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3729 * Each VFS module could then implement its own mapping as appropriate for the
3730 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3732 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3736 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3740 { UF_IMMUTABLE, EXT_IMMUTABLE },
3744 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3748 { UF_HIDDEN, EXT_HIDDEN },
3751 /* Do not remove. We need to guarantee that this array has at least one
3752 * entry to build on HP-UX.
3758 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3759 uint32 *smb_fflags, uint32 *smb_fmask)
3763 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3764 *smb_fmask |= info2_flags_map[i].smb_fflag;
3765 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3766 *smb_fflags |= info2_flags_map[i].smb_fflag;
3771 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3772 const uint32 smb_fflags,
3773 const uint32 smb_fmask,
3776 uint32 max_fmask = 0;
3779 *stat_fflags = psbuf->st_ex_flags;
3781 /* For each flags requested in smb_fmask, check the state of the
3782 * corresponding flag in smb_fflags and set or clear the matching
3786 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3787 max_fmask |= info2_flags_map[i].smb_fflag;
3788 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3789 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3790 *stat_fflags |= info2_flags_map[i].stat_fflag;
3792 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3797 /* If smb_fmask is asking to set any bits that are not supported by
3798 * our flag mappings, we should fail.
3800 if ((smb_fmask & max_fmask) != smb_fmask) {
3808 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3809 * of file flags and birth (create) time.
3811 static char *store_file_unix_basic_info2(connection_struct *conn,
3814 const SMB_STRUCT_STAT *psbuf)
3816 uint32 file_flags = 0;
3817 uint32 flags_mask = 0;
3819 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3821 /* Create (birth) time 64 bit */
3822 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3825 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3826 SIVAL(pdata, 0, file_flags); /* flags */
3827 SIVAL(pdata, 4, flags_mask); /* mask */
3833 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3834 const struct stream_struct *streams,
3836 unsigned int max_data_bytes,
3837 unsigned int *data_size)
3840 unsigned int ofs = 0;
3842 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3843 unsigned int next_offset;
3845 smb_ucs2_t *namebuf;
3847 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3848 streams[i].name, &namelen) ||
3851 return NT_STATUS_INVALID_PARAMETER;
3855 * name_buf is now null-terminated, we need to marshall as not
3861 SIVAL(data, ofs+4, namelen);
3862 SOFF_T(data, ofs+8, streams[i].size);
3863 SOFF_T(data, ofs+16, streams[i].alloc_size);
3864 memcpy(data+ofs+24, namebuf, namelen);
3865 TALLOC_FREE(namebuf);
3867 next_offset = ofs + 24 + namelen;
3869 if (i == num_streams-1) {
3870 SIVAL(data, ofs, 0);
3873 unsigned int align = ndr_align_size(next_offset, 8);
3875 memset(data+next_offset, 0, align);
3876 next_offset += align;
3878 SIVAL(data, ofs, next_offset - ofs);
3887 return NT_STATUS_OK;
3890 /****************************************************************************
3891 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3892 ****************************************************************************/
3894 static void call_trans2qpipeinfo(connection_struct *conn,
3895 struct smb_request *req,
3896 unsigned int tran_call,
3897 char **pparams, int total_params,
3898 char **ppdata, int total_data,
3899 unsigned int max_data_bytes)
3901 char *params = *pparams;
3902 char *pdata = *ppdata;
3903 unsigned int data_size = 0;
3904 unsigned int param_size = 2;
3909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3913 if (total_params < 4) {
3914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3918 fsp = file_fsp(req, SVAL(params,0));
3919 if (!fsp_is_np(fsp)) {
3920 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3924 info_level = SVAL(params,2);
3926 *pparams = (char *)SMB_REALLOC(*pparams,2);
3927 if (*pparams == NULL) {
3928 reply_nterror(req, NT_STATUS_NO_MEMORY);
3933 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3934 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3935 if (*ppdata == NULL ) {
3936 reply_nterror(req, NT_STATUS_NO_MEMORY);
3941 switch (info_level) {
3942 case SMB_FILE_STANDARD_INFORMATION:
3944 SOFF_T(pdata,0,4096LL);
3951 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3955 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3961 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3962 TALLOC_CTX *mem_ctx,
3963 uint16_t info_level,
3965 const struct smb_filename *smb_fname,
3966 bool delete_pending,
3967 struct timespec write_time_ts,
3969 struct ea_list *ea_list,
3970 int lock_data_count,
3973 unsigned int max_data_bytes,
3975 unsigned int *pdata_size)
3977 char *pdata = *ppdata;
3978 char *dstart, *dend;
3979 unsigned int data_size;
3980 struct timespec create_time_ts, mtime_ts, atime_ts;
3981 time_t create_time, mtime, atime;
3982 SMB_STRUCT_STAT sbuf;
3990 uint64_t file_size = 0;
3992 uint64_t allocation_size = 0;
3993 uint64_t file_index = 0;
3994 uint32_t access_mask = 0;
3996 sbuf = smb_fname->st;
3998 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3999 return NT_STATUS_INVALID_LEVEL;
4002 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
4003 if (!NT_STATUS_IS_OK(status)) {
4007 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4008 fname, fsp ? fsp->fnum : -1, info_level, max_data_bytes));
4011 mode = dos_mode_msdfs(conn, smb_fname);
4013 mode = dos_mode(conn, smb_fname);
4016 mode = FILE_ATTRIBUTE_NORMAL;
4018 nlink = sbuf.st_ex_nlink;
4020 if (nlink && (mode&aDIR)) {
4024 if ((nlink > 0) && delete_pending) {
4028 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4029 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4030 if (*ppdata == NULL) {
4031 return NT_STATUS_NO_MEMORY;
4035 dend = dstart + data_size - 1;
4037 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4038 update_stat_ex_mtime(&sbuf, write_time_ts);
4041 create_time_ts = sbuf.st_ex_btime;
4042 mtime_ts = sbuf.st_ex_mtime;
4043 atime_ts = sbuf.st_ex_atime;
4045 if (lp_dos_filetime_resolution(SNUM(conn))) {
4046 dos_filetime_timespec(&create_time_ts);
4047 dos_filetime_timespec(&mtime_ts);
4048 dos_filetime_timespec(&atime_ts);
4051 create_time = convert_timespec_to_time_t(create_time_ts);
4052 mtime = convert_timespec_to_time_t(mtime_ts);
4053 atime = convert_timespec_to_time_t(atime_ts);
4055 p = strrchr_m(smb_fname->base_name,'/');
4057 base_name = smb_fname->base_name;
4061 /* NT expects the name to be in an exact form of the *full*
4062 filename. See the trans2 torture test */
4063 if (ISDOT(base_name)) {
4064 dos_fname = talloc_strdup(mem_ctx, "\\");
4066 return NT_STATUS_NO_MEMORY;
4069 dos_fname = talloc_asprintf(mem_ctx,
4073 return NT_STATUS_NO_MEMORY;
4075 string_replace(dos_fname, '/', '\\');
4078 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4081 /* Do we have this path open ? */
4083 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4084 fsp1 = file_find_di_first(fileid);
4085 if (fsp1 && fsp1->initial_allocation_size) {
4086 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4090 if (!(mode & aDIR)) {
4091 file_size = get_file_size_stat(&sbuf);
4095 pos = fsp->fh->position_information;
4099 access_mask = fsp->access_mask;
4101 /* GENERIC_EXECUTE mapping from Windows */
4102 access_mask = 0x12019F;
4105 /* This should be an index number - looks like
4108 I think this causes us to fail the IFSKIT
4109 BasicFileInformationTest. -tpot */
4110 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4111 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4113 switch (info_level) {
4114 case SMB_INFO_STANDARD:
4115 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4117 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4118 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4119 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4120 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4121 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4122 SSVAL(pdata,l1_attrFile,mode);
4125 case SMB_INFO_QUERY_EA_SIZE:
4127 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4128 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4130 srv_put_dos_date2(pdata,0,create_time);
4131 srv_put_dos_date2(pdata,4,atime);
4132 srv_put_dos_date2(pdata,8,mtime); /* write time */
4133 SIVAL(pdata,12,(uint32)file_size);
4134 SIVAL(pdata,16,(uint32)allocation_size);
4135 SSVAL(pdata,20,mode);
4136 SIVAL(pdata,22,ea_size);
4140 case SMB_INFO_IS_NAME_VALID:
4141 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4143 /* os/2 needs this ? really ?*/
4144 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4146 /* This is only reached for qpathinfo */
4150 case SMB_INFO_QUERY_EAS_FROM_LIST:
4152 size_t total_ea_len = 0;
4153 struct ea_list *ea_file_list = NULL;
4155 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4157 ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4158 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4160 if (!ea_list || (total_ea_len > data_size)) {
4162 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4166 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4170 case SMB_INFO_QUERY_ALL_EAS:
4172 /* We have data_size bytes to put EA's into. */
4173 size_t total_ea_len = 0;
4175 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4177 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4178 if (!ea_list || (total_ea_len > data_size)) {
4180 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4184 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4188 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4190 /* We have data_size bytes to put EA's into. */
4191 size_t total_ea_len = 0;
4192 struct ea_list *ea_file_list = NULL;
4194 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4196 /*TODO: add filtering and index handling */
4198 ea_file_list = get_ea_list_from_file(mem_ctx,
4202 if (!ea_file_list) {
4203 return NT_STATUS_NO_EAS_ON_FILE;
4206 status = fill_ea_chained_buffer(mem_ctx,
4210 conn, ea_file_list);
4211 if (!NT_STATUS_IS_OK(status)) {
4217 case SMB_FILE_BASIC_INFORMATION:
4218 case SMB_QUERY_FILE_BASIC_INFO:
4220 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4221 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4222 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4224 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4228 put_long_date_timespec(pdata,create_time_ts);
4229 put_long_date_timespec(pdata+8,atime_ts);
4230 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4231 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4232 SIVAL(pdata,32,mode);
4234 DEBUG(5,("SMB_QFBI - "));
4235 DEBUG(5,("create: %s ", ctime(&create_time)));
4236 DEBUG(5,("access: %s ", ctime(&atime)));
4237 DEBUG(5,("write: %s ", ctime(&mtime)));
4238 DEBUG(5,("change: %s ", ctime(&mtime)));
4239 DEBUG(5,("mode: %x\n", mode));
4242 case SMB_FILE_STANDARD_INFORMATION:
4243 case SMB_QUERY_FILE_STANDARD_INFO:
4245 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4247 SOFF_T(pdata,0,allocation_size);
4248 SOFF_T(pdata,8,file_size);
4249 SIVAL(pdata,16,nlink);
4250 SCVAL(pdata,20,delete_pending?1:0);
4251 SCVAL(pdata,21,(mode&aDIR)?1:0);
4252 SSVAL(pdata,22,0); /* Padding. */
4255 case SMB_FILE_EA_INFORMATION:
4256 case SMB_QUERY_FILE_EA_INFO:
4258 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4259 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4261 SIVAL(pdata,0,ea_size);
4265 /* Get the 8.3 name - used if NT SMB was negotiated. */
4266 case SMB_QUERY_FILE_ALT_NAME_INFO:
4267 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4270 char mangled_name[13];
4271 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4272 if (!name_to_8_3(base_name,mangled_name,
4273 True,conn->params)) {
4274 return NT_STATUS_NO_MEMORY;
4276 len = srvstr_push(dstart, flags2,
4277 pdata+4, mangled_name,
4278 PTR_DIFF(dend, pdata+4),
4280 data_size = 4 + len;
4285 case SMB_QUERY_FILE_NAME_INFO:
4289 this must be *exactly* right for ACLs on mapped drives to work
4291 len = srvstr_push(dstart, flags2,
4293 PTR_DIFF(dend, pdata+4),
4295 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4296 data_size = 4 + len;
4301 case SMB_FILE_ALLOCATION_INFORMATION:
4302 case SMB_QUERY_FILE_ALLOCATION_INFO:
4303 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4305 SOFF_T(pdata,0,allocation_size);
4308 case SMB_FILE_END_OF_FILE_INFORMATION:
4309 case SMB_QUERY_FILE_END_OF_FILEINFO:
4310 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4312 SOFF_T(pdata,0,file_size);
4315 case SMB_QUERY_FILE_ALL_INFO:
4316 case SMB_FILE_ALL_INFORMATION:
4319 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4320 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4321 put_long_date_timespec(pdata,create_time_ts);
4322 put_long_date_timespec(pdata+8,atime_ts);
4323 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4324 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4325 SIVAL(pdata,32,mode);
4326 SIVAL(pdata,36,0); /* padding. */
4328 SOFF_T(pdata,0,allocation_size);
4329 SOFF_T(pdata,8,file_size);
4330 SIVAL(pdata,16,nlink);
4331 SCVAL(pdata,20,delete_pending);
4332 SCVAL(pdata,21,(mode&aDIR)?1:0);
4335 SIVAL(pdata,0,ea_size);
4336 pdata += 4; /* EA info */
4337 len = srvstr_push(dstart, flags2,
4339 PTR_DIFF(dend, pdata+4),
4343 data_size = PTR_DIFF(pdata,(*ppdata));
4347 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4350 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4351 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4352 put_long_date_timespec(pdata+0x00,create_time_ts);
4353 put_long_date_timespec(pdata+0x08,atime_ts);
4354 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4355 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4356 SIVAL(pdata, 0x20, mode);
4357 SIVAL(pdata, 0x24, 0); /* padding. */
4358 SBVAL(pdata, 0x28, allocation_size);
4359 SBVAL(pdata, 0x30, file_size);
4360 SIVAL(pdata, 0x38, nlink);
4361 SCVAL(pdata, 0x3C, delete_pending);
4362 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4363 SSVAL(pdata, 0x3E, 0); /* padding */
4364 SBVAL(pdata, 0x40, file_index);
4365 SIVAL(pdata, 0x48, ea_size);
4366 SIVAL(pdata, 0x4C, access_mask);
4367 SBVAL(pdata, 0x50, pos);
4368 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4369 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4373 len = srvstr_push(dstart, flags2,
4375 PTR_DIFF(dend, pdata+4),
4379 data_size = PTR_DIFF(pdata,(*ppdata));
4382 case SMB_FILE_INTERNAL_INFORMATION:
4384 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4385 SBVAL(pdata, 0, file_index);
4389 case SMB_FILE_ACCESS_INFORMATION:
4390 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4391 SIVAL(pdata, 0, access_mask);
4395 case SMB_FILE_NAME_INFORMATION:
4396 /* Pathname with leading '\'. */
4399 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4400 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4401 SIVAL(pdata,0,byte_len);
4402 data_size = 4 + byte_len;
4406 case SMB_FILE_DISPOSITION_INFORMATION:
4407 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4409 SCVAL(pdata,0,delete_pending);
4412 case SMB_FILE_POSITION_INFORMATION:
4413 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4415 SOFF_T(pdata,0,pos);
4418 case SMB_FILE_MODE_INFORMATION:
4419 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4420 SIVAL(pdata,0,mode);
4424 case SMB_FILE_ALIGNMENT_INFORMATION:
4425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4426 SIVAL(pdata,0,0); /* No alignment needed. */
4431 * NT4 server just returns "invalid query" to this - if we try
4432 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4435 /* The first statement above is false - verified using Thursby
4436 * client against NT4 -- gcolley.
4438 case SMB_QUERY_FILE_STREAM_INFO:
4439 case SMB_FILE_STREAM_INFORMATION: {
4440 unsigned int num_streams;
4441 struct stream_struct *streams;
4443 DEBUG(10,("smbd_do_qfilepathinfo: "
4444 "SMB_FILE_STREAM_INFORMATION\n"));
4446 status = SMB_VFS_STREAMINFO(
4447 conn, fsp, fname, talloc_tos(),
4448 &num_streams, &streams);
4450 if (!NT_STATUS_IS_OK(status)) {
4451 DEBUG(10, ("could not get stream info: %s\n",
4452 nt_errstr(status)));
4456 status = marshall_stream_info(num_streams, streams,
4457 pdata, max_data_bytes,
4460 if (!NT_STATUS_IS_OK(status)) {
4461 DEBUG(10, ("marshall_stream_info failed: %s\n",
4462 nt_errstr(status)));
4466 TALLOC_FREE(streams);
4470 case SMB_QUERY_COMPRESSION_INFO:
4471 case SMB_FILE_COMPRESSION_INFORMATION:
4472 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4473 SOFF_T(pdata,0,file_size);
4474 SIVAL(pdata,8,0); /* ??? */
4475 SIVAL(pdata,12,0); /* ??? */
4479 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4480 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4481 put_long_date_timespec(pdata,create_time_ts);
4482 put_long_date_timespec(pdata+8,atime_ts);
4483 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4484 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4485 SOFF_T(pdata,32,allocation_size);
4486 SOFF_T(pdata,40,file_size);
4487 SIVAL(pdata,48,mode);
4488 SIVAL(pdata,52,0); /* ??? */
4492 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4493 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4494 SIVAL(pdata,0,mode);
4500 * CIFS UNIX Extensions.
4503 case SMB_QUERY_FILE_UNIX_BASIC:
4505 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4506 data_size = PTR_DIFF(pdata,(*ppdata));
4510 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4512 for (i=0; i<100; i++)
4513 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4519 case SMB_QUERY_FILE_UNIX_INFO2:
4521 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4522 data_size = PTR_DIFF(pdata,(*ppdata));
4526 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4528 for (i=0; i<100; i++)
4529 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4535 case SMB_QUERY_FILE_UNIX_LINK:
4538 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4541 return NT_STATUS_NO_MEMORY;
4544 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4546 if(!S_ISLNK(sbuf.st_ex_mode)) {
4547 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4550 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4552 len = SMB_VFS_READLINK(conn,fname,
4555 return map_nt_error_from_unix(errno);
4558 len = srvstr_push(dstart, flags2,
4560 PTR_DIFF(dend, pdata),
4563 data_size = PTR_DIFF(pdata,(*ppdata));
4568 #if defined(HAVE_POSIX_ACLS)
4569 case SMB_QUERY_POSIX_ACL:
4571 SMB_ACL_T file_acl = NULL;
4572 SMB_ACL_T def_acl = NULL;
4573 uint16 num_file_acls = 0;
4574 uint16 num_def_acls = 0;
4576 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4577 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4579 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4582 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4583 DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4585 return NT_STATUS_NOT_IMPLEMENTED;
4588 if (S_ISDIR(sbuf.st_ex_mode)) {
4589 if (fsp && fsp->is_directory) {
4591 SMB_VFS_SYS_ACL_GET_FILE(
4593 fsp->fsp_name->base_name,
4594 SMB_ACL_TYPE_DEFAULT);
4596 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4598 def_acl = free_empty_sys_acl(conn, def_acl);
4601 num_file_acls = count_acl_entries(conn, file_acl);
4602 num_def_acls = count_acl_entries(conn, def_acl);
4604 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4605 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4607 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4608 SMB_POSIX_ACL_HEADER_SIZE) ));
4610 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4613 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4615 return NT_STATUS_BUFFER_TOO_SMALL;
4618 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4619 SSVAL(pdata,2,num_file_acls);
4620 SSVAL(pdata,4,num_def_acls);
4621 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4623 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4626 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4628 return NT_STATUS_INTERNAL_ERROR;
4630 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4632 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4635 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4637 return NT_STATUS_INTERNAL_ERROR;
4641 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4644 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4646 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4652 case SMB_QUERY_POSIX_LOCK:
4657 enum brl_type lock_type;
4659 /* We need an open file with a real fd for this. */
4660 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4661 return NT_STATUS_INVALID_LEVEL;
4664 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4665 return NT_STATUS_INVALID_PARAMETER;
4668 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4669 case POSIX_LOCK_TYPE_READ:
4670 lock_type = READ_LOCK;
4672 case POSIX_LOCK_TYPE_WRITE:
4673 lock_type = WRITE_LOCK;
4675 case POSIX_LOCK_TYPE_UNLOCK:
4677 /* There's no point in asking for an unlock... */
4678 return NT_STATUS_INVALID_PARAMETER;
4681 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4682 #if defined(HAVE_LONGLONG)
4683 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4684 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4685 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4686 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4687 #else /* HAVE_LONGLONG */
4688 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4689 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4690 #endif /* HAVE_LONGLONG */
4692 status = query_lock(fsp,
4699 if (ERROR_WAS_LOCK_DENIED(status)) {
4700 /* Here we need to report who has it locked... */
4701 data_size = POSIX_LOCK_DATA_SIZE;
4703 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4704 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4705 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4706 #if defined(HAVE_LONGLONG)
4707 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4708 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4709 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4710 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4711 #else /* HAVE_LONGLONG */
4712 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4713 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4714 #endif /* HAVE_LONGLONG */
4716 } else if (NT_STATUS_IS_OK(status)) {
4717 /* For success we just return a copy of what we sent
4718 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4719 data_size = POSIX_LOCK_DATA_SIZE;
4720 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4721 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4729 return NT_STATUS_INVALID_LEVEL;
4732 *pdata_size = data_size;
4733 return NT_STATUS_OK;
4736 /****************************************************************************
4737 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4738 file name or file id).
4739 ****************************************************************************/
4741 static void call_trans2qfilepathinfo(connection_struct *conn,
4742 struct smb_request *req,
4743 unsigned int tran_call,
4744 char **pparams, int total_params,
4745 char **ppdata, int total_data,
4746 unsigned int max_data_bytes)
4748 char *params = *pparams;
4749 char *pdata = *ppdata;
4751 unsigned int data_size = 0;
4752 unsigned int param_size = 2;
4754 struct smb_filename *smb_fname = NULL;
4755 bool delete_pending = False;
4756 struct timespec write_time_ts;
4757 files_struct *fsp = NULL;
4758 struct file_id fileid;
4759 struct ea_list *ea_list = NULL;
4760 int lock_data_count = 0;
4761 char *lock_data = NULL;
4762 bool ms_dfs_link = false;
4763 NTSTATUS status = NT_STATUS_OK;
4766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4770 ZERO_STRUCT(write_time_ts);
4772 if (tran_call == TRANSACT2_QFILEINFO) {
4773 if (total_params < 4) {
4774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4779 call_trans2qpipeinfo(conn, req, tran_call,
4780 pparams, total_params,
4786 fsp = file_fsp(req, SVAL(params,0));
4787 info_level = SVAL(params,2);
4789 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4791 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4792 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4796 /* Initial check for valid fsp ptr. */
4797 if (!check_fsp_open(conn, req, fsp)) {
4801 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4803 if (!NT_STATUS_IS_OK(status)) {
4804 reply_nterror(req, status);
4808 if(fsp->fake_file_handle) {
4810 * This is actually for the QUOTA_FAKE_FILE --metze
4813 /* We know this name is ok, it's already passed the checks. */
4815 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4817 * This is actually a QFILEINFO on a directory
4818 * handle (returned from an NT SMB). NT5.0 seems
4819 * to do this call. JRA.
4822 if (INFO_LEVEL_IS_UNIX(info_level)) {
4823 /* Always do lstat for UNIX calls. */
4824 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4825 DEBUG(3,("call_trans2qfilepathinfo: "
4826 "SMB_VFS_LSTAT of %s failed "
4828 smb_fname_str_dbg(smb_fname),
4831 map_nt_error_from_unix(errno));
4834 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4835 DEBUG(3,("call_trans2qfilepathinfo: "
4836 "SMB_VFS_STAT of %s failed (%s)\n",
4837 smb_fname_str_dbg(smb_fname),
4840 map_nt_error_from_unix(errno));
4844 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4845 get_file_infos(fileid, &delete_pending, &write_time_ts);
4848 * Original code - this is an open file.
4850 if (!check_fsp(conn, req, fsp)) {
4854 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4855 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4856 fsp->fnum, strerror(errno)));
4858 map_nt_error_from_unix(errno));
4861 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4862 get_file_infos(fileid, &delete_pending, &write_time_ts);
4867 if (total_params < 7) {
4868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4872 info_level = SVAL(params,0);
4874 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4876 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4877 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4881 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4883 STR_TERMINATE, &status);
4884 if (!NT_STATUS_IS_OK(status)) {
4885 reply_nterror(req, status);
4889 status = filename_convert(req,
4891 req->flags2 & FLAGS2_DFS_PATHNAMES,
4895 if (!NT_STATUS_IS_OK(status)) {
4896 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4897 reply_botherror(req,
4898 NT_STATUS_PATH_NOT_COVERED,
4899 ERRSRV, ERRbadpath);
4902 reply_nterror(req, status);
4906 /* If this is a stream, check if there is a delete_pending. */
4907 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4908 && is_ntfs_stream_smb_fname(smb_fname)) {
4909 struct smb_filename *smb_fname_base = NULL;
4911 /* Create an smb_filename with stream_name == NULL. */
4913 create_synthetic_smb_fname(talloc_tos(),
4914 smb_fname->base_name,
4917 if (!NT_STATUS_IS_OK(status)) {
4918 reply_nterror(req, status);
4922 if (INFO_LEVEL_IS_UNIX(info_level)) {
4923 /* Always do lstat for UNIX calls. */
4924 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4925 DEBUG(3,("call_trans2qfilepathinfo: "
4926 "SMB_VFS_LSTAT of %s failed "
4928 smb_fname_str_dbg(smb_fname_base),
4930 TALLOC_FREE(smb_fname_base);
4932 map_nt_error_from_unix(errno));
4936 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4937 DEBUG(3,("call_trans2qfilepathinfo: "
4938 "fileinfo of %s failed "
4940 smb_fname_str_dbg(smb_fname_base),
4942 TALLOC_FREE(smb_fname_base);
4944 map_nt_error_from_unix(errno));
4949 fileid = vfs_file_id_from_sbuf(conn,
4950 &smb_fname_base->st);
4951 TALLOC_FREE(smb_fname_base);
4952 get_file_infos(fileid, &delete_pending, NULL);
4953 if (delete_pending) {
4954 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4959 if (INFO_LEVEL_IS_UNIX(info_level)) {
4960 /* Always do lstat for UNIX calls. */
4961 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4962 DEBUG(3,("call_trans2qfilepathinfo: "
4963 "SMB_VFS_LSTAT of %s failed (%s)\n",
4964 smb_fname_str_dbg(smb_fname),
4967 map_nt_error_from_unix(errno));
4971 } else if (!VALID_STAT(smb_fname->st) &&
4972 SMB_VFS_STAT(conn, smb_fname) &&
4973 (info_level != SMB_INFO_IS_NAME_VALID)) {
4974 ms_dfs_link = check_msdfs_link(conn, fname,
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 total_data=%d\n",
4997 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4999 /* Pull out any data sent here before we realloc. */
5000 switch (info_level) {
5001 case SMB_INFO_QUERY_EAS_FROM_LIST:
5003 /* Pull any EA list from the data portion. */
5006 if (total_data < 4) {
5008 req, NT_STATUS_INVALID_PARAMETER);
5011 ea_size = IVAL(pdata,0);
5013 if (total_data > 0 && ea_size != total_data) {
5014 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5015 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5017 req, NT_STATUS_INVALID_PARAMETER);
5021 if (!lp_ea_support(SNUM(conn))) {
5022 reply_doserror(req, ERRDOS,
5023 ERReasnotsupported);
5027 /* Pull out the list of names. */
5028 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5031 req, NT_STATUS_INVALID_PARAMETER);
5037 case SMB_QUERY_POSIX_LOCK:
5039 if (fsp == NULL || fsp->fh->fd == -1) {
5040 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5044 if (total_data != POSIX_LOCK_DATA_SIZE) {
5046 req, NT_STATUS_INVALID_PARAMETER);
5050 /* Copy the lock range data. */
5051 lock_data = (char *)TALLOC_MEMDUP(
5052 req, pdata, total_data);
5054 reply_nterror(req, NT_STATUS_NO_MEMORY);
5057 lock_data_count = total_data;
5063 *pparams = (char *)SMB_REALLOC(*pparams,2);
5064 if (*pparams == NULL) {
5065 reply_nterror(req, NT_STATUS_NO_MEMORY);
5072 * draft-leach-cifs-v1-spec-02.txt
5073 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5076 * The requested information is placed in the Data portion of the
5077 * transaction response. For the information levels greater than 0x100,
5078 * the transaction response has 1 parameter word which should be
5079 * ignored by the client.
5081 * However Windows only follows this rule for the IS_NAME_VALID call.
5083 switch (info_level) {
5084 case SMB_INFO_IS_NAME_VALID:
5089 if ((info_level & 0xFF00) == 0xFF00) {
5091 * We use levels that start with 0xFF00
5092 * internally to represent SMB2 specific levels
5094 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5098 status = smbd_do_qfilepathinfo(conn, req, info_level,
5100 delete_pending, write_time_ts,
5101 ms_dfs_link, ea_list,
5102 lock_data_count, lock_data,
5103 req->flags2, max_data_bytes,
5104 ppdata, &data_size);
5105 if (!NT_STATUS_IS_OK(status)) {
5106 reply_nterror(req, status);
5110 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5116 /****************************************************************************
5117 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5119 ****************************************************************************/
5121 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5122 connection_struct *conn,
5123 const struct smb_filename *smb_fname_old,
5124 const struct smb_filename *smb_fname_new)
5126 char *oldname = NULL;
5127 char *newname = NULL;
5128 NTSTATUS status = NT_STATUS_OK;
5130 /* source must already exist. */
5131 if (!VALID_STAT(smb_fname_old->st)) {
5132 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5135 /* Disallow if newname already exists. */
5136 if (VALID_STAT(smb_fname_new->st)) {
5137 return NT_STATUS_OBJECT_NAME_COLLISION;
5140 /* No links from a directory. */
5141 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5142 return NT_STATUS_FILE_IS_A_DIRECTORY;
5145 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
5146 if (!NT_STATUS_IS_OK(status)) {
5149 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
5150 if (!NT_STATUS_IS_OK(status)) {
5154 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
5156 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
5157 status = map_nt_error_from_unix(errno);
5158 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5159 nt_errstr(status), newname, oldname));
5162 TALLOC_FREE(newname);
5163 TALLOC_FREE(oldname);
5167 /****************************************************************************
5168 Deal with setting the time from any of the setfilepathinfo functions.
5169 ****************************************************************************/
5171 NTSTATUS smb_set_file_time(connection_struct *conn,
5173 const struct smb_filename *smb_fname,
5174 struct smb_file_time *ft,
5175 bool setting_write_time)
5177 struct smb_filename *smb_fname_base = NULL;
5179 FILE_NOTIFY_CHANGE_LAST_ACCESS
5180 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5183 if (!VALID_STAT(smb_fname->st)) {
5184 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5187 /* get some defaults (no modifications) if any info is zero or -1. */
5188 if (null_timespec(ft->atime)) {
5189 ft->atime= smb_fname->st.st_ex_atime;
5190 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5193 if (null_timespec(ft->mtime)) {
5194 ft->mtime = smb_fname->st.st_ex_mtime;
5195 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5198 if (!setting_write_time) {
5199 /* ft->mtime comes from change time, not write time. */
5200 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5203 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5204 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5205 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5206 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5207 if (!null_timespec(ft->create_time)) {
5208 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5209 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5213 * Try and set the times of this file if
5214 * they are different from the current values.
5218 struct timespec mts = smb_fname->st.st_ex_mtime;
5219 struct timespec ats = smb_fname->st.st_ex_atime;
5220 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5221 (timespec_compare(&ft->mtime, &mts) == 0)) {
5222 return NT_STATUS_OK;
5226 if (setting_write_time) {
5228 * This was a Windows setfileinfo on an open file.
5229 * NT does this a lot. We also need to
5230 * set the time here, as it can be read by
5231 * FindFirst/FindNext and with the patch for bug #2045
5232 * in smbd/fileio.c it ensures that this timestamp is
5233 * kept sticky even after a write. We save the request
5234 * away and will set it on file close and after a write. JRA.
5237 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5238 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5241 if (fsp->base_fsp) {
5242 set_sticky_write_time_fsp(fsp->base_fsp,
5245 set_sticky_write_time_fsp(fsp, ft->mtime);
5248 set_sticky_write_time_path(
5249 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5254 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5256 /* Always call ntimes on the base, even if a stream was passed in. */
5257 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5258 NULL, &smb_fname->st,
5260 if (!NT_STATUS_IS_OK(status)) {
5264 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5265 TALLOC_FREE(smb_fname_base);
5266 return map_nt_error_from_unix(errno);
5268 TALLOC_FREE(smb_fname_base);
5270 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5271 smb_fname->base_name);
5272 return NT_STATUS_OK;
5275 /****************************************************************************
5276 Deal with setting the dosmode from any of the setfilepathinfo functions.
5277 ****************************************************************************/
5279 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5280 const struct smb_filename *smb_fname,
5283 struct smb_filename *smb_fname_base = NULL;
5286 if (!VALID_STAT(smb_fname->st)) {
5287 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5290 /* Always operate on the base_name, even if a stream was passed in. */
5291 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5292 NULL, &smb_fname->st,
5294 if (!NT_STATUS_IS_OK(status)) {
5299 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5306 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5308 /* check the mode isn't different, before changing it */
5309 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5310 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5311 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5312 (unsigned int)dosmode));
5314 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5316 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5318 smb_fname_str_dbg(smb_fname_base),
5320 status = map_nt_error_from_unix(errno);
5324 status = NT_STATUS_OK;
5326 TALLOC_FREE(smb_fname_base);
5330 /****************************************************************************
5331 Deal with setting the size from any of the setfilepathinfo functions.
5332 ****************************************************************************/
5334 static NTSTATUS smb_set_file_size(connection_struct *conn,
5335 struct smb_request *req,
5337 const struct smb_filename *smb_fname,
5338 const SMB_STRUCT_STAT *psbuf,
5341 NTSTATUS status = NT_STATUS_OK;
5342 struct smb_filename *smb_fname_tmp = NULL;
5343 files_struct *new_fsp = NULL;
5345 if (!VALID_STAT(*psbuf)) {
5346 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5349 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5351 if (size == get_file_size_stat(psbuf)) {
5352 return NT_STATUS_OK;
5355 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5356 smb_fname_str_dbg(smb_fname), (double)size));
5358 if (fsp && fsp->fh->fd != -1) {
5359 /* Handle based call. */
5360 if (vfs_set_filelen(fsp, size) == -1) {
5361 return map_nt_error_from_unix(errno);
5363 trigger_write_time_update_immediate(fsp);
5364 return NT_STATUS_OK;
5367 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5368 if (!NT_STATUS_IS_OK(status)) {
5372 smb_fname_tmp->st = *psbuf;
5374 status = SMB_VFS_CREATE_FILE(
5377 0, /* root_dir_fid */
5378 smb_fname_tmp, /* fname */
5379 FILE_WRITE_ATTRIBUTES, /* access_mask */
5380 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5382 FILE_OPEN, /* create_disposition*/
5383 0, /* create_options */
5384 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5385 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5386 0, /* allocation_size */
5389 &new_fsp, /* result */
5392 TALLOC_FREE(smb_fname_tmp);
5394 if (!NT_STATUS_IS_OK(status)) {
5395 /* NB. We check for open_was_deferred in the caller. */
5399 if (vfs_set_filelen(new_fsp, size) == -1) {
5400 status = map_nt_error_from_unix(errno);
5401 close_file(req, new_fsp,NORMAL_CLOSE);
5405 trigger_write_time_update_immediate(new_fsp);
5406 close_file(req, new_fsp,NORMAL_CLOSE);
5407 return NT_STATUS_OK;
5410 /****************************************************************************
5411 Deal with SMB_INFO_SET_EA.
5412 ****************************************************************************/
5414 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5418 const struct smb_filename *smb_fname)
5420 struct ea_list *ea_list = NULL;
5421 TALLOC_CTX *ctx = NULL;
5422 NTSTATUS status = NT_STATUS_OK;
5424 if (total_data < 10) {
5426 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5427 length. They seem to have no effect. Bug #3212. JRA */
5429 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5430 /* We're done. We only get EA info in this call. */
5431 return NT_STATUS_OK;
5434 return NT_STATUS_INVALID_PARAMETER;
5437 if (IVAL(pdata,0) > total_data) {
5438 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5439 IVAL(pdata,0), (unsigned int)total_data));
5440 return NT_STATUS_INVALID_PARAMETER;
5444 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5446 return NT_STATUS_INVALID_PARAMETER;
5448 status = set_ea(conn, fsp, smb_fname, ea_list);
5453 /****************************************************************************
5454 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5455 ****************************************************************************/
5457 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5461 const struct smb_filename *smb_fname)
5463 NTSTATUS status = NT_STATUS_OK;
5464 bool delete_on_close;
5467 if (total_data < 1) {
5468 return NT_STATUS_INVALID_PARAMETER;
5472 return NT_STATUS_INVALID_HANDLE;
5475 delete_on_close = (CVAL(pdata,0) ? True : False);
5476 dosmode = dos_mode(conn, smb_fname);
5478 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5479 "delete_on_close = %u\n",
5480 smb_fname_str_dbg(smb_fname),
5481 (unsigned int)dosmode,
5482 (unsigned int)delete_on_close ));
5484 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5486 if (!NT_STATUS_IS_OK(status)) {
5490 /* The set is across all open files on this dev/inode pair. */
5491 if (!set_delete_on_close(fsp, delete_on_close,
5492 &conn->server_info->utok)) {
5493 return NT_STATUS_ACCESS_DENIED;
5495 return NT_STATUS_OK;
5498 /****************************************************************************
5499 Deal with SMB_FILE_POSITION_INFORMATION.
5500 ****************************************************************************/
5502 static NTSTATUS smb_file_position_information(connection_struct *conn,
5507 uint64_t position_information;
5509 if (total_data < 8) {
5510 return NT_STATUS_INVALID_PARAMETER;
5514 /* Ignore on pathname based set. */
5515 return NT_STATUS_OK;
5518 position_information = (uint64_t)IVAL(pdata,0);
5519 #ifdef LARGE_SMB_OFF_T
5520 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5521 #else /* LARGE_SMB_OFF_T */
5522 if (IVAL(pdata,4) != 0) {
5523 /* more than 32 bits? */
5524 return NT_STATUS_INVALID_PARAMETER;
5526 #endif /* LARGE_SMB_OFF_T */
5528 DEBUG(10,("smb_file_position_information: Set file position "
5529 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5530 (double)position_information));
5531 fsp->fh->position_information = position_information;
5532 return NT_STATUS_OK;
5535 /****************************************************************************
5536 Deal with SMB_FILE_MODE_INFORMATION.
5537 ****************************************************************************/
5539 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5545 if (total_data < 4) {
5546 return NT_STATUS_INVALID_PARAMETER;
5548 mode = IVAL(pdata,0);
5549 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5550 return NT_STATUS_INVALID_PARAMETER;
5552 return NT_STATUS_OK;
5555 /****************************************************************************
5556 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5557 ****************************************************************************/
5559 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5560 struct smb_request *req,
5565 char *link_target = NULL;
5566 const char *newname = fname;
5567 NTSTATUS status = NT_STATUS_OK;
5568 TALLOC_CTX *ctx = talloc_tos();
5570 /* Set a symbolic link. */
5571 /* Don't allow this if follow links is false. */
5573 if (total_data == 0) {
5574 return NT_STATUS_INVALID_PARAMETER;
5577 if (!lp_symlinks(SNUM(conn))) {
5578 return NT_STATUS_ACCESS_DENIED;
5581 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5582 total_data, STR_TERMINATE);
5585 return NT_STATUS_INVALID_PARAMETER;
5588 /* !widelinks forces the target path to be within the share. */
5589 /* This means we can interpret the target as a pathname. */
5590 if (!lp_widelinks(SNUM(conn))) {
5591 char *rel_name = NULL;
5592 char *last_dirp = NULL;
5594 if (*link_target == '/') {
5595 /* No absolute paths allowed. */
5596 return NT_STATUS_ACCESS_DENIED;
5598 rel_name = talloc_strdup(ctx,newname);
5600 return NT_STATUS_NO_MEMORY;
5602 last_dirp = strrchr_m(rel_name, '/');
5604 last_dirp[1] = '\0';
5606 rel_name = talloc_strdup(ctx,"./");
5608 return NT_STATUS_NO_MEMORY;
5611 rel_name = talloc_asprintf_append(rel_name,
5615 return NT_STATUS_NO_MEMORY;
5618 status = check_name(conn, rel_name);
5619 if (!NT_STATUS_IS_OK(status)) {
5624 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5625 newname, link_target ));
5627 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5628 return map_nt_error_from_unix(errno);
5631 return NT_STATUS_OK;
5634 /****************************************************************************
5635 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5636 ****************************************************************************/
5638 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5639 struct smb_request *req,
5640 const char *pdata, int total_data,
5641 const struct smb_filename *smb_fname_new)
5643 char *oldname = NULL;
5644 struct smb_filename *smb_fname_old = NULL;
5645 TALLOC_CTX *ctx = talloc_tos();
5646 NTSTATUS status = NT_STATUS_OK;
5648 /* Set a hard link. */
5649 if (total_data == 0) {
5650 return NT_STATUS_INVALID_PARAMETER;
5653 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5654 total_data, STR_TERMINATE, &status);
5655 if (!NT_STATUS_IS_OK(status)) {
5659 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5660 smb_fname_str_dbg(smb_fname_new), oldname));
5662 status = filename_convert(ctx,
5664 req->flags2 & FLAGS2_DFS_PATHNAMES,
5668 if (!NT_STATUS_IS_OK(status)) {
5672 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5675 /****************************************************************************
5676 Deal with SMB_FILE_RENAME_INFORMATION.
5677 ****************************************************************************/
5679 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5680 struct smb_request *req,
5689 char *newname = NULL;
5690 char *base_name = NULL;
5691 struct smb_filename *smb_fname = NULL;
5692 bool dest_has_wcard = False;
5693 NTSTATUS status = NT_STATUS_OK;
5695 TALLOC_CTX *ctx = talloc_tos();
5697 if (total_data < 13) {
5698 return NT_STATUS_INVALID_PARAMETER;
5701 overwrite = (CVAL(pdata,0) ? True : False);
5702 root_fid = IVAL(pdata,4);
5703 len = IVAL(pdata,8);
5705 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5706 return NT_STATUS_INVALID_PARAMETER;
5709 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5712 if (!NT_STATUS_IS_OK(status)) {
5716 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5719 status = resolve_dfspath_wcard(ctx, conn,
5720 req->flags2 & FLAGS2_DFS_PATHNAMES,
5724 if (!NT_STATUS_IS_OK(status)) {
5728 /* Check the new name has no '/' characters. */
5729 if (strchr_m(newname, '/')) {
5730 return NT_STATUS_NOT_SUPPORTED;
5733 if (fsp && fsp->base_fsp) {
5734 /* newname must be a stream name. */
5735 if (newname[0] != ':') {
5736 return NT_STATUS_NOT_SUPPORTED;
5739 /* Create an smb_fname to call rename_internals_fsp() with. */
5740 status = create_synthetic_smb_fname(talloc_tos(),
5741 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5743 if (!NT_STATUS_IS_OK(status)) {
5748 * Set the original last component, since
5749 * rename_internals_fsp() requires it.
5751 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5752 if (smb_fname->original_lcomp == NULL) {
5753 status = NT_STATUS_NO_MEMORY;
5757 /* Create a char * to call rename_internals() with. */
5758 base_name = talloc_asprintf(ctx, "%s%s",
5759 fsp->base_fsp->fsp_name->base_name,
5762 status = NT_STATUS_NO_MEMORY;
5766 /* newname must *not* be a stream name. */
5767 if (newname[0] == ':') {
5768 return NT_STATUS_NOT_SUPPORTED;
5771 /* Create the base directory. */
5772 base_name = talloc_strdup(ctx, fname);
5774 return NT_STATUS_NO_MEMORY;
5776 p = strrchr_m(base_name, '/');
5780 base_name = talloc_strdup(ctx, "./");
5782 return NT_STATUS_NO_MEMORY;
5785 /* Append the new name. */
5786 base_name = talloc_asprintf_append(base_name,
5790 return NT_STATUS_NO_MEMORY;
5793 status = unix_convert(ctx, conn, base_name, &smb_fname,
5796 /* If an error we expect this to be
5797 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5799 if (!NT_STATUS_IS_OK(status)) {
5800 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5804 /* Create an smb_fname to call rename_internals_fsp() */
5805 status = create_synthetic_smb_fname(talloc_tos(),
5808 if (!NT_STATUS_IS_OK(status)) {
5816 DEBUG(10,("smb_file_rename_information: "
5817 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5818 fsp->fnum, fsp_str_dbg(fsp), base_name));
5819 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5822 DEBUG(10,("smb_file_rename_information: "
5823 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5825 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5826 overwrite, False, dest_has_wcard,
5827 FILE_WRITE_ATTRIBUTES);
5830 TALLOC_FREE(smb_fname);
5834 /****************************************************************************
5835 Deal with SMB_SET_POSIX_ACL.
5836 ****************************************************************************/
5838 #if defined(HAVE_POSIX_ACLS)
5839 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5844 SMB_STRUCT_STAT *psbuf)
5846 uint16 posix_acl_version;
5847 uint16 num_file_acls;
5848 uint16 num_def_acls;
5849 bool valid_file_acls = True;
5850 bool valid_def_acls = True;
5852 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5853 return NT_STATUS_INVALID_PARAMETER;
5855 posix_acl_version = SVAL(pdata,0);
5856 num_file_acls = SVAL(pdata,2);
5857 num_def_acls = SVAL(pdata,4);
5859 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5860 valid_file_acls = False;
5864 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5865 valid_def_acls = False;
5869 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5870 return NT_STATUS_INVALID_PARAMETER;
5873 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5874 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5875 return NT_STATUS_INVALID_PARAMETER;
5878 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5879 fname ? fname : fsp_str_dbg(fsp),
5880 (unsigned int)num_file_acls,
5881 (unsigned int)num_def_acls));
5883 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5884 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5885 return map_nt_error_from_unix(errno);
5888 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5889 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5890 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5891 return map_nt_error_from_unix(errno);
5893 return NT_STATUS_OK;
5897 /****************************************************************************
5898 Deal with SMB_SET_POSIX_LOCK.
5899 ****************************************************************************/
5901 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5902 struct smb_request *req,
5910 bool blocking_lock = False;
5911 enum brl_type lock_type;
5913 NTSTATUS status = NT_STATUS_OK;
5915 if (fsp == NULL || fsp->fh->fd == -1) {
5916 return NT_STATUS_INVALID_HANDLE;
5919 if (total_data != POSIX_LOCK_DATA_SIZE) {
5920 return NT_STATUS_INVALID_PARAMETER;
5923 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5924 case POSIX_LOCK_TYPE_READ:
5925 lock_type = READ_LOCK;
5927 case POSIX_LOCK_TYPE_WRITE:
5928 /* Return the right POSIX-mappable error code for files opened read-only. */
5929 if (!fsp->can_write) {
5930 return NT_STATUS_INVALID_HANDLE;
5932 lock_type = WRITE_LOCK;
5934 case POSIX_LOCK_TYPE_UNLOCK:
5935 lock_type = UNLOCK_LOCK;
5938 return NT_STATUS_INVALID_PARAMETER;
5941 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5942 blocking_lock = False;
5943 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5944 blocking_lock = True;
5946 return NT_STATUS_INVALID_PARAMETER;
5949 if (!lp_blocking_locks(SNUM(conn))) {
5950 blocking_lock = False;
5953 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5954 #if defined(HAVE_LONGLONG)
5955 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5956 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5957 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5958 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5959 #else /* HAVE_LONGLONG */
5960 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5961 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5962 #endif /* HAVE_LONGLONG */
5964 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5965 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5967 (unsigned int)lock_type,
5968 (unsigned int)lock_pid,
5972 if (lock_type == UNLOCK_LOCK) {
5973 status = do_unlock(smbd_messaging_context(),
5980 uint32 block_smbpid;
5982 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5994 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5996 * A blocking lock was requested. Package up
5997 * this smb into a queued request and push it
5998 * onto the blocking lock queue.
6000 if(push_blocking_lock_request(br_lck,
6003 -1, /* infinite timeout. */
6011 TALLOC_FREE(br_lck);
6015 TALLOC_FREE(br_lck);
6021 /****************************************************************************
6022 Deal with SMB_INFO_STANDARD.
6023 ****************************************************************************/
6025 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6029 const struct smb_filename *smb_fname)
6031 struct smb_file_time ft;
6034 if (total_data < 12) {
6035 return NT_STATUS_INVALID_PARAMETER;
6039 ft.create_time = interpret_long_date(pdata);
6042 ft.atime = interpret_long_date(pdata + 8);
6045 ft.mtime = interpret_long_date(pdata + 16);
6047 DEBUG(10,("smb_set_info_standard: file %s\n",
6048 smb_fname_str_dbg(smb_fname)));
6050 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
6053 /****************************************************************************
6054 Deal with SMB_SET_FILE_BASIC_INFO.
6055 ****************************************************************************/
6057 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6061 const struct smb_filename *smb_fname)
6063 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6064 struct timespec write_time;
6065 struct timespec changed_time;
6066 struct smb_file_time ft;
6068 NTSTATUS status = NT_STATUS_OK;
6069 bool setting_write_time = true;
6073 if (total_data < 36) {
6074 return NT_STATUS_INVALID_PARAMETER;
6077 /* Set the attributes */
6078 dosmode = IVAL(pdata,32);
6079 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6080 if (!NT_STATUS_IS_OK(status)) {
6085 ft.atime = interpret_long_date(pdata+8);
6087 write_time = interpret_long_date(pdata+16);
6088 changed_time = interpret_long_date(pdata+24);
6091 ft.mtime = timespec_min(&write_time, &changed_time);
6094 ft.create_time = interpret_long_date(pdata);
6096 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
6097 !null_timespec(write_time)) {
6098 ft.mtime = write_time;
6101 /* Prefer a defined time to an undefined one. */
6102 if (null_timespec(ft.mtime)) {
6103 if (null_timespec(write_time)) {
6104 ft.mtime = changed_time;
6105 setting_write_time = false;
6107 ft.mtime = write_time;
6111 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6112 smb_fname_str_dbg(smb_fname)));
6114 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6115 setting_write_time);
6118 /****************************************************************************
6119 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6120 ****************************************************************************/
6122 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6123 struct smb_request *req,
6127 struct smb_filename *smb_fname)
6129 uint64_t allocation_size = 0;
6130 NTSTATUS status = NT_STATUS_OK;
6131 files_struct *new_fsp = NULL;
6133 if (!VALID_STAT(smb_fname->st)) {
6134 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6137 if (total_data < 8) {
6138 return NT_STATUS_INVALID_PARAMETER;
6141 allocation_size = (uint64_t)IVAL(pdata,0);
6142 #ifdef LARGE_SMB_OFF_T
6143 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6144 #else /* LARGE_SMB_OFF_T */
6145 if (IVAL(pdata,4) != 0) {
6146 /* more than 32 bits? */
6147 return NT_STATUS_INVALID_PARAMETER;
6149 #endif /* LARGE_SMB_OFF_T */
6151 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6152 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6153 (double)allocation_size));
6155 if (allocation_size) {
6156 allocation_size = smb_roundup(conn, allocation_size);
6159 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6160 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6161 (double)allocation_size));
6163 if (fsp && fsp->fh->fd != -1) {
6164 /* Open file handle. */
6165 /* Only change if needed. */
6166 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6167 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6168 return map_nt_error_from_unix(errno);
6171 /* But always update the time. */
6173 * This is equivalent to a write. Ensure it's seen immediately
6174 * if there are no pending writes.
6176 trigger_write_time_update_immediate(fsp);
6177 return NT_STATUS_OK;
6180 /* Pathname or stat or directory file. */
6181 status = SMB_VFS_CREATE_FILE(
6184 0, /* root_dir_fid */
6185 smb_fname, /* fname */
6186 FILE_WRITE_DATA, /* access_mask */
6187 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6189 FILE_OPEN, /* create_disposition*/
6190 0, /* create_options */
6191 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6192 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6193 0, /* allocation_size */
6196 &new_fsp, /* result */
6199 if (!NT_STATUS_IS_OK(status)) {
6200 /* NB. We check for open_was_deferred in the caller. */
6204 /* Only change if needed. */
6205 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6206 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6207 status = map_nt_error_from_unix(errno);
6208 close_file(req, new_fsp, NORMAL_CLOSE);
6213 /* Changing the allocation size should set the last mod time. */
6215 * This is equivalent to a write. Ensure it's seen immediately
6216 * if there are no pending writes.
6218 trigger_write_time_update_immediate(new_fsp);
6220 close_file(req, new_fsp, NORMAL_CLOSE);
6221 return NT_STATUS_OK;
6224 /****************************************************************************
6225 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6226 ****************************************************************************/
6228 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6229 struct smb_request *req,
6233 const struct smb_filename *smb_fname)
6237 if (total_data < 8) {
6238 return NT_STATUS_INVALID_PARAMETER;
6241 size = IVAL(pdata,0);
6242 #ifdef LARGE_SMB_OFF_T
6243 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6244 #else /* LARGE_SMB_OFF_T */
6245 if (IVAL(pdata,4) != 0) {
6246 /* more than 32 bits? */
6247 return NT_STATUS_INVALID_PARAMETER;
6249 #endif /* LARGE_SMB_OFF_T */
6250 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6251 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6254 return smb_set_file_size(conn, req,
6261 /****************************************************************************
6262 Allow a UNIX info mknod.
6263 ****************************************************************************/
6265 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6268 const struct smb_filename *smb_fname)
6270 uint32 file_type = IVAL(pdata,56);
6271 #if defined(HAVE_MAKEDEV)
6272 uint32 dev_major = IVAL(pdata,60);
6273 uint32 dev_minor = IVAL(pdata,68);
6275 SMB_DEV_T dev = (SMB_DEV_T)0;
6276 uint32 raw_unixmode = IVAL(pdata,84);
6280 if (total_data < 100) {
6281 return NT_STATUS_INVALID_PARAMETER;
6284 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6285 PERM_NEW_FILE, &unixmode);
6286 if (!NT_STATUS_IS_OK(status)) {
6290 #if defined(HAVE_MAKEDEV)
6291 dev = makedev(dev_major, dev_minor);
6294 switch (file_type) {
6295 #if defined(S_IFIFO)
6296 case UNIX_TYPE_FIFO:
6297 unixmode |= S_IFIFO;
6300 #if defined(S_IFSOCK)
6301 case UNIX_TYPE_SOCKET:
6302 unixmode |= S_IFSOCK;
6305 #if defined(S_IFCHR)
6306 case UNIX_TYPE_CHARDEV:
6307 unixmode |= S_IFCHR;
6310 #if defined(S_IFBLK)
6311 case UNIX_TYPE_BLKDEV:
6312 unixmode |= S_IFBLK;
6316 return NT_STATUS_INVALID_PARAMETER;
6319 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6320 "%.0f mode 0%o for file %s\n", (double)dev,
6321 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6323 /* Ok - do the mknod. */
6324 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6325 return map_nt_error_from_unix(errno);
6328 /* If any of the other "set" calls fail we
6329 * don't want to end up with a half-constructed mknod.
6332 if (lp_inherit_perms(SNUM(conn))) {
6334 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6336 return NT_STATUS_NO_MEMORY;
6338 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6340 TALLOC_FREE(parent);
6343 return NT_STATUS_OK;
6346 /****************************************************************************
6347 Deal with SMB_SET_FILE_UNIX_BASIC.
6348 ****************************************************************************/
6350 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6351 struct smb_request *req,
6355 const struct smb_filename *smb_fname)
6357 struct smb_file_time ft;
6358 uint32 raw_unixmode;
6361 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6362 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6363 NTSTATUS status = NT_STATUS_OK;
6364 bool delete_on_fail = False;
6365 enum perm_type ptype;
6366 files_struct *all_fsps = NULL;
6367 bool modify_mtime = true;
6369 SMB_STRUCT_STAT sbuf;
6373 if (total_data < 100) {
6374 return NT_STATUS_INVALID_PARAMETER;
6377 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6378 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6379 size=IVAL(pdata,0); /* first 8 Bytes are size */
6380 #ifdef LARGE_SMB_OFF_T
6381 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6382 #else /* LARGE_SMB_OFF_T */
6383 if (IVAL(pdata,4) != 0) {
6384 /* more than 32 bits? */
6385 return NT_STATUS_INVALID_PARAMETER;
6387 #endif /* LARGE_SMB_OFF_T */
6390 ft.atime = interpret_long_date(pdata+24); /* access_time */
6391 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6392 set_owner = (uid_t)IVAL(pdata,40);
6393 set_grp = (gid_t)IVAL(pdata,48);
6394 raw_unixmode = IVAL(pdata,84);
6396 if (VALID_STAT(smb_fname->st)) {
6397 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6398 ptype = PERM_EXISTING_DIR;
6400 ptype = PERM_EXISTING_FILE;
6403 ptype = PERM_NEW_FILE;
6406 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6408 if (!NT_STATUS_IS_OK(status)) {
6412 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6413 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6414 smb_fname_str_dbg(smb_fname), (double)size,
6415 (unsigned int)set_owner, (unsigned int)set_grp,
6416 (int)raw_unixmode));
6418 sbuf = smb_fname->st;
6420 if (!VALID_STAT(sbuf)) {
6421 struct smb_filename *smb_fname_tmp = NULL;
6423 * The only valid use of this is to create character and block
6424 * devices, and named pipes. This is deprecated (IMHO) and
6425 * a new info level should be used for mknod. JRA.
6428 status = smb_unix_mknod(conn,
6432 if (!NT_STATUS_IS_OK(status)) {
6436 status = copy_smb_filename(talloc_tos(), smb_fname,
6438 if (!NT_STATUS_IS_OK(status)) {
6442 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6443 status = map_nt_error_from_unix(errno);
6444 TALLOC_FREE(smb_fname_tmp);
6445 SMB_VFS_UNLINK(conn, smb_fname);
6449 sbuf = smb_fname_tmp->st;
6450 TALLOC_FREE(smb_fname_tmp);
6452 /* Ensure we don't try and change anything else. */
6453 raw_unixmode = SMB_MODE_NO_CHANGE;
6454 size = get_file_size_stat(&sbuf);
6455 ft.atime = sbuf.st_ex_atime;
6456 ft.mtime = sbuf.st_ex_mtime;
6458 * We continue here as we might want to change the
6461 delete_on_fail = True;
6465 /* Horrible backwards compatibility hack as an old server bug
6466 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6470 size = get_file_size_stat(&sbuf);
6475 * Deal with the UNIX specific mode set.
6478 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6479 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6480 "setting mode 0%o for file %s\n",
6481 (unsigned int)unixmode,
6482 smb_fname_str_dbg(smb_fname)));
6483 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6484 return map_nt_error_from_unix(errno);
6489 * Deal with the UNIX specific uid set.
6492 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6493 (sbuf.st_ex_uid != set_owner)) {
6496 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6497 "changing owner %u for path %s\n",
6498 (unsigned int)set_owner,
6499 smb_fname_str_dbg(smb_fname)));
6501 if (S_ISLNK(sbuf.st_ex_mode)) {
6502 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6503 set_owner, (gid_t)-1);
6505 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6506 set_owner, (gid_t)-1);
6510 status = map_nt_error_from_unix(errno);
6511 if (delete_on_fail) {
6512 SMB_VFS_UNLINK(conn, smb_fname);
6519 * Deal with the UNIX specific gid set.
6522 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6523 (sbuf.st_ex_gid != set_grp)) {
6524 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6525 "changing group %u for file %s\n",
6526 (unsigned int)set_owner,
6527 smb_fname_str_dbg(smb_fname)));
6528 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6530 status = map_nt_error_from_unix(errno);
6531 if (delete_on_fail) {
6532 SMB_VFS_UNLINK(conn, smb_fname);
6538 /* Deal with any size changes. */
6540 status = smb_set_file_size(conn, req,
6545 if (!NT_STATUS_IS_OK(status)) {
6549 /* Deal with any time changes. */
6550 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6551 /* No change, don't cancel anything. */
6555 id = vfs_file_id_from_sbuf(conn, &sbuf);
6556 for(all_fsps = file_find_di_first(id); all_fsps;
6557 all_fsps = file_find_di_next(all_fsps)) {
6559 * We're setting the time explicitly for UNIX.
6560 * Cancel any pending changes over all handles.
6562 all_fsps->update_write_time_on_close = false;
6563 TALLOC_FREE(all_fsps->update_write_time_event);
6567 * Override the "setting_write_time"
6568 * parameter here as it almost does what
6569 * we need. Just remember if we modified
6570 * mtime and send the notify ourselves.
6572 if (null_timespec(ft.mtime)) {
6573 modify_mtime = false;
6576 status = smb_set_file_time(conn,
6582 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6583 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6588 /****************************************************************************
6589 Deal with SMB_SET_FILE_UNIX_INFO2.
6590 ****************************************************************************/
6592 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6593 struct smb_request *req,
6597 const struct smb_filename *smb_fname)
6603 if (total_data < 116) {
6604 return NT_STATUS_INVALID_PARAMETER;
6607 /* Start by setting all the fields that are common between UNIX_BASIC
6610 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6612 if (!NT_STATUS_IS_OK(status)) {
6616 smb_fflags = IVAL(pdata, 108);
6617 smb_fmask = IVAL(pdata, 112);
6619 /* NB: We should only attempt to alter the file flags if the client
6620 * sends a non-zero mask.
6622 if (smb_fmask != 0) {
6623 int stat_fflags = 0;
6625 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6626 smb_fmask, &stat_fflags)) {
6627 /* Client asked to alter a flag we don't understand. */
6628 return NT_STATUS_INVALID_PARAMETER;
6631 if (fsp && fsp->fh->fd != -1) {
6632 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6633 return NT_STATUS_NOT_SUPPORTED;
6635 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6636 stat_fflags) != 0) {
6637 return map_nt_error_from_unix(errno);
6642 /* XXX: need to add support for changing the create_time here. You
6643 * can do this for paths on Darwin with setattrlist(2). The right way
6644 * to hook this up is probably by extending the VFS utimes interface.
6647 return NT_STATUS_OK;
6650 /****************************************************************************
6651 Create a directory with POSIX semantics.
6652 ****************************************************************************/
6654 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6655 struct smb_request *req,
6659 SMB_STRUCT_STAT *psbuf,
6660 int *pdata_return_size)
6662 struct smb_filename *smb_fname;
6663 NTSTATUS status = NT_STATUS_OK;
6664 uint32 raw_unixmode = 0;
6665 uint32 mod_unixmode = 0;
6666 mode_t unixmode = (mode_t)0;
6667 files_struct *fsp = NULL;
6668 uint16 info_level_return = 0;
6670 char *pdata = *ppdata;
6672 if (total_data < 18) {
6673 return NT_STATUS_INVALID_PARAMETER;
6676 raw_unixmode = IVAL(pdata,8);
6677 /* Next 4 bytes are not yet defined. */
6679 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6680 if (!NT_STATUS_IS_OK(status)) {
6684 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6686 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6687 fname, (unsigned int)unixmode ));
6689 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6691 if (!NT_STATUS_IS_OK(status)) {
6695 status = SMB_VFS_CREATE_FILE(
6698 0, /* root_dir_fid */
6699 smb_fname, /* fname */
6700 FILE_READ_ATTRIBUTES, /* access_mask */
6701 FILE_SHARE_NONE, /* share_access */
6702 FILE_CREATE, /* create_disposition*/
6703 FILE_DIRECTORY_FILE, /* create_options */
6704 mod_unixmode, /* file_attributes */
6705 0, /* oplock_request */
6706 0, /* allocation_size */
6712 *psbuf = smb_fname->st;
6713 TALLOC_FREE(smb_fname);
6715 if (NT_STATUS_IS_OK(status)) {
6716 close_file(req, fsp, NORMAL_CLOSE);
6719 info_level_return = SVAL(pdata,16);
6721 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6722 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6723 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6724 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6726 *pdata_return_size = 12;
6729 /* Realloc the data size */
6730 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6731 if (*ppdata == NULL) {
6732 *pdata_return_size = 0;
6733 return NT_STATUS_NO_MEMORY;
6737 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6738 SSVAL(pdata,2,0); /* No fnum. */
6739 SIVAL(pdata,4,info); /* Was directory created. */
6741 switch (info_level_return) {
6742 case SMB_QUERY_FILE_UNIX_BASIC:
6743 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6744 SSVAL(pdata,10,0); /* Padding. */
6745 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6747 case SMB_QUERY_FILE_UNIX_INFO2:
6748 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6749 SSVAL(pdata,10,0); /* Padding. */
6750 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6753 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6754 SSVAL(pdata,10,0); /* Padding. */
6761 /****************************************************************************
6762 Open/Create a file with POSIX semantics.
6763 ****************************************************************************/
6765 static NTSTATUS smb_posix_open(connection_struct *conn,
6766 struct smb_request *req,
6770 SMB_STRUCT_STAT *psbuf,
6771 int *pdata_return_size)
6773 struct smb_filename *smb_fname = NULL;
6774 bool extended_oplock_granted = False;
6775 char *pdata = *ppdata;
6777 uint32 wire_open_mode = 0;
6778 uint32 raw_unixmode = 0;
6779 uint32 mod_unixmode = 0;
6780 uint32 create_disp = 0;
6781 uint32 access_mask = 0;
6782 uint32 create_options = 0;
6783 NTSTATUS status = NT_STATUS_OK;
6784 mode_t unixmode = (mode_t)0;
6785 files_struct *fsp = NULL;
6786 int oplock_request = 0;
6788 uint16 info_level_return = 0;
6790 if (total_data < 18) {
6791 return NT_STATUS_INVALID_PARAMETER;
6794 flags = IVAL(pdata,0);
6795 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6796 if (oplock_request) {
6797 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6800 wire_open_mode = IVAL(pdata,4);
6802 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6803 return smb_posix_mkdir(conn, req,
6811 switch (wire_open_mode & SMB_ACCMODE) {
6813 access_mask = FILE_READ_DATA;
6816 access_mask = FILE_WRITE_DATA;
6819 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6822 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6823 (unsigned int)wire_open_mode ));
6824 return NT_STATUS_INVALID_PARAMETER;
6827 wire_open_mode &= ~SMB_ACCMODE;
6829 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6830 create_disp = FILE_CREATE;
6831 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6832 create_disp = FILE_OVERWRITE_IF;
6833 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6834 create_disp = FILE_OPEN_IF;
6835 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6836 create_disp = FILE_OPEN;
6838 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6839 (unsigned int)wire_open_mode ));
6840 return NT_STATUS_INVALID_PARAMETER;
6843 raw_unixmode = IVAL(pdata,8);
6844 /* Next 4 bytes are not yet defined. */
6846 status = unix_perms_from_wire(conn,
6849 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6852 if (!NT_STATUS_IS_OK(status)) {
6856 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6858 if (wire_open_mode & SMB_O_SYNC) {
6859 create_options |= FILE_WRITE_THROUGH;
6861 if (wire_open_mode & SMB_O_APPEND) {
6862 access_mask |= FILE_APPEND_DATA;
6864 if (wire_open_mode & SMB_O_DIRECT) {
6865 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6868 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6870 (unsigned int)wire_open_mode,
6871 (unsigned int)unixmode ));
6873 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6875 if (!NT_STATUS_IS_OK(status)) {
6879 status = SMB_VFS_CREATE_FILE(
6882 0, /* root_dir_fid */
6883 smb_fname, /* fname */
6884 access_mask, /* access_mask */
6885 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6887 create_disp, /* create_disposition*/
6888 FILE_NON_DIRECTORY_FILE, /* create_options */
6889 mod_unixmode, /* file_attributes */
6890 oplock_request, /* oplock_request */
6891 0, /* allocation_size */
6897 *psbuf = smb_fname->st;
6898 TALLOC_FREE(smb_fname);
6900 if (!NT_STATUS_IS_OK(status)) {
6904 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6905 extended_oplock_granted = True;
6908 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6909 extended_oplock_granted = True;
6912 info_level_return = SVAL(pdata,16);
6914 /* Allocate the correct return size. */
6916 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6917 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6918 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6919 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6921 *pdata_return_size = 12;
6924 /* Realloc the data size */
6925 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6926 if (*ppdata == NULL) {
6927 close_file(req, fsp, ERROR_CLOSE);
6928 *pdata_return_size = 0;
6929 return NT_STATUS_NO_MEMORY;
6933 if (extended_oplock_granted) {
6934 if (flags & REQUEST_BATCH_OPLOCK) {
6935 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6937 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6939 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6940 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6942 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6945 SSVAL(pdata,2,fsp->fnum);
6946 SIVAL(pdata,4,info); /* Was file created etc. */
6948 switch (info_level_return) {
6949 case SMB_QUERY_FILE_UNIX_BASIC:
6950 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6951 SSVAL(pdata,10,0); /* padding. */
6952 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6954 case SMB_QUERY_FILE_UNIX_INFO2:
6955 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6956 SSVAL(pdata,10,0); /* padding. */
6957 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6960 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6961 SSVAL(pdata,10,0); /* padding. */
6964 return NT_STATUS_OK;
6967 /****************************************************************************
6968 Delete a file with POSIX semantics.
6969 ****************************************************************************/
6971 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6972 struct smb_request *req,
6975 struct smb_filename *smb_fname)
6977 NTSTATUS status = NT_STATUS_OK;
6978 files_struct *fsp = NULL;
6982 int create_options = 0;
6984 struct share_mode_lock *lck = NULL;
6986 if (total_data < 2) {
6987 return NT_STATUS_INVALID_PARAMETER;
6990 flags = SVAL(pdata,0);
6992 if (!VALID_STAT(smb_fname->st)) {
6993 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6996 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6997 !VALID_STAT_OF_DIR(smb_fname->st)) {
6998 return NT_STATUS_NOT_A_DIRECTORY;
7001 DEBUG(10,("smb_posix_unlink: %s %s\n",
7002 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7003 smb_fname_str_dbg(smb_fname)));
7005 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7006 create_options |= FILE_DIRECTORY_FILE;
7009 status = SMB_VFS_CREATE_FILE(
7012 0, /* root_dir_fid */
7013 smb_fname, /* fname */
7014 DELETE_ACCESS, /* access_mask */
7015 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7017 FILE_OPEN, /* create_disposition*/
7018 create_options, /* create_options */
7019 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7020 0, /* oplock_request */
7021 0, /* allocation_size */
7027 if (!NT_STATUS_IS_OK(status)) {
7032 * Don't lie to client. If we can't really delete due to
7033 * non-POSIX opens return SHARING_VIOLATION.
7036 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7039 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7040 "lock for file %s\n", fsp_str_dbg(fsp)));
7041 close_file(req, fsp, NORMAL_CLOSE);
7042 return NT_STATUS_INVALID_PARAMETER;
7046 * See if others still have the file open. If this is the case, then
7047 * don't delete. If all opens are POSIX delete we can set the delete
7048 * on close disposition.
7050 for (i=0; i<lck->num_share_modes; i++) {
7051 struct share_mode_entry *e = &lck->share_modes[i];
7052 if (is_valid_share_mode_entry(e)) {
7053 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7056 /* Fail with sharing violation. */
7057 close_file(req, fsp, NORMAL_CLOSE);
7059 return NT_STATUS_SHARING_VIOLATION;
7064 * Set the delete on close.
7066 status = smb_set_file_disposition_info(conn,
7072 if (!NT_STATUS_IS_OK(status)) {
7073 close_file(req, fsp, NORMAL_CLOSE);
7078 return close_file(req, fsp, NORMAL_CLOSE);
7081 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7082 struct smb_request *req,
7083 TALLOC_CTX *mem_ctx,
7084 uint16_t info_level,
7086 struct smb_filename *smb_fname,
7087 char **ppdata, int total_data,
7090 char *pdata = *ppdata;
7091 SMB_STRUCT_STAT sbuf;
7093 NTSTATUS status = NT_STATUS_OK;
7094 int data_return_size = 0;
7098 /* Set sbuf for use below. */
7099 sbuf = smb_fname->st;
7101 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7102 return NT_STATUS_INVALID_LEVEL;
7105 if (!CAN_WRITE(conn)) {
7106 /* Allow POSIX opens. The open path will deny
7107 * any non-readonly opens. */
7108 if (info_level != SMB_POSIX_PATH_OPEN) {
7109 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7113 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
7114 if (!NT_STATUS_IS_OK(status)) {
7118 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d totdata=%d\n",
7119 fname, fsp ? fsp->fnum : -1, info_level, total_data));
7121 switch (info_level) {
7123 case SMB_INFO_STANDARD:
7125 status = smb_set_info_standard(conn,
7133 case SMB_INFO_SET_EA:
7135 status = smb_info_set_ea(conn,
7143 case SMB_SET_FILE_BASIC_INFO:
7144 case SMB_FILE_BASIC_INFORMATION:
7146 status = smb_set_file_basic_info(conn,
7154 case SMB_FILE_ALLOCATION_INFORMATION:
7155 case SMB_SET_FILE_ALLOCATION_INFO:
7157 status = smb_set_file_allocation_info(conn, req,
7165 case SMB_FILE_END_OF_FILE_INFORMATION:
7166 case SMB_SET_FILE_END_OF_FILE_INFO:
7168 status = smb_set_file_end_of_file_info(conn, req,
7176 case SMB_FILE_DISPOSITION_INFORMATION:
7177 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7180 /* JRA - We used to just ignore this on a path ?
7181 * Shouldn't this be invalid level on a pathname
7184 if (tran_call != TRANSACT2_SETFILEINFO) {
7185 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7188 status = smb_set_file_disposition_info(conn,
7196 case SMB_FILE_POSITION_INFORMATION:
7198 status = smb_file_position_information(conn,
7205 /* From tridge Samba4 :
7206 * MODE_INFORMATION in setfileinfo (I have no
7207 * idea what "mode information" on a file is - it takes a value of 0,
7208 * 2, 4 or 6. What could it be?).
7211 case SMB_FILE_MODE_INFORMATION:
7213 status = smb_file_mode_information(conn,
7220 * CIFS UNIX extensions.
7223 case SMB_SET_FILE_UNIX_BASIC:
7225 status = smb_set_file_unix_basic(conn, req,
7233 case SMB_SET_FILE_UNIX_INFO2:
7235 status = smb_set_file_unix_info2(conn, req,
7243 case SMB_SET_FILE_UNIX_LINK:
7246 /* We must have a pathname for this. */
7247 return NT_STATUS_INVALID_LEVEL;
7249 status = smb_set_file_unix_link(conn, req, pdata,
7254 case SMB_SET_FILE_UNIX_HLINK:
7257 /* We must have a pathname for this. */
7258 return NT_STATUS_INVALID_LEVEL;
7260 status = smb_set_file_unix_hlink(conn, req,
7266 case SMB_FILE_RENAME_INFORMATION:
7268 status = smb_file_rename_information(conn, req,
7274 #if defined(HAVE_POSIX_ACLS)
7275 case SMB_SET_POSIX_ACL:
7277 status = smb_set_posix_acl(conn,
7287 case SMB_SET_POSIX_LOCK:
7290 return NT_STATUS_INVALID_LEVEL;
7292 status = smb_set_posix_lock(conn, req,
7293 pdata, total_data, fsp);
7297 case SMB_POSIX_PATH_OPEN:
7300 /* We must have a pathname for this. */
7301 return NT_STATUS_INVALID_LEVEL;
7304 status = smb_posix_open(conn, req,
7313 case SMB_POSIX_PATH_UNLINK:
7316 /* We must have a pathname for this. */
7317 return NT_STATUS_INVALID_LEVEL;
7320 status = smb_posix_unlink(conn, req,
7328 return NT_STATUS_INVALID_LEVEL;
7331 if (!NT_STATUS_IS_OK(status)) {
7335 *ret_data_size = data_return_size;
7336 return NT_STATUS_OK;
7339 /****************************************************************************
7340 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7341 ****************************************************************************/
7343 static void call_trans2setfilepathinfo(connection_struct *conn,
7344 struct smb_request *req,
7345 unsigned int tran_call,
7346 char **pparams, int total_params,
7347 char **ppdata, int total_data,
7348 unsigned int max_data_bytes)
7350 char *params = *pparams;
7351 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));
7449 if (total_params < 7) {
7450 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7454 info_level = SVAL(params,0);
7455 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7456 total_params - 6, STR_TERMINATE,
7458 if (!NT_STATUS_IS_OK(status)) {
7459 reply_nterror(req, status);
7463 status = filename_convert(req, conn,
7464 req->flags2 & FLAGS2_DFS_PATHNAMES,
7468 if (!NT_STATUS_IS_OK(status)) {
7469 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7470 reply_botherror(req,
7471 NT_STATUS_PATH_NOT_COVERED,
7472 ERRSRV, ERRbadpath);
7475 reply_nterror(req, status);
7479 if (INFO_LEVEL_IS_UNIX(info_level)) {
7481 * For CIFS UNIX extensions the target name may not exist.
7484 /* Always do lstat for UNIX calls. */
7485 SMB_VFS_LSTAT(conn, smb_fname);
7487 } else if (!VALID_STAT(smb_fname->st) &&
7488 SMB_VFS_STAT(conn, smb_fname)) {
7489 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7491 smb_fname_str_dbg(smb_fname),
7493 reply_nterror(req, map_nt_error_from_unix(errno));
7498 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
7499 tran_call, fname, fsp ? fsp->fnum : -1, info_level,total_data));
7501 /* Realloc the parameter size */
7502 *pparams = (char *)SMB_REALLOC(*pparams,2);
7503 if (*pparams == NULL) {
7504 reply_nterror(req, NT_STATUS_NO_MEMORY);
7511 status = smbd_do_setfilepathinfo(conn, req, req,
7517 if (!NT_STATUS_IS_OK(status)) {
7518 if (open_was_deferred(req->mid)) {
7519 /* We have re-scheduled this call. */
7522 if (blocking_lock_was_deferred(req->mid)) {
7523 /* We have re-scheduled this call. */
7526 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7527 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7528 ERRSRV, ERRbadpath);
7531 if (info_level == SMB_POSIX_PATH_OPEN) {
7532 reply_openerror(req, status);
7536 reply_nterror(req, status);
7540 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7546 /****************************************************************************
7547 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7548 ****************************************************************************/
7550 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7551 char **pparams, int total_params,
7552 char **ppdata, int total_data,
7553 unsigned int max_data_bytes)
7555 struct smb_filename *smb_dname = NULL;
7556 char *params = *pparams;
7557 char *pdata = *ppdata;
7558 char *directory = NULL;
7559 NTSTATUS status = NT_STATUS_OK;
7560 struct ea_list *ea_list = NULL;
7561 TALLOC_CTX *ctx = talloc_tos();
7563 if (!CAN_WRITE(conn)) {
7564 reply_doserror(req, ERRSRV, ERRaccess);
7568 if (total_params < 5) {
7569 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7573 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7574 total_params - 4, STR_TERMINATE,
7576 if (!NT_STATUS_IS_OK(status)) {
7577 reply_nterror(req, status);
7581 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7583 status = filename_convert(ctx,
7585 req->flags2 & FLAGS2_DFS_PATHNAMES,
7590 if (!NT_STATUS_IS_OK(status)) {
7591 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7592 reply_botherror(req,
7593 NT_STATUS_PATH_NOT_COVERED,
7594 ERRSRV, ERRbadpath);
7597 reply_nterror(req, status);
7601 /* Any data in this call is an EA list. */
7602 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7603 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7608 * OS/2 workplace shell seems to send SET_EA requests of "null"
7609 * length (4 bytes containing IVAL 4).
7610 * They seem to have no effect. Bug #3212. JRA.
7613 if (total_data != 4) {
7614 if (total_data < 10) {
7615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7619 if (IVAL(pdata,0) > total_data) {
7620 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7621 IVAL(pdata,0), (unsigned int)total_data));
7622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7626 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7633 /* If total_data == 4 Windows doesn't care what values
7634 * are placed in that field, it just ignores them.
7635 * The System i QNTC IBM SMB client puts bad values here,
7636 * so ignore them. */
7638 status = create_directory(conn, req, smb_dname);
7640 if (!NT_STATUS_IS_OK(status)) {
7641 reply_nterror(req, status);
7645 /* Try and set any given EA. */
7647 status = set_ea(conn, NULL, smb_dname, ea_list);
7648 if (!NT_STATUS_IS_OK(status)) {
7649 reply_nterror(req, status);
7654 /* Realloc the parameter and data sizes */
7655 *pparams = (char *)SMB_REALLOC(*pparams,2);
7656 if(*pparams == NULL) {
7657 reply_nterror(req, NT_STATUS_NO_MEMORY);
7664 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7667 TALLOC_FREE(smb_dname);
7671 /****************************************************************************
7672 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7673 We don't actually do this - we just send a null response.
7674 ****************************************************************************/
7676 static void call_trans2findnotifyfirst(connection_struct *conn,
7677 struct smb_request *req,
7678 char **pparams, int total_params,
7679 char **ppdata, int total_data,
7680 unsigned int max_data_bytes)
7682 char *params = *pparams;
7685 if (total_params < 6) {
7686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7690 info_level = SVAL(params,4);
7691 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7693 switch (info_level) {
7698 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7702 /* Realloc the parameter and data sizes */
7703 *pparams = (char *)SMB_REALLOC(*pparams,6);
7704 if (*pparams == NULL) {
7705 reply_nterror(req, NT_STATUS_NO_MEMORY);
7710 SSVAL(params,0,fnf_handle);
7711 SSVAL(params,2,0); /* No changes */
7712 SSVAL(params,4,0); /* No EA errors */
7719 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7724 /****************************************************************************
7725 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7726 changes). Currently this does nothing.
7727 ****************************************************************************/
7729 static void call_trans2findnotifynext(connection_struct *conn,
7730 struct smb_request *req,
7731 char **pparams, int total_params,
7732 char **ppdata, int total_data,
7733 unsigned int max_data_bytes)
7735 char *params = *pparams;
7737 DEBUG(3,("call_trans2findnotifynext\n"));
7739 /* Realloc the parameter and data sizes */
7740 *pparams = (char *)SMB_REALLOC(*pparams,4);
7741 if (*pparams == NULL) {
7742 reply_nterror(req, NT_STATUS_NO_MEMORY);
7747 SSVAL(params,0,0); /* No changes */
7748 SSVAL(params,2,0); /* No EA errors */
7750 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7755 /****************************************************************************
7756 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7757 ****************************************************************************/
7759 static void call_trans2getdfsreferral(connection_struct *conn,
7760 struct smb_request *req,
7761 char **pparams, int total_params,
7762 char **ppdata, int total_data,
7763 unsigned int max_data_bytes)
7765 char *params = *pparams;
7766 char *pathname = NULL;
7768 int max_referral_level;
7769 NTSTATUS status = NT_STATUS_OK;
7770 TALLOC_CTX *ctx = talloc_tos();
7772 DEBUG(10,("call_trans2getdfsreferral\n"));
7774 if (total_params < 3) {
7775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7779 max_referral_level = SVAL(params,0);
7781 if(!lp_host_msdfs()) {
7782 reply_doserror(req, ERRDOS, ERRbadfunc);
7786 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7787 total_params - 2, STR_TERMINATE);
7789 reply_nterror(req, NT_STATUS_NOT_FOUND);
7792 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7793 ppdata,&status)) < 0) {
7794 reply_nterror(req, status);
7798 SSVAL(req->inbuf, smb_flg2,
7799 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7800 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7805 #define LMCAT_SPL 0x53
7806 #define LMFUNC_GETJOBID 0x60
7808 /****************************************************************************
7809 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7810 ****************************************************************************/
7812 static void call_trans2ioctl(connection_struct *conn,
7813 struct smb_request *req,
7814 char **pparams, int total_params,
7815 char **ppdata, int total_data,
7816 unsigned int max_data_bytes)
7818 char *pdata = *ppdata;
7819 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7821 /* check for an invalid fid before proceeding */
7824 reply_doserror(req, ERRDOS, ERRbadfid);
7828 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7829 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7830 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7831 if (*ppdata == NULL) {
7832 reply_nterror(req, NT_STATUS_NO_MEMORY);
7837 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7838 CAN ACCEPT THIS IN UNICODE. JRA. */
7840 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7841 srvstr_push(pdata, req->flags2, pdata + 2,
7842 global_myname(), 15,
7843 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7844 srvstr_push(pdata, req->flags2, pdata+18,
7845 lp_servicename(SNUM(conn)), 13,
7846 STR_ASCII|STR_TERMINATE); /* Service name */
7847 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7852 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7853 reply_doserror(req, ERRSRV, ERRerror);
7856 /****************************************************************************
7857 Reply to a SMBfindclose (stop trans2 directory search).
7858 ****************************************************************************/
7860 void reply_findclose(struct smb_request *req)
7864 START_PROFILE(SMBfindclose);
7867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7868 END_PROFILE(SMBfindclose);
7872 dptr_num = SVALS(req->vwv+0, 0);
7874 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7876 dptr_close(&dptr_num);
7878 reply_outbuf(req, 0, 0);
7880 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7882 END_PROFILE(SMBfindclose);
7886 /****************************************************************************
7887 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7888 ****************************************************************************/
7890 void reply_findnclose(struct smb_request *req)
7894 START_PROFILE(SMBfindnclose);
7897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7898 END_PROFILE(SMBfindnclose);
7902 dptr_num = SVAL(req->vwv+0, 0);
7904 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7906 /* We never give out valid handles for a
7907 findnotifyfirst - so any dptr_num is ok here.
7910 reply_outbuf(req, 0, 0);
7912 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7914 END_PROFILE(SMBfindnclose);
7918 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7919 struct trans_state *state)
7921 if (Protocol >= PROTOCOL_NT1) {
7922 req->flags2 |= 0x40; /* IS_LONG_NAME */
7923 SSVAL(req->inbuf,smb_flg2,req->flags2);
7926 if (conn->encrypt_level == Required && !req->encrypted) {
7927 if (state->call != TRANSACT2_QFSINFO &&
7928 state->call != TRANSACT2_SETFSINFO) {
7929 DEBUG(0,("handle_trans2: encryption required "
7931 (unsigned int)state->call));
7932 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7937 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7939 /* Now we must call the relevant TRANS2 function */
7940 switch(state->call) {
7941 case TRANSACT2_OPEN:
7943 START_PROFILE(Trans2_open);
7944 call_trans2open(conn, req,
7945 &state->param, state->total_param,
7946 &state->data, state->total_data,
7947 state->max_data_return);
7948 END_PROFILE(Trans2_open);
7952 case TRANSACT2_FINDFIRST:
7954 START_PROFILE(Trans2_findfirst);
7955 call_trans2findfirst(conn, req,
7956 &state->param, state->total_param,
7957 &state->data, state->total_data,
7958 state->max_data_return);
7959 END_PROFILE(Trans2_findfirst);
7963 case TRANSACT2_FINDNEXT:
7965 START_PROFILE(Trans2_findnext);
7966 call_trans2findnext(conn, req,
7967 &state->param, state->total_param,
7968 &state->data, state->total_data,
7969 state->max_data_return);
7970 END_PROFILE(Trans2_findnext);
7974 case TRANSACT2_QFSINFO:
7976 START_PROFILE(Trans2_qfsinfo);
7977 call_trans2qfsinfo(conn, req,
7978 &state->param, state->total_param,
7979 &state->data, state->total_data,
7980 state->max_data_return);
7981 END_PROFILE(Trans2_qfsinfo);
7985 case TRANSACT2_SETFSINFO:
7987 START_PROFILE(Trans2_setfsinfo);
7988 call_trans2setfsinfo(conn, req,
7989 &state->param, state->total_param,
7990 &state->data, state->total_data,
7991 state->max_data_return);
7992 END_PROFILE(Trans2_setfsinfo);
7996 case TRANSACT2_QPATHINFO:
7997 case TRANSACT2_QFILEINFO:
7999 START_PROFILE(Trans2_qpathinfo);
8000 call_trans2qfilepathinfo(conn, req, state->call,
8001 &state->param, state->total_param,
8002 &state->data, state->total_data,
8003 state->max_data_return);
8004 END_PROFILE(Trans2_qpathinfo);
8008 case TRANSACT2_SETPATHINFO:
8009 case TRANSACT2_SETFILEINFO:
8011 START_PROFILE(Trans2_setpathinfo);
8012 call_trans2setfilepathinfo(conn, req, state->call,
8013 &state->param, state->total_param,
8014 &state->data, state->total_data,
8015 state->max_data_return);
8016 END_PROFILE(Trans2_setpathinfo);
8020 case TRANSACT2_FINDNOTIFYFIRST:
8022 START_PROFILE(Trans2_findnotifyfirst);
8023 call_trans2findnotifyfirst(conn, req,
8024 &state->param, state->total_param,
8025 &state->data, state->total_data,
8026 state->max_data_return);
8027 END_PROFILE(Trans2_findnotifyfirst);
8031 case TRANSACT2_FINDNOTIFYNEXT:
8033 START_PROFILE(Trans2_findnotifynext);
8034 call_trans2findnotifynext(conn, req,
8035 &state->param, state->total_param,
8036 &state->data, state->total_data,
8037 state->max_data_return);
8038 END_PROFILE(Trans2_findnotifynext);
8042 case TRANSACT2_MKDIR:
8044 START_PROFILE(Trans2_mkdir);
8045 call_trans2mkdir(conn, req,
8046 &state->param, state->total_param,
8047 &state->data, state->total_data,
8048 state->max_data_return);
8049 END_PROFILE(Trans2_mkdir);
8053 case TRANSACT2_GET_DFS_REFERRAL:
8055 START_PROFILE(Trans2_get_dfs_referral);
8056 call_trans2getdfsreferral(conn, req,
8057 &state->param, state->total_param,
8058 &state->data, state->total_data,
8059 state->max_data_return);
8060 END_PROFILE(Trans2_get_dfs_referral);
8064 case TRANSACT2_IOCTL:
8066 START_PROFILE(Trans2_ioctl);
8067 call_trans2ioctl(conn, req,
8068 &state->param, state->total_param,
8069 &state->data, state->total_data,
8070 state->max_data_return);
8071 END_PROFILE(Trans2_ioctl);
8076 /* Error in request */
8077 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8078 reply_doserror(req, ERRSRV,ERRerror);
8082 /****************************************************************************
8083 Reply to a SMBtrans2.
8084 ****************************************************************************/
8086 void reply_trans2(struct smb_request *req)
8088 connection_struct *conn = req->conn;
8093 unsigned int tran_call;
8094 struct trans_state *state;
8097 START_PROFILE(SMBtrans2);
8099 if (req->wct < 14) {
8100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8101 END_PROFILE(SMBtrans2);
8105 dsoff = SVAL(req->vwv+12, 0);
8106 dscnt = SVAL(req->vwv+11, 0);
8107 psoff = SVAL(req->vwv+10, 0);
8108 pscnt = SVAL(req->vwv+9, 0);
8109 tran_call = SVAL(req->vwv+14, 0);
8111 result = allow_new_trans(conn->pending_trans, req->mid);
8112 if (!NT_STATUS_IS_OK(result)) {
8113 DEBUG(2, ("Got invalid trans2 request: %s\n",
8114 nt_errstr(result)));
8115 reply_nterror(req, result);
8116 END_PROFILE(SMBtrans2);
8121 switch (tran_call) {
8122 /* List the allowed trans2 calls on IPC$ */
8123 case TRANSACT2_OPEN:
8124 case TRANSACT2_GET_DFS_REFERRAL:
8125 case TRANSACT2_QFILEINFO:
8126 case TRANSACT2_QFSINFO:
8127 case TRANSACT2_SETFSINFO:
8130 reply_doserror(req, ERRSRV, ERRaccess);
8131 END_PROFILE(SMBtrans2);
8136 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8137 DEBUG(0, ("talloc failed\n"));
8138 reply_nterror(req, NT_STATUS_NO_MEMORY);
8139 END_PROFILE(SMBtrans2);
8143 state->cmd = SMBtrans2;
8145 state->mid = req->mid;
8146 state->vuid = req->vuid;
8147 state->setup_count = SVAL(req->vwv+13, 0);
8148 state->setup = NULL;
8149 state->total_param = SVAL(req->vwv+0, 0);
8150 state->param = NULL;
8151 state->total_data = SVAL(req->vwv+1, 0);
8153 state->max_param_return = SVAL(req->vwv+2, 0);
8154 state->max_data_return = SVAL(req->vwv+3, 0);
8155 state->max_setup_return = SVAL(req->vwv+4, 0);
8156 state->close_on_completion = BITSETW(req->vwv+5, 0);
8157 state->one_way = BITSETW(req->vwv+5, 1);
8159 state->call = tran_call;
8161 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8162 is so as a sanity check */
8163 if (state->setup_count != 1) {
8165 * Need to have rc=0 for ioctl to get job id for OS/2.
8166 * Network printing will fail if function is not successful.
8167 * Similar function in reply.c will be used if protocol
8168 * is LANMAN1.0 instead of LM1.2X002.
8169 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8170 * outbuf doesn't have to be set(only job id is used).
8172 if ( (state->setup_count == 4)
8173 && (tran_call == TRANSACT2_IOCTL)
8174 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8175 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8176 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8178 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8179 DEBUG(2,("Transaction is %d\n",tran_call));
8181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8182 END_PROFILE(SMBtrans2);
8187 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8190 if (state->total_data) {
8192 if (trans_oob(state->total_data, 0, dscnt)
8193 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8197 /* Can't use talloc here, the core routines do realloc on the
8198 * params and data. */
8199 state->data = (char *)SMB_MALLOC(state->total_data);
8200 if (state->data == NULL) {
8201 DEBUG(0,("reply_trans2: data malloc fail for %u "
8202 "bytes !\n", (unsigned int)state->total_data));
8204 reply_nterror(req, NT_STATUS_NO_MEMORY);
8205 END_PROFILE(SMBtrans2);
8209 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8212 if (state->total_param) {
8214 if (trans_oob(state->total_param, 0, pscnt)
8215 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8219 /* Can't use talloc here, the core routines do realloc on the
8220 * params and data. */
8221 state->param = (char *)SMB_MALLOC(state->total_param);
8222 if (state->param == NULL) {
8223 DEBUG(0,("reply_trans: param malloc fail for %u "
8224 "bytes !\n", (unsigned int)state->total_param));
8225 SAFE_FREE(state->data);
8227 reply_nterror(req, NT_STATUS_NO_MEMORY);
8228 END_PROFILE(SMBtrans2);
8232 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8235 state->received_data = dscnt;
8236 state->received_param = pscnt;
8238 if ((state->received_param == state->total_param) &&
8239 (state->received_data == state->total_data)) {
8241 handle_trans2(conn, req, state);
8243 SAFE_FREE(state->data);
8244 SAFE_FREE(state->param);
8246 END_PROFILE(SMBtrans2);
8250 DLIST_ADD(conn->pending_trans, state);
8252 /* We need to send an interim response then receive the rest
8253 of the parameter/data bytes */
8254 reply_outbuf(req, 0, 0);
8255 show_msg((char *)req->outbuf);
8256 END_PROFILE(SMBtrans2);
8261 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8262 SAFE_FREE(state->data);
8263 SAFE_FREE(state->param);
8265 END_PROFILE(SMBtrans2);
8266 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8270 /****************************************************************************
8271 Reply to a SMBtranss2
8272 ****************************************************************************/
8274 void reply_transs2(struct smb_request *req)
8276 connection_struct *conn = req->conn;
8277 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8278 struct trans_state *state;
8280 START_PROFILE(SMBtranss2);
8282 show_msg((char *)req->inbuf);
8285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8286 END_PROFILE(SMBtranss2);
8290 for (state = conn->pending_trans; state != NULL;
8291 state = state->next) {
8292 if (state->mid == req->mid) {
8297 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8298 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8299 END_PROFILE(SMBtranss2);
8303 /* Revise state->total_param and state->total_data in case they have
8304 changed downwards */
8306 if (SVAL(req->vwv+0, 0) < state->total_param)
8307 state->total_param = SVAL(req->vwv+0, 0);
8308 if (SVAL(req->vwv+1, 0) < state->total_data)
8309 state->total_data = SVAL(req->vwv+1, 0);
8311 pcnt = SVAL(req->vwv+2, 0);
8312 poff = SVAL(req->vwv+3, 0);
8313 pdisp = SVAL(req->vwv+4, 0);
8315 dcnt = SVAL(req->vwv+5, 0);
8316 doff = SVAL(req->vwv+6, 0);
8317 ddisp = SVAL(req->vwv+7, 0);
8319 state->received_param += pcnt;
8320 state->received_data += dcnt;
8322 if ((state->received_data > state->total_data) ||
8323 (state->received_param > state->total_param))
8327 if (trans_oob(state->total_param, pdisp, pcnt)
8328 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8331 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8335 if (trans_oob(state->total_data, ddisp, dcnt)
8336 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8339 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8342 if ((state->received_param < state->total_param) ||
8343 (state->received_data < state->total_data)) {
8344 END_PROFILE(SMBtranss2);
8348 handle_trans2(conn, req, state);
8350 DLIST_REMOVE(conn->pending_trans, state);
8351 SAFE_FREE(state->data);
8352 SAFE_FREE(state->param);
8355 END_PROFILE(SMBtranss2);
8360 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8361 DLIST_REMOVE(conn->pending_trans, state);
8362 SAFE_FREE(state->data);
8363 SAFE_FREE(state->param);
8365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8366 END_PROFILE(SMBtranss2);