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,
1032 if (!NT_STATUS_IS_OK(status)) {
1033 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1034 reply_botherror(req,
1035 NT_STATUS_PATH_NOT_COVERED,
1036 ERRSRV, ERRbadpath);
1039 reply_nterror(req, status);
1043 if (open_ofun == 0) {
1044 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1048 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1049 &access_mask, &share_mode,
1050 &create_disposition,
1052 reply_doserror(req, ERRDOS, ERRbadaccess);
1056 /* Any data in this call is an EA list. */
1057 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1058 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1062 if (total_data != 4) {
1063 if (total_data < 10) {
1064 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1068 if (IVAL(pdata,0) > total_data) {
1069 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1070 IVAL(pdata,0), (unsigned int)total_data));
1071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1075 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1081 } else if (IVAL(pdata,0) != 4) {
1082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1086 status = SMB_VFS_CREATE_FILE(
1089 0, /* root_dir_fid */
1090 smb_fname, /* fname */
1091 access_mask, /* access_mask */
1092 share_mode, /* share_access */
1093 create_disposition, /* create_disposition*/
1094 create_options, /* create_options */
1095 open_attr, /* file_attributes */
1096 oplock_request, /* oplock_request */
1097 open_size, /* allocation_size */
1099 ea_list, /* ea_list */
1101 &smb_action); /* psbuf */
1103 if (!NT_STATUS_IS_OK(status)) {
1104 if (open_was_deferred(req->mid)) {
1105 /* We have re-scheduled this call. */
1108 reply_openerror(req, status);
1112 size = get_file_size_stat(&smb_fname->st);
1113 fattr = dos_mode(conn, smb_fname);
1114 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1115 inode = smb_fname->st.st_ex_ino;
1117 close_file(req, fsp, ERROR_CLOSE);
1118 reply_doserror(req, ERRDOS,ERRnoaccess);
1122 /* Realloc the size of parameters and data we will return */
1123 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1124 if(*pparams == NULL ) {
1125 reply_nterror(req, NT_STATUS_NO_MEMORY);
1130 SSVAL(params,0,fsp->fnum);
1131 SSVAL(params,2,fattr);
1132 srv_put_dos_date2(params,4, mtime);
1133 SIVAL(params,8, (uint32)size);
1134 SSVAL(params,12,deny_mode);
1135 SSVAL(params,14,0); /* open_type - file or directory. */
1136 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1138 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1139 smb_action |= EXTENDED_OPLOCK_GRANTED;
1142 SSVAL(params,18,smb_action);
1145 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1147 SIVAL(params,20,inode);
1148 SSVAL(params,24,0); /* Padding. */
1150 uint32 ea_size = estimate_ea_size(conn, fsp,
1151 fsp->fsp_name->base_name);
1152 SIVAL(params, 26, ea_size);
1154 SIVAL(params, 26, 0);
1157 /* Send the required number of replies */
1158 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1160 TALLOC_FREE(smb_fname);
1163 /*********************************************************
1164 Routine to check if a given string matches exactly.
1165 as a special case a mask of "." does NOT match. That
1166 is required for correct wildcard semantics
1167 Case can be significant or not.
1168 **********************************************************/
1170 static bool exact_match(connection_struct *conn,
1174 if (mask[0] == '.' && mask[1] == 0)
1176 if (dptr_has_wild(conn->dirptr)) {
1179 if (conn->case_sensitive)
1180 return strcmp(str,mask)==0;
1182 return StrCaseCmp(str,mask) == 0;
1185 /****************************************************************************
1186 Return the filetype for UNIX extensions.
1187 ****************************************************************************/
1189 static uint32 unix_filetype(mode_t mode)
1192 return UNIX_TYPE_FILE;
1193 else if(S_ISDIR(mode))
1194 return UNIX_TYPE_DIR;
1196 else if(S_ISLNK(mode))
1197 return UNIX_TYPE_SYMLINK;
1200 else if(S_ISCHR(mode))
1201 return UNIX_TYPE_CHARDEV;
1204 else if(S_ISBLK(mode))
1205 return UNIX_TYPE_BLKDEV;
1208 else if(S_ISFIFO(mode))
1209 return UNIX_TYPE_FIFO;
1212 else if(S_ISSOCK(mode))
1213 return UNIX_TYPE_SOCKET;
1216 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1217 return UNIX_TYPE_UNKNOWN;
1220 /****************************************************************************
1221 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1222 ****************************************************************************/
1224 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1226 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1227 const SMB_STRUCT_STAT *psbuf,
1229 enum perm_type ptype,
1234 if (perms == SMB_MODE_NO_CHANGE) {
1235 if (!VALID_STAT(*psbuf)) {
1236 return NT_STATUS_INVALID_PARAMETER;
1238 *ret_perms = psbuf->st_ex_mode;
1239 return NT_STATUS_OK;
1243 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1244 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1245 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1246 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1247 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1248 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1249 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1250 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1251 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1253 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1256 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1259 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1264 /* Apply mode mask */
1265 ret &= lp_create_mask(SNUM(conn));
1266 /* Add in force bits */
1267 ret |= lp_force_create_mode(SNUM(conn));
1270 ret &= lp_dir_mask(SNUM(conn));
1271 /* Add in force bits */
1272 ret |= lp_force_dir_mode(SNUM(conn));
1274 case PERM_EXISTING_FILE:
1275 /* Apply mode mask */
1276 ret &= lp_security_mask(SNUM(conn));
1277 /* Add in force bits */
1278 ret |= lp_force_security_mode(SNUM(conn));
1280 case PERM_EXISTING_DIR:
1281 /* Apply mode mask */
1282 ret &= lp_dir_security_mask(SNUM(conn));
1283 /* Add in force bits */
1284 ret |= lp_force_dir_security_mode(SNUM(conn));
1289 return NT_STATUS_OK;
1292 /****************************************************************************
1293 Needed to show the msdfs symlinks as directories. Modifies psbuf
1294 to be a directory if it's a msdfs link.
1295 ****************************************************************************/
1297 static bool check_msdfs_link(connection_struct *conn,
1298 const char *pathname,
1299 SMB_STRUCT_STAT *psbuf)
1301 int saved_errno = errno;
1302 if(lp_host_msdfs() &&
1303 lp_msdfs_root(SNUM(conn)) &&
1304 is_msdfs_link(conn, pathname, psbuf)) {
1306 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1309 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1310 errno = saved_errno;
1313 errno = saved_errno;
1318 /****************************************************************************
1319 Get a level dependent lanman2 dir entry.
1320 ****************************************************************************/
1322 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1323 connection_struct *conn,
1325 const char *path_mask,
1328 int requires_resume_key,
1334 int space_remaining,
1336 bool *got_exact_match,
1337 int *last_entry_off,
1338 struct ea_list *name_list)
1342 SMB_STRUCT_STAT sbuf;
1343 const char *mask = NULL;
1344 char *pathreal = NULL;
1346 char *p, *q, *pdata = *ppdata;
1350 SMB_OFF_T file_size = 0;
1351 uint64_t allocation_size = 0;
1353 struct timespec mdate_ts, adate_ts, create_date_ts;
1354 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1356 char *last_entry_ptr;
1358 uint32 nt_extmode; /* Used for NT connections instead of mode */
1359 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1360 bool check_mangled_names = lp_manglednames(conn->params);
1361 char mangled_name[13]; /* mangled 8.3 name. */
1363 *out_of_space = False;
1364 *got_exact_match = False;
1366 ZERO_STRUCT(mdate_ts);
1367 ZERO_STRUCT(adate_ts);
1368 ZERO_STRUCT(create_date_ts);
1370 if (!conn->dirptr) {
1374 p = strrchr_m(path_mask,'/');
1377 mask = talloc_strdup(ctx,"*.*");
1387 bool ms_dfs_link = False;
1389 /* Needed if we run out of space */
1390 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1391 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1394 * Due to bugs in NT client redirectors we are not using
1395 * resume keys any more - set them to zero.
1396 * Check out the related comments in findfirst/findnext.
1402 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1403 (long)conn->dirptr,curr_dirpos));
1410 * fname may get mangled, dname is never mangled.
1411 * Whenever we're accessing the filesystem we use
1412 * pathreal which is composed from dname.
1418 /* Mangle fname if it's an illegal name. */
1419 if (mangle_must_mangle(dname,conn->params)) {
1420 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1422 continue; /* Error - couldn't mangle. */
1424 fname = talloc_strdup(ctx, mangled_name);
1430 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1431 got_match = mask_match(fname, mask, conn->case_sensitive);
1434 if(!got_match && check_mangled_names &&
1435 !mangle_is_8_3(fname, False, conn->params)) {
1437 * It turns out that NT matches wildcards against
1438 * both long *and* short names. This may explain some
1439 * of the wildcard wierdness from old DOS clients
1440 * that some people have been seeing.... JRA.
1442 /* Force the mangling into 8.3. */
1443 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1445 continue; /* Error - couldn't mangle. */
1448 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1449 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1454 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1455 struct smb_filename *smb_fname = NULL;
1458 if (dont_descend && !isdots) {
1465 pathreal = talloc_asprintf(ctx,
1470 pathreal = talloc_asprintf(ctx,
1481 /* A dirent from dptr_ReadDirName isn't a stream. */
1482 status = create_synthetic_smb_fname(ctx, pathreal,
1485 if (!NT_STATUS_IS_OK(status)) {
1490 if (INFO_LEVEL_IS_UNIX(info_level)) {
1491 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
1492 DEBUG(5,("get_lanman2_dir_entry: "
1493 "Couldn't lstat [%s] (%s)\n",
1494 smb_fname_str_dbg(smb_fname),
1496 TALLOC_FREE(smb_fname);
1497 TALLOC_FREE(pathreal);
1501 } else if (!VALID_STAT(smb_fname->st) &&
1502 SMB_VFS_STAT(conn, smb_fname) != 0) {
1503 /* Needed to show the msdfs symlinks as
1507 check_msdfs_link(conn,
1508 smb_fname->base_name,
1511 DEBUG(5,("get_lanman2_dir_entry: "
1512 "Couldn't stat [%s] (%s)\n",
1513 smb_fname_str_dbg(smb_fname),
1515 TALLOC_FREE(smb_fname);
1516 TALLOC_FREE(pathreal);
1523 mode = dos_mode_msdfs(conn, smb_fname);
1525 mode = dos_mode(conn, smb_fname);
1528 if (!dir_check_ftype(conn,mode,dirtype)) {
1529 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1530 TALLOC_FREE(smb_fname);
1531 TALLOC_FREE(pathreal);
1536 if (!(mode & aDIR)) {
1537 file_size = get_file_size_stat(&smb_fname->st);
1540 SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1542 if (ask_sharemode) {
1543 struct timespec write_time_ts;
1544 struct file_id fileid;
1546 ZERO_STRUCT(write_time_ts);
1547 fileid = vfs_file_id_from_sbuf(conn,
1549 get_file_infos(fileid, NULL, &write_time_ts);
1550 if (!null_timespec(write_time_ts)) {
1551 update_stat_ex_mtime(&smb_fname->st,
1556 mdate_ts = smb_fname->st.st_ex_mtime;
1557 adate_ts = smb_fname->st.st_ex_atime;
1558 create_date_ts = smb_fname->st.st_ex_btime;
1560 if (lp_dos_filetime_resolution(SNUM(conn))) {
1561 dos_filetime_timespec(&create_date_ts);
1562 dos_filetime_timespec(&mdate_ts);
1563 dos_filetime_timespec(&adate_ts);
1566 create_date = convert_timespec_to_time_t(create_date_ts);
1567 mdate = convert_timespec_to_time_t(mdate_ts);
1568 adate = convert_timespec_to_time_t(adate_ts);
1570 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1571 smb_fname_str_dbg(smb_fname), fname));
1575 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1576 sbuf = smb_fname->st;
1578 TALLOC_FREE(smb_fname);
1588 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1590 switch (info_level) {
1591 case SMB_FIND_INFO_STANDARD:
1592 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1593 if(requires_resume_key) {
1597 srv_put_dos_date2(p,0,create_date);
1598 srv_put_dos_date2(p,4,adate);
1599 srv_put_dos_date2(p,8,mdate);
1600 SIVAL(p,12,(uint32)file_size);
1601 SIVAL(p,16,(uint32)allocation_size);
1605 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1606 p += ucs2_align(base_data, p, 0);
1608 len = srvstr_push(base_data, flags2, p,
1609 fname, PTR_DIFF(end_data, p),
1611 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1613 SCVAL(nameptr, -1, len - 2);
1615 SCVAL(nameptr, -1, 0);
1619 SCVAL(nameptr, -1, len - 1);
1621 SCVAL(nameptr, -1, 0);
1627 case SMB_FIND_EA_SIZE:
1628 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1629 if(requires_resume_key) {
1633 srv_put_dos_date2(p,0,create_date);
1634 srv_put_dos_date2(p,4,adate);
1635 srv_put_dos_date2(p,8,mdate);
1636 SIVAL(p,12,(uint32)file_size);
1637 SIVAL(p,16,(uint32)allocation_size);
1640 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1641 SIVAL(p,22,ea_size); /* Extended attributes */
1645 len = srvstr_push(base_data, flags2,
1646 p, fname, PTR_DIFF(end_data, p),
1647 STR_TERMINATE | STR_NOALIGN);
1648 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1661 SCVAL(nameptr,0,len);
1663 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1666 case SMB_FIND_EA_LIST:
1668 struct ea_list *file_list = NULL;
1671 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1675 if(requires_resume_key) {
1679 srv_put_dos_date2(p,0,create_date);
1680 srv_put_dos_date2(p,4,adate);
1681 srv_put_dos_date2(p,8,mdate);
1682 SIVAL(p,12,(uint32)file_size);
1683 SIVAL(p,16,(uint32)allocation_size);
1685 p += 22; /* p now points to the EA area. */
1687 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1688 name_list = ea_list_union(name_list, file_list, &ea_len);
1690 /* We need to determine if this entry will fit in the space available. */
1691 /* Max string size is 255 bytes. */
1692 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1693 /* Move the dirptr back to prev_dirpos */
1694 dptr_SeekDir(conn->dirptr, prev_dirpos);
1695 *out_of_space = True;
1696 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1697 return False; /* Not finished - just out of space */
1700 /* Push the ea_data followed by the name. */
1701 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1703 len = srvstr_push(base_data, flags2,
1704 p + 1, fname, PTR_DIFF(end_data, p+1),
1705 STR_TERMINATE | STR_NOALIGN);
1706 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1719 SCVAL(nameptr,0,len);
1721 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1725 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1726 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1727 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1729 SIVAL(p,0,reskey); p += 4;
1730 put_long_date_timespec(p,create_date_ts); p += 8;
1731 put_long_date_timespec(p,adate_ts); p += 8;
1732 put_long_date_timespec(p,mdate_ts); p += 8;
1733 put_long_date_timespec(p,mdate_ts); p += 8;
1734 SOFF_T(p,0,file_size); p += 8;
1735 SOFF_T(p,0,allocation_size); p += 8;
1736 SIVAL(p,0,nt_extmode); p += 4;
1737 q = p; p += 4; /* q is placeholder for name length. */
1739 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1740 SIVAL(p,0,ea_size); /* Extended attributes */
1743 /* Clear the short name buffer. This is
1744 * IMPORTANT as not doing so will trigger
1745 * a Win2k client bug. JRA.
1747 if (!was_8_3 && check_mangled_names) {
1748 if (!name_to_8_3(fname,mangled_name,True,
1750 /* Error - mangle failed ! */
1751 memset(mangled_name,'\0',12);
1753 mangled_name[12] = 0;
1754 len = srvstr_push(base_data, flags2,
1755 p+2, mangled_name, 24,
1756 STR_UPPER|STR_UNICODE);
1758 memset(p + 2 + len,'\0',24 - len);
1765 len = srvstr_push(base_data, flags2, p,
1766 fname, PTR_DIFF(end_data, p),
1767 STR_TERMINATE_ASCII);
1770 SIVAL(p,0,0); /* Ensure any padding is null. */
1771 len = PTR_DIFF(p, pdata);
1772 len = (len + 3) & ~3;
1777 case SMB_FIND_FILE_DIRECTORY_INFO:
1778 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1780 SIVAL(p,0,reskey); p += 4;
1781 put_long_date_timespec(p,create_date_ts); p += 8;
1782 put_long_date_timespec(p,adate_ts); p += 8;
1783 put_long_date_timespec(p,mdate_ts); p += 8;
1784 put_long_date_timespec(p,mdate_ts); p += 8;
1785 SOFF_T(p,0,file_size); p += 8;
1786 SOFF_T(p,0,allocation_size); p += 8;
1787 SIVAL(p,0,nt_extmode); p += 4;
1788 len = srvstr_push(base_data, flags2,
1789 p + 4, fname, PTR_DIFF(end_data, p+4),
1790 STR_TERMINATE_ASCII);
1793 SIVAL(p,0,0); /* Ensure any padding is null. */
1794 len = PTR_DIFF(p, pdata);
1795 len = (len + 3) & ~3;
1800 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1801 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1803 SIVAL(p,0,reskey); p += 4;
1804 put_long_date_timespec(p,create_date_ts); p += 8;
1805 put_long_date_timespec(p,adate_ts); p += 8;
1806 put_long_date_timespec(p,mdate_ts); p += 8;
1807 put_long_date_timespec(p,mdate_ts); p += 8;
1808 SOFF_T(p,0,file_size); p += 8;
1809 SOFF_T(p,0,allocation_size); p += 8;
1810 SIVAL(p,0,nt_extmode); p += 4;
1811 q = p; p += 4; /* q is placeholder for name length. */
1813 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1814 SIVAL(p,0,ea_size); /* Extended attributes */
1817 len = srvstr_push(base_data, flags2, p,
1818 fname, PTR_DIFF(end_data, p),
1819 STR_TERMINATE_ASCII);
1823 SIVAL(p,0,0); /* Ensure any padding is null. */
1824 len = PTR_DIFF(p, pdata);
1825 len = (len + 3) & ~3;
1830 case SMB_FIND_FILE_NAMES_INFO:
1831 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1833 SIVAL(p,0,reskey); p += 4;
1835 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1836 acl on a dir (tridge) */
1837 len = srvstr_push(base_data, flags2, p,
1838 fname, PTR_DIFF(end_data, p),
1839 STR_TERMINATE_ASCII);
1842 SIVAL(p,0,0); /* Ensure any padding is null. */
1843 len = PTR_DIFF(p, pdata);
1844 len = (len + 3) & ~3;
1849 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1850 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1852 SIVAL(p,0,reskey); p += 4;
1853 put_long_date_timespec(p,create_date_ts); p += 8;
1854 put_long_date_timespec(p,adate_ts); p += 8;
1855 put_long_date_timespec(p,mdate_ts); p += 8;
1856 put_long_date_timespec(p,mdate_ts); p += 8;
1857 SOFF_T(p,0,file_size); p += 8;
1858 SOFF_T(p,0,allocation_size); p += 8;
1859 SIVAL(p,0,nt_extmode); p += 4;
1860 q = p; p += 4; /* q is placeholder for name length. */
1862 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1863 SIVAL(p,0,ea_size); /* Extended attributes */
1866 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1867 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1868 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1869 len = srvstr_push(base_data, flags2, p,
1870 fname, PTR_DIFF(end_data, p),
1871 STR_TERMINATE_ASCII);
1874 SIVAL(p,0,0); /* Ensure any padding is null. */
1875 len = PTR_DIFF(p, pdata);
1876 len = (len + 3) & ~3;
1881 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1882 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1883 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1885 SIVAL(p,0,reskey); p += 4;
1886 put_long_date_timespec(p,create_date_ts); p += 8;
1887 put_long_date_timespec(p,adate_ts); p += 8;
1888 put_long_date_timespec(p,mdate_ts); p += 8;
1889 put_long_date_timespec(p,mdate_ts); p += 8;
1890 SOFF_T(p,0,file_size); p += 8;
1891 SOFF_T(p,0,allocation_size); p += 8;
1892 SIVAL(p,0,nt_extmode); p += 4;
1893 q = p; p += 4; /* q is placeholder for name length */
1895 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1896 SIVAL(p,0,ea_size); /* Extended attributes */
1899 /* Clear the short name buffer. This is
1900 * IMPORTANT as not doing so will trigger
1901 * a Win2k client bug. JRA.
1903 if (!was_8_3 && check_mangled_names) {
1904 if (!name_to_8_3(fname,mangled_name,True,
1906 /* Error - mangle failed ! */
1907 memset(mangled_name,'\0',12);
1909 mangled_name[12] = 0;
1910 len = srvstr_push(base_data, flags2,
1911 p+2, mangled_name, 24,
1912 STR_UPPER|STR_UNICODE);
1915 memset(p + 2 + len,'\0',24 - len);
1922 SSVAL(p,0,0); p += 2; /* Reserved ? */
1923 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1924 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1925 len = srvstr_push(base_data, flags2, p,
1926 fname, PTR_DIFF(end_data, p),
1927 STR_TERMINATE_ASCII);
1930 SIVAL(p,0,0); /* Ensure any padding is null. */
1931 len = PTR_DIFF(p, pdata);
1932 len = (len + 3) & ~3;
1937 /* CIFS UNIX Extension. */
1939 case SMB_FIND_FILE_UNIX:
1940 case SMB_FIND_FILE_UNIX_INFO2:
1942 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1944 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1946 if (info_level == SMB_FIND_FILE_UNIX) {
1947 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1948 p = store_file_unix_basic(conn, p,
1950 len = srvstr_push(base_data, flags2, p,
1951 fname, PTR_DIFF(end_data, p),
1954 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1955 p = store_file_unix_basic_info2(conn, p,
1959 len = srvstr_push(base_data, flags2, p, fname,
1960 PTR_DIFF(end_data, p), 0);
1961 SIVAL(nameptr, 0, len);
1965 SIVAL(p,0,0); /* Ensure any padding is null. */
1967 len = PTR_DIFF(p, pdata);
1968 len = (len + 3) & ~3;
1969 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1971 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1981 if (PTR_DIFF(p,pdata) > space_remaining) {
1982 /* Move the dirptr back to prev_dirpos */
1983 dptr_SeekDir(conn->dirptr, prev_dirpos);
1984 *out_of_space = True;
1985 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1986 return False; /* Not finished - just out of space */
1989 /* Setup the last entry pointer, as an offset from base_data */
1990 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1991 /* Advance the data pointer to the next slot */
1997 /****************************************************************************
1998 Reply to a TRANS2_FINDFIRST.
1999 ****************************************************************************/
2001 static void call_trans2findfirst(connection_struct *conn,
2002 struct smb_request *req,
2003 char **pparams, int total_params,
2004 char **ppdata, int total_data,
2005 unsigned int max_data_bytes)
2007 /* We must be careful here that we don't return more than the
2008 allowed number of data bytes. If this means returning fewer than
2009 maxentries then so be it. We assume that the redirector has
2010 enough room for the fixed number of parameter bytes it has
2012 struct smb_filename *smb_dname = NULL;
2013 char *params = *pparams;
2014 char *pdata = *ppdata;
2018 uint16 findfirst_flags;
2019 bool close_after_first;
2021 bool requires_resume_key;
2023 char *directory = NULL;
2026 int last_entry_off=0;
2030 bool finished = False;
2031 bool dont_descend = False;
2032 bool out_of_space = False;
2033 int space_remaining;
2034 bool mask_contains_wcard = False;
2035 struct ea_list *ea_list = NULL;
2036 NTSTATUS ntstatus = NT_STATUS_OK;
2037 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2038 TALLOC_CTX *ctx = talloc_tos();
2040 if (total_params < 13) {
2041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2045 dirtype = SVAL(params,0);
2046 maxentries = SVAL(params,2);
2047 findfirst_flags = SVAL(params,4);
2048 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2049 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2050 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2051 info_level = SVAL(params,6);
2053 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2054 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2055 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2056 info_level, max_data_bytes));
2059 /* W2K3 seems to treat zero as 1. */
2063 switch (info_level) {
2064 case SMB_FIND_INFO_STANDARD:
2065 case SMB_FIND_EA_SIZE:
2066 case SMB_FIND_EA_LIST:
2067 case SMB_FIND_FILE_DIRECTORY_INFO:
2068 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2069 case SMB_FIND_FILE_NAMES_INFO:
2070 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2071 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2072 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2074 case SMB_FIND_FILE_UNIX:
2075 case SMB_FIND_FILE_UNIX_INFO2:
2076 /* Always use filesystem for UNIX mtime query. */
2077 ask_sharemode = false;
2078 if (!lp_unix_extensions()) {
2079 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2084 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2088 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2089 params+12, total_params - 12,
2090 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2091 if (!NT_STATUS_IS_OK(ntstatus)) {
2092 reply_nterror(req, ntstatus);
2096 ntstatus = resolve_dfspath_wcard(ctx, conn,
2097 req->flags2 & FLAGS2_DFS_PATHNAMES,
2100 &mask_contains_wcard);
2101 if (!NT_STATUS_IS_OK(ntstatus)) {
2102 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2103 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2104 ERRSRV, ERRbadpath);
2107 reply_nterror(req, ntstatus);
2111 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2112 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2113 if (!NT_STATUS_IS_OK(ntstatus)) {
2114 reply_nterror(req, ntstatus);
2118 mask = smb_dname->original_lcomp;
2120 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2121 TALLOC_FREE(smb_dname);
2122 if (!NT_STATUS_IS_OK(ntstatus)) {
2123 reply_nterror(req, ntstatus);
2127 ntstatus = check_name(conn, directory);
2128 if (!NT_STATUS_IS_OK(ntstatus)) {
2129 reply_nterror(req, ntstatus);
2133 p = strrchr_m(directory,'/');
2135 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2136 if((directory[0] == '.') && (directory[1] == '\0')) {
2137 mask = talloc_strdup(ctx,"*");
2139 reply_nterror(req, NT_STATUS_NO_MEMORY);
2142 mask_contains_wcard = True;
2144 directory = talloc_strdup(talloc_tos(), "./");
2146 reply_nterror(req, NT_STATUS_NO_MEMORY);
2153 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2155 if (info_level == SMB_FIND_EA_LIST) {
2158 if (total_data < 4) {
2159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2163 ea_size = IVAL(pdata,0);
2164 if (ea_size != total_data) {
2165 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2166 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2171 if (!lp_ea_support(SNUM(conn))) {
2172 reply_doserror(req, ERRDOS, ERReasnotsupported);
2176 /* Pull out the list of names. */
2177 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2184 *ppdata = (char *)SMB_REALLOC(
2185 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2186 if(*ppdata == NULL ) {
2187 reply_nterror(req, NT_STATUS_NO_MEMORY);
2191 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2193 /* Realloc the params space */
2194 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2195 if (*pparams == NULL) {
2196 reply_nterror(req, NT_STATUS_NO_MEMORY);
2201 /* Save the wildcard match and attribs we are using on this directory -
2202 needed as lanman2 assumes these are being saved between calls */
2204 ntstatus = dptr_create(conn,
2210 mask_contains_wcard,
2214 if (!NT_STATUS_IS_OK(ntstatus)) {
2215 reply_nterror(req, ntstatus);
2219 dptr_num = dptr_dnum(conn->dirptr);
2220 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2222 /* Initialize per TRANS2_FIND_FIRST operation data */
2223 dptr_init_search_op(conn->dirptr);
2225 /* We don't need to check for VOL here as this is returned by
2226 a different TRANS2 call. */
2228 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2229 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2230 dont_descend = True;
2233 space_remaining = max_data_bytes;
2234 out_of_space = False;
2236 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2237 bool got_exact_match = False;
2239 /* this is a heuristic to avoid seeking the dirptr except when
2240 absolutely necessary. It allows for a filename of about 40 chars */
2241 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2242 out_of_space = True;
2245 finished = !get_lanman2_dir_entry(ctx,
2248 mask,dirtype,info_level,
2249 requires_resume_key,dont_descend,
2252 space_remaining, &out_of_space,
2254 &last_entry_off, ea_list);
2257 if (finished && out_of_space)
2260 if (!finished && !out_of_space)
2264 * As an optimisation if we know we aren't looking
2265 * for a wildcard name (ie. the name matches the wildcard exactly)
2266 * then we can finish on any (first) match.
2267 * This speeds up large directory searches. JRA.
2273 /* Ensure space_remaining never goes -ve. */
2274 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2275 space_remaining = 0;
2276 out_of_space = true;
2278 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2282 /* Check if we can close the dirptr */
2283 if(close_after_first || (finished && close_if_end)) {
2284 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2285 dptr_close(&dptr_num);
2289 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2290 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2291 * the protocol level is less than NT1. Tested with smbclient. JRA.
2292 * This should fix the OS/2 client bug #2335.
2295 if(numentries == 0) {
2296 dptr_close(&dptr_num);
2297 if (Protocol < PROTOCOL_NT1) {
2298 reply_doserror(req, ERRDOS, ERRnofiles);
2301 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2302 ERRDOS, ERRbadfile);
2307 /* At this point pdata points to numentries directory entries. */
2309 /* Set up the return parameter block */
2310 SSVAL(params,0,dptr_num);
2311 SSVAL(params,2,numentries);
2312 SSVAL(params,4,finished);
2313 SSVAL(params,6,0); /* Never an EA error */
2314 SSVAL(params,8,last_entry_off);
2316 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2319 if ((! *directory) && dptr_path(dptr_num)) {
2320 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2322 reply_nterror(req, NT_STATUS_NO_MEMORY);
2326 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2327 smb_fn_name(req->cmd),
2328 mask, directory, dirtype, numentries ) );
2331 * Force a name mangle here to ensure that the
2332 * mask as an 8.3 name is top of the mangled cache.
2333 * The reasons for this are subtle. Don't remove
2334 * this code unless you know what you are doing
2335 * (see PR#13758). JRA.
2338 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2339 char mangled_name[13];
2340 name_to_8_3(mask, mangled_name, True, conn->params);
2346 /****************************************************************************
2347 Reply to a TRANS2_FINDNEXT.
2348 ****************************************************************************/
2350 static void call_trans2findnext(connection_struct *conn,
2351 struct smb_request *req,
2352 char **pparams, int total_params,
2353 char **ppdata, int total_data,
2354 unsigned int max_data_bytes)
2356 /* We must be careful here that we don't return more than the
2357 allowed number of data bytes. If this means returning fewer than
2358 maxentries then so be it. We assume that the redirector has
2359 enough room for the fixed number of parameter bytes it has
2361 char *params = *pparams;
2362 char *pdata = *ppdata;
2368 uint16 findnext_flags;
2369 bool close_after_request;
2371 bool requires_resume_key;
2373 bool mask_contains_wcard = False;
2374 char *resume_name = NULL;
2375 const char *mask = NULL;
2376 const char *directory = NULL;
2380 int i, last_entry_off=0;
2381 bool finished = False;
2382 bool dont_descend = False;
2383 bool out_of_space = False;
2384 int space_remaining;
2385 struct ea_list *ea_list = NULL;
2386 NTSTATUS ntstatus = NT_STATUS_OK;
2387 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2388 TALLOC_CTX *ctx = talloc_tos();
2390 if (total_params < 13) {
2391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2395 dptr_num = SVAL(params,0);
2396 maxentries = SVAL(params,2);
2397 info_level = SVAL(params,4);
2398 resume_key = IVAL(params,6);
2399 findnext_flags = SVAL(params,10);
2400 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2401 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2402 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2403 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2405 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2407 total_params - 12, STR_TERMINATE, &ntstatus,
2408 &mask_contains_wcard);
2409 if (!NT_STATUS_IS_OK(ntstatus)) {
2410 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2411 complain (it thinks we're asking for the directory above the shared
2412 path or an invalid name). Catch this as the resume name is only compared, never used in
2413 a file access. JRA. */
2414 srvstr_pull_talloc(ctx, params, req->flags2,
2415 &resume_name, params+12,
2419 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2420 reply_nterror(req, ntstatus);
2425 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2426 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2427 resume_key = %d resume name = %s continue=%d level = %d\n",
2428 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2429 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2432 /* W2K3 seems to treat zero as 1. */
2436 switch (info_level) {
2437 case SMB_FIND_INFO_STANDARD:
2438 case SMB_FIND_EA_SIZE:
2439 case SMB_FIND_EA_LIST:
2440 case SMB_FIND_FILE_DIRECTORY_INFO:
2441 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2442 case SMB_FIND_FILE_NAMES_INFO:
2443 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2444 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2445 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2447 case SMB_FIND_FILE_UNIX:
2448 case SMB_FIND_FILE_UNIX_INFO2:
2449 /* Always use filesystem for UNIX mtime query. */
2450 ask_sharemode = false;
2451 if (!lp_unix_extensions()) {
2452 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2457 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2461 if (info_level == SMB_FIND_EA_LIST) {
2464 if (total_data < 4) {
2465 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2469 ea_size = IVAL(pdata,0);
2470 if (ea_size != total_data) {
2471 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2472 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2477 if (!lp_ea_support(SNUM(conn))) {
2478 reply_doserror(req, ERRDOS, ERReasnotsupported);
2482 /* Pull out the list of names. */
2483 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2490 *ppdata = (char *)SMB_REALLOC(
2491 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2492 if(*ppdata == NULL) {
2493 reply_nterror(req, NT_STATUS_NO_MEMORY);
2498 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2500 /* Realloc the params space */
2501 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2502 if(*pparams == NULL ) {
2503 reply_nterror(req, NT_STATUS_NO_MEMORY);
2509 /* Check that the dptr is valid */
2510 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2511 reply_doserror(req, ERRDOS, ERRnofiles);
2515 string_set(&conn->dirpath,dptr_path(dptr_num));
2517 /* Get the wildcard mask from the dptr */
2518 if((p = dptr_wcard(dptr_num))== NULL) {
2519 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2520 reply_doserror(req, ERRDOS, ERRnofiles);
2525 directory = conn->dirpath;
2527 /* Get the attr mask from the dptr */
2528 dirtype = dptr_attr(dptr_num);
2530 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2531 dptr_num, mask, dirtype,
2533 dptr_TellDir(conn->dirptr)));
2535 /* Initialize per TRANS2_FIND_NEXT operation data */
2536 dptr_init_search_op(conn->dirptr);
2538 /* We don't need to check for VOL here as this is returned by
2539 a different TRANS2 call. */
2541 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2542 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2543 dont_descend = True;
2546 space_remaining = max_data_bytes;
2547 out_of_space = False;
2550 * Seek to the correct position. We no longer use the resume key but
2551 * depend on the last file name instead.
2554 if(*resume_name && !continue_bit) {
2557 long current_pos = 0;
2559 * Remember, name_to_8_3 is called by
2560 * get_lanman2_dir_entry(), so the resume name
2561 * could be mangled. Ensure we check the unmangled name.
2564 if (mangle_is_mangled(resume_name, conn->params)) {
2565 char *new_resume_name = NULL;
2566 mangle_lookup_name_from_8_3(ctx,
2570 if (new_resume_name) {
2571 resume_name = new_resume_name;
2576 * Fix for NT redirector problem triggered by resume key indexes
2577 * changing between directory scans. We now return a resume key of 0
2578 * and instead look for the filename to continue from (also given
2579 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2580 * findfirst/findnext (as is usual) then the directory pointer
2581 * should already be at the correct place.
2584 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2585 } /* end if resume_name && !continue_bit */
2587 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2588 bool got_exact_match = False;
2590 /* this is a heuristic to avoid seeking the dirptr except when
2591 absolutely necessary. It allows for a filename of about 40 chars */
2592 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2593 out_of_space = True;
2596 finished = !get_lanman2_dir_entry(ctx,
2599 mask,dirtype,info_level,
2600 requires_resume_key,dont_descend,
2603 space_remaining, &out_of_space,
2605 &last_entry_off, ea_list);
2608 if (finished && out_of_space)
2611 if (!finished && !out_of_space)
2615 * As an optimisation if we know we aren't looking
2616 * for a wildcard name (ie. the name matches the wildcard exactly)
2617 * then we can finish on any (first) match.
2618 * This speeds up large directory searches. JRA.
2624 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2627 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2628 smb_fn_name(req->cmd),
2629 mask, directory, dirtype, numentries ) );
2631 /* Check if we can close the dirptr */
2632 if(close_after_request || (finished && close_if_end)) {
2633 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2634 dptr_close(&dptr_num); /* This frees up the saved mask */
2637 /* Set up the return parameter block */
2638 SSVAL(params,0,numentries);
2639 SSVAL(params,2,finished);
2640 SSVAL(params,4,0); /* Never an EA error */
2641 SSVAL(params,6,last_entry_off);
2643 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2649 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2651 E_md4hash(lp_servicename(SNUM(conn)),objid);
2655 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2657 SMB_ASSERT(extended_info != NULL);
2659 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2660 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2661 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2662 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2663 #ifdef SAMBA_VERSION_REVISION
2664 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2666 extended_info->samba_subversion = 0;
2667 #ifdef SAMBA_VERSION_RC_RELEASE
2668 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2670 #ifdef SAMBA_VERSION_PRE_RELEASE
2671 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2674 #ifdef SAMBA_VERSION_VENDOR_PATCH
2675 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2677 extended_info->samba_gitcommitdate = 0;
2678 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2679 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2682 memset(extended_info->samba_version_string, 0,
2683 sizeof(extended_info->samba_version_string));
2685 snprintf (extended_info->samba_version_string,
2686 sizeof(extended_info->samba_version_string),
2687 "%s", samba_version_string());
2690 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2691 TALLOC_CTX *mem_ctx,
2692 uint16_t info_level,
2695 unsigned int max_data_bytes,
2699 char *pdata, *end_data;
2700 int data_len = 0, len;
2701 const char *vname = volume_label(SNUM(conn));
2702 int snum = SNUM(conn);
2703 char *fstype = lp_fstype(SNUM(conn));
2704 uint32 additional_flags = 0;
2707 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2708 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2709 "info level (0x%x) on IPC$.\n",
2710 (unsigned int)info_level));
2711 return NT_STATUS_ACCESS_DENIED;
2715 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2717 *ppdata = (char *)SMB_REALLOC(
2718 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2719 if (*ppdata == NULL) {
2720 return NT_STATUS_NO_MEMORY;
2724 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2725 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2727 switch (info_level) {
2728 case SMB_INFO_ALLOCATION:
2730 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2732 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2733 return map_nt_error_from_unix(errno);
2736 block_size = lp_block_size(snum);
2737 if (bsize < block_size) {
2738 uint64_t factor = block_size/bsize;
2743 if (bsize > block_size) {
2744 uint64_t factor = bsize/block_size;
2749 bytes_per_sector = 512;
2750 sectors_per_unit = bsize/bytes_per_sector;
2752 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2753 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2754 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2756 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2757 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2758 SIVAL(pdata,l1_cUnit,dsize);
2759 SIVAL(pdata,l1_cUnitAvail,dfree);
2760 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2764 case SMB_INFO_VOLUME:
2765 /* Return volume name */
2767 * Add volume serial number - hash of a combination of
2768 * the called hostname and the service name.
2770 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2772 * Win2k3 and previous mess this up by sending a name length
2773 * one byte short. I believe only older clients (OS/2 Win9x) use
2774 * this call so try fixing this by adding a terminating null to
2775 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2779 pdata+l2_vol_szVolLabel, vname,
2780 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2781 STR_NOALIGN|STR_TERMINATE);
2782 SCVAL(pdata,l2_vol_cch,len);
2783 data_len = l2_vol_szVolLabel + len;
2784 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2785 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2789 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2790 case SMB_FS_ATTRIBUTE_INFORMATION:
2792 additional_flags = 0;
2793 #if defined(HAVE_SYS_QUOTAS)
2794 additional_flags |= FILE_VOLUME_QUOTAS;
2797 if(lp_nt_acl_support(SNUM(conn))) {
2798 additional_flags |= FILE_PERSISTENT_ACLS;
2801 /* Capabilities are filled in at connection time through STATVFS call */
2802 additional_flags |= conn->fs_capabilities;
2804 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2805 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2806 additional_flags); /* FS ATTRIBUTES */
2808 SIVAL(pdata,4,255); /* Max filename component length */
2809 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2810 and will think we can't do long filenames */
2811 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2812 PTR_DIFF(end_data, pdata+12),
2815 data_len = 12 + len;
2818 case SMB_QUERY_FS_LABEL_INFO:
2819 case SMB_FS_LABEL_INFORMATION:
2820 len = srvstr_push(pdata, flags2, pdata+4, vname,
2821 PTR_DIFF(end_data, pdata+4), 0);
2826 case SMB_QUERY_FS_VOLUME_INFO:
2827 case SMB_FS_VOLUME_INFORMATION:
2830 * Add volume serial number - hash of a combination of
2831 * the called hostname and the service name.
2833 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2834 (str_checksum(get_local_machine_name())<<16));
2836 /* Max label len is 32 characters. */
2837 len = srvstr_push(pdata, flags2, pdata+18, vname,
2838 PTR_DIFF(end_data, pdata+18),
2840 SIVAL(pdata,12,len);
2843 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2844 (int)strlen(vname),vname, lp_servicename(snum)));
2847 case SMB_QUERY_FS_SIZE_INFO:
2848 case SMB_FS_SIZE_INFORMATION:
2850 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2852 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2853 return map_nt_error_from_unix(errno);
2855 block_size = lp_block_size(snum);
2856 if (bsize < block_size) {
2857 uint64_t factor = block_size/bsize;
2862 if (bsize > block_size) {
2863 uint64_t factor = bsize/block_size;
2868 bytes_per_sector = 512;
2869 sectors_per_unit = bsize/bytes_per_sector;
2870 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2871 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2872 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2873 SBIG_UINT(pdata,0,dsize);
2874 SBIG_UINT(pdata,8,dfree);
2875 SIVAL(pdata,16,sectors_per_unit);
2876 SIVAL(pdata,20,bytes_per_sector);
2880 case SMB_FS_FULL_SIZE_INFORMATION:
2882 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2884 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2885 return map_nt_error_from_unix(errno);
2887 block_size = lp_block_size(snum);
2888 if (bsize < block_size) {
2889 uint64_t factor = block_size/bsize;
2894 if (bsize > block_size) {
2895 uint64_t factor = bsize/block_size;
2900 bytes_per_sector = 512;
2901 sectors_per_unit = bsize/bytes_per_sector;
2902 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2903 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2904 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2905 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2906 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2907 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2908 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2909 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2913 case SMB_QUERY_FS_DEVICE_INFO:
2914 case SMB_FS_DEVICE_INFORMATION:
2916 SIVAL(pdata,0,0); /* dev type */
2917 SIVAL(pdata,4,0); /* characteristics */
2920 #ifdef HAVE_SYS_QUOTAS
2921 case SMB_FS_QUOTA_INFORMATION:
2923 * what we have to send --metze:
2925 * Unknown1: 24 NULL bytes
2926 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2927 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2928 * Quota Flags: 2 byte :
2929 * Unknown3: 6 NULL bytes
2933 * details for Quota Flags:
2935 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2936 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2937 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2938 * 0x0001 Enable Quotas: enable quota for this fs
2942 /* we need to fake up a fsp here,
2943 * because its not send in this call
2946 SMB_NTQUOTA_STRUCT quotas;
2949 ZERO_STRUCT(quotas);
2955 if (conn->server_info->utok.uid != sec_initial_uid()) {
2956 DEBUG(0,("set_user_quota: access_denied "
2957 "service [%s] user [%s]\n",
2958 lp_servicename(SNUM(conn)),
2959 conn->server_info->unix_name));
2960 return NT_STATUS_ACCESS_DENIED;
2963 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2964 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2965 return map_nt_error_from_unix(errno);
2970 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2971 lp_servicename(SNUM(conn))));
2973 /* Unknown1 24 NULL bytes*/
2974 SBIG_UINT(pdata,0,(uint64_t)0);
2975 SBIG_UINT(pdata,8,(uint64_t)0);
2976 SBIG_UINT(pdata,16,(uint64_t)0);
2978 /* Default Soft Quota 8 bytes */
2979 SBIG_UINT(pdata,24,quotas.softlim);
2981 /* Default Hard Quota 8 bytes */
2982 SBIG_UINT(pdata,32,quotas.hardlim);
2984 /* Quota flag 2 bytes */
2985 SSVAL(pdata,40,quotas.qflags);
2987 /* Unknown3 6 NULL bytes */
2993 #endif /* HAVE_SYS_QUOTAS */
2994 case SMB_FS_OBJECTID_INFORMATION:
2996 unsigned char objid[16];
2997 struct smb_extended_info extended_info;
2998 memcpy(pdata,create_volume_objectid(conn, objid),16);
2999 samba_extended_info_version (&extended_info);
3000 SIVAL(pdata,16,extended_info.samba_magic);
3001 SIVAL(pdata,20,extended_info.samba_version);
3002 SIVAL(pdata,24,extended_info.samba_subversion);
3003 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3004 memcpy(pdata+36,extended_info.samba_version_string,28);
3010 * Query the version and capabilities of the CIFS UNIX extensions
3014 case SMB_QUERY_CIFS_UNIX_INFO:
3016 bool large_write = lp_min_receive_file_size() &&
3017 !srv_is_signing_active(smbd_server_conn);
3018 bool large_read = !srv_is_signing_active(smbd_server_conn);
3019 int encrypt_caps = 0;
3021 if (!lp_unix_extensions()) {
3022 return NT_STATUS_INVALID_LEVEL;
3025 switch (conn->encrypt_level) {
3031 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3034 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3035 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3036 large_write = false;
3042 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3043 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3045 /* We have POSIX ACLs, pathname, encryption,
3046 * large read/write, and locking capability. */
3048 SBIG_UINT(pdata,4,((uint64_t)(
3049 CIFS_UNIX_POSIX_ACLS_CAP|
3050 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3051 CIFS_UNIX_FCNTL_LOCKS_CAP|
3052 CIFS_UNIX_EXTATTR_CAP|
3053 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3055 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3057 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3061 case SMB_QUERY_POSIX_FS_INFO:
3064 vfs_statvfs_struct svfs;
3066 if (!lp_unix_extensions()) {
3067 return NT_STATUS_INVALID_LEVEL;
3070 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3074 SIVAL(pdata,0,svfs.OptimalTransferSize);
3075 SIVAL(pdata,4,svfs.BlockSize);
3076 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3077 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3078 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3079 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3080 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3081 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3082 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3084 } else if (rc == EOPNOTSUPP) {
3085 return NT_STATUS_INVALID_LEVEL;
3086 #endif /* EOPNOTSUPP */
3088 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3089 return NT_STATUS_DOS(ERRSRV, ERRerror);
3094 case SMB_QUERY_POSIX_WHOAMI:
3100 if (!lp_unix_extensions()) {
3101 return NT_STATUS_INVALID_LEVEL;
3104 if (max_data_bytes < 40) {
3105 return NT_STATUS_BUFFER_TOO_SMALL;
3108 /* We ARE guest if global_sid_Builtin_Guests is
3109 * in our list of SIDs.
3111 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3112 conn->server_info->ptok)) {
3113 flags |= SMB_WHOAMI_GUEST;
3116 /* We are NOT guest if global_sid_Authenticated_Users
3117 * is in our list of SIDs.
3119 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3120 conn->server_info->ptok)) {
3121 flags &= ~SMB_WHOAMI_GUEST;
3124 /* NOTE: 8 bytes for UID/GID, irrespective of native
3125 * platform size. This matches
3126 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3128 data_len = 4 /* flags */
3135 + 4 /* pad/reserved */
3136 + (conn->server_info->utok.ngroups * 8)
3138 + (conn->server_info->ptok->num_sids *
3142 SIVAL(pdata, 0, flags);
3143 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3145 (uint64_t)conn->server_info->utok.uid);
3146 SBIG_UINT(pdata, 16,
3147 (uint64_t)conn->server_info->utok.gid);
3150 if (data_len >= max_data_bytes) {
3151 /* Potential overflow, skip the GIDs and SIDs. */
3153 SIVAL(pdata, 24, 0); /* num_groups */
3154 SIVAL(pdata, 28, 0); /* num_sids */
3155 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3156 SIVAL(pdata, 36, 0); /* reserved */
3162 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3163 SIVAL(pdata, 28, conn->server_info->num_sids);
3165 /* We walk the SID list twice, but this call is fairly
3166 * infrequent, and I don't expect that it's performance
3167 * sensitive -- jpeach
3169 for (i = 0, sid_bytes = 0;
3170 i < conn->server_info->ptok->num_sids; ++i) {
3171 sid_bytes += ndr_size_dom_sid(
3172 &conn->server_info->ptok->user_sids[i],
3177 /* SID list byte count */
3178 SIVAL(pdata, 32, sid_bytes);
3180 /* 4 bytes pad/reserved - must be zero */
3181 SIVAL(pdata, 36, 0);
3185 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3186 SBIG_UINT(pdata, data_len,
3187 (uint64_t)conn->server_info->utok.groups[i]);
3193 i < conn->server_info->ptok->num_sids; ++i) {
3194 int sid_len = ndr_size_dom_sid(
3195 &conn->server_info->ptok->user_sids[i],
3199 sid_linearize(pdata + data_len, sid_len,
3200 &conn->server_info->ptok->user_sids[i]);
3201 data_len += sid_len;
3207 case SMB_MAC_QUERY_FS_INFO:
3209 * Thursby MAC extension... ONLY on NTFS filesystems
3210 * once we do streams then we don't need this
3212 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3214 SIVAL(pdata,84,0x100); /* Don't support mac... */
3219 return NT_STATUS_INVALID_LEVEL;
3222 *ret_data_len = data_len;
3223 return NT_STATUS_OK;
3226 /****************************************************************************
3227 Reply to a TRANS2_QFSINFO (query filesystem info).
3228 ****************************************************************************/
3230 static void call_trans2qfsinfo(connection_struct *conn,
3231 struct smb_request *req,
3232 char **pparams, int total_params,
3233 char **ppdata, int total_data,
3234 unsigned int max_data_bytes)
3236 char *params = *pparams;
3237 uint16_t info_level;
3242 if (total_params < 2) {
3243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3247 info_level = SVAL(params,0);
3249 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3250 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3251 DEBUG(0,("call_trans2qfsinfo: encryption required "
3252 "and info level 0x%x sent.\n",
3253 (unsigned int)info_level));
3254 exit_server_cleanly("encryption required "
3260 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3262 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
3263 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
3264 reply_doserror(req, ERRSRV, ERRinvdevice);
3268 status = smbd_do_qfsinfo(conn, req,
3273 if (!NT_STATUS_IS_OK(status)) {
3274 reply_nterror(req, status);
3278 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3281 DEBUG( 4, ( "%s info_level = %d\n",
3282 smb_fn_name(req->cmd), info_level) );
3287 /****************************************************************************
3288 Reply to a TRANS2_SETFSINFO (set filesystem info).
3289 ****************************************************************************/
3291 static void call_trans2setfsinfo(connection_struct *conn,
3292 struct smb_request *req,
3293 char **pparams, int total_params,
3294 char **ppdata, int total_data,
3295 unsigned int max_data_bytes)
3297 char *pdata = *ppdata;
3298 char *params = *pparams;
3301 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3304 if (total_params < 4) {
3305 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3311 info_level = SVAL(params,2);
3314 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3315 info_level != SMB_SET_CIFS_UNIX_INFO) {
3316 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3317 "info level (0x%x) on IPC$.\n",
3318 (unsigned int)info_level));
3319 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3324 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3325 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3326 DEBUG(0,("call_trans2setfsinfo: encryption required "
3327 "and info level 0x%x sent.\n",
3328 (unsigned int)info_level));
3329 exit_server_cleanly("encryption required "
3335 switch(info_level) {
3336 case SMB_SET_CIFS_UNIX_INFO:
3338 uint16 client_unix_major;
3339 uint16 client_unix_minor;
3340 uint32 client_unix_cap_low;
3341 uint32 client_unix_cap_high;
3343 if (!lp_unix_extensions()) {
3345 NT_STATUS_INVALID_LEVEL);
3349 /* There should be 12 bytes of capabilities set. */
3350 if (total_data < 8) {
3353 NT_STATUS_INVALID_PARAMETER);
3356 client_unix_major = SVAL(pdata,0);
3357 client_unix_minor = SVAL(pdata,2);
3358 client_unix_cap_low = IVAL(pdata,4);
3359 client_unix_cap_high = IVAL(pdata,8);
3360 /* Just print these values for now. */
3361 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3362 cap_low = 0x%x, cap_high = 0x%x\n",
3363 (unsigned int)client_unix_major,
3364 (unsigned int)client_unix_minor,
3365 (unsigned int)client_unix_cap_low,
3366 (unsigned int)client_unix_cap_high ));
3368 /* Here is where we must switch to posix pathname processing... */
3369 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3370 lp_set_posix_pathnames();
3371 mangle_change_to_posix();
3374 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3375 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3376 /* Client that knows how to do posix locks,
3377 * but not posix open/mkdir operations. Set a
3378 * default type for read/write checks. */
3380 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3386 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3389 size_t param_len = 0;
3390 size_t data_len = total_data;
3392 if (!lp_unix_extensions()) {
3395 NT_STATUS_INVALID_LEVEL);
3399 if (lp_smb_encrypt(SNUM(conn)) == false) {
3402 NT_STATUS_NOT_SUPPORTED);
3406 DEBUG( 4,("call_trans2setfsinfo: "
3407 "request transport encryption.\n"));
3409 status = srv_request_encryption_setup(conn,
3410 (unsigned char **)ppdata,
3412 (unsigned char **)pparams,
3415 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3416 !NT_STATUS_IS_OK(status)) {
3417 reply_nterror(req, status);
3421 send_trans2_replies(conn, req,
3428 if (NT_STATUS_IS_OK(status)) {
3429 /* Server-side transport
3430 * encryption is now *on*. */
3431 status = srv_encryption_start(conn);
3432 if (!NT_STATUS_IS_OK(status)) {
3433 exit_server_cleanly(
3434 "Failure in setting "
3435 "up encrypted transport");
3441 case SMB_FS_QUOTA_INFORMATION:
3443 files_struct *fsp = NULL;
3444 SMB_NTQUOTA_STRUCT quotas;
3446 ZERO_STRUCT(quotas);
3449 if ((conn->server_info->utok.uid != sec_initial_uid())
3450 ||!CAN_WRITE(conn)) {
3451 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3452 lp_servicename(SNUM(conn)),
3453 conn->server_info->unix_name));
3454 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3458 /* note: normaly there're 48 bytes,
3459 * but we didn't use the last 6 bytes for now
3462 fsp = file_fsp(req, SVAL(params,0));
3464 if (!check_fsp_ntquota_handle(conn, req,
3466 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3468 req, NT_STATUS_INVALID_HANDLE);
3472 if (total_data < 42) {
3473 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3477 NT_STATUS_INVALID_PARAMETER);
3481 /* unknown_1 24 NULL bytes in pdata*/
3483 /* the soft quotas 8 bytes (uint64_t)*/
3484 quotas.softlim = (uint64_t)IVAL(pdata,24);
3485 #ifdef LARGE_SMB_OFF_T
3486 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3487 #else /* LARGE_SMB_OFF_T */
3488 if ((IVAL(pdata,28) != 0)&&
3489 ((quotas.softlim != 0xFFFFFFFF)||
3490 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3491 /* more than 32 bits? */
3494 NT_STATUS_INVALID_PARAMETER);
3497 #endif /* LARGE_SMB_OFF_T */
3499 /* the hard quotas 8 bytes (uint64_t)*/
3500 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3501 #ifdef LARGE_SMB_OFF_T
3502 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3503 #else /* LARGE_SMB_OFF_T */
3504 if ((IVAL(pdata,36) != 0)&&
3505 ((quotas.hardlim != 0xFFFFFFFF)||
3506 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3507 /* more than 32 bits? */
3510 NT_STATUS_INVALID_PARAMETER);
3513 #endif /* LARGE_SMB_OFF_T */
3515 /* quota_flags 2 bytes **/
3516 quotas.qflags = SVAL(pdata,40);
3518 /* unknown_2 6 NULL bytes follow*/
3520 /* now set the quotas */
3521 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3522 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3523 reply_nterror(req, map_nt_error_from_unix(errno));
3530 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3532 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3538 * sending this reply works fine,
3539 * but I'm not sure it's the same
3540 * like windows do...
3543 reply_outbuf(req, 10, 0);
3546 #if defined(HAVE_POSIX_ACLS)
3547 /****************************************************************************
3548 Utility function to count the number of entries in a POSIX acl.
3549 ****************************************************************************/
3551 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3553 unsigned int ace_count = 0;
3554 int entry_id = SMB_ACL_FIRST_ENTRY;
3555 SMB_ACL_ENTRY_T entry;
3557 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3559 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3560 entry_id = SMB_ACL_NEXT_ENTRY;
3567 /****************************************************************************
3568 Utility function to marshall a POSIX acl into wire format.
3569 ****************************************************************************/
3571 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3573 int entry_id = SMB_ACL_FIRST_ENTRY;
3574 SMB_ACL_ENTRY_T entry;
3576 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3577 SMB_ACL_TAG_T tagtype;
3578 SMB_ACL_PERMSET_T permset;
3579 unsigned char perms = 0;
3580 unsigned int own_grp;
3583 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3584 entry_id = SMB_ACL_NEXT_ENTRY;
3587 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3588 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3592 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3593 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3597 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3598 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3599 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3601 SCVAL(pdata,1,perms);
3604 case SMB_ACL_USER_OBJ:
3605 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3606 own_grp = (unsigned int)pst->st_ex_uid;
3607 SIVAL(pdata,2,own_grp);
3612 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3614 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3617 own_grp = (unsigned int)*puid;
3618 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3619 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3620 SIVAL(pdata,2,own_grp);
3624 case SMB_ACL_GROUP_OBJ:
3625 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3626 own_grp = (unsigned int)pst->st_ex_gid;
3627 SIVAL(pdata,2,own_grp);
3632 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3634 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3637 own_grp = (unsigned int)*pgid;
3638 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3639 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3640 SIVAL(pdata,2,own_grp);
3645 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3646 SIVAL(pdata,2,0xFFFFFFFF);
3647 SIVAL(pdata,6,0xFFFFFFFF);
3650 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3651 SIVAL(pdata,2,0xFFFFFFFF);
3652 SIVAL(pdata,6,0xFFFFFFFF);
3655 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3658 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3665 /****************************************************************************
3666 Store the FILE_UNIX_BASIC info.
3667 ****************************************************************************/
3669 static char *store_file_unix_basic(connection_struct *conn,
3672 const SMB_STRUCT_STAT *psbuf)
3674 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3675 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3677 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3680 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3683 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3684 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3685 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3688 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3692 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3696 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3699 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3703 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3707 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3710 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3714 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3721 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3722 * the chflags(2) (or equivalent) flags.
3724 * XXX: this really should be behind the VFS interface. To do this, we would
3725 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3726 * Each VFS module could then implement its own mapping as appropriate for the
3727 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3729 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3733 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3737 { UF_IMMUTABLE, EXT_IMMUTABLE },
3741 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3745 { UF_HIDDEN, EXT_HIDDEN },
3748 /* Do not remove. We need to guarantee that this array has at least one
3749 * entry to build on HP-UX.
3755 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3756 uint32 *smb_fflags, uint32 *smb_fmask)
3760 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3761 *smb_fmask |= info2_flags_map[i].smb_fflag;
3762 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3763 *smb_fflags |= info2_flags_map[i].smb_fflag;
3768 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3769 const uint32 smb_fflags,
3770 const uint32 smb_fmask,
3773 uint32 max_fmask = 0;
3776 *stat_fflags = psbuf->st_ex_flags;
3778 /* For each flags requested in smb_fmask, check the state of the
3779 * corresponding flag in smb_fflags and set or clear the matching
3783 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3784 max_fmask |= info2_flags_map[i].smb_fflag;
3785 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3786 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3787 *stat_fflags |= info2_flags_map[i].stat_fflag;
3789 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3794 /* If smb_fmask is asking to set any bits that are not supported by
3795 * our flag mappings, we should fail.
3797 if ((smb_fmask & max_fmask) != smb_fmask) {
3805 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3806 * of file flags and birth (create) time.
3808 static char *store_file_unix_basic_info2(connection_struct *conn,
3811 const SMB_STRUCT_STAT *psbuf)
3813 uint32 file_flags = 0;
3814 uint32 flags_mask = 0;
3816 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3818 /* Create (birth) time 64 bit */
3819 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3822 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3823 SIVAL(pdata, 0, file_flags); /* flags */
3824 SIVAL(pdata, 4, flags_mask); /* mask */
3830 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3831 const struct stream_struct *streams,
3833 unsigned int max_data_bytes,
3834 unsigned int *data_size)
3837 unsigned int ofs = 0;
3839 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3840 unsigned int next_offset;
3842 smb_ucs2_t *namebuf;
3844 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3845 streams[i].name, &namelen) ||
3848 return NT_STATUS_INVALID_PARAMETER;
3852 * name_buf is now null-terminated, we need to marshall as not
3858 SIVAL(data, ofs+4, namelen);
3859 SOFF_T(data, ofs+8, streams[i].size);
3860 SOFF_T(data, ofs+16, streams[i].alloc_size);
3861 memcpy(data+ofs+24, namebuf, namelen);
3862 TALLOC_FREE(namebuf);
3864 next_offset = ofs + 24 + namelen;
3866 if (i == num_streams-1) {
3867 SIVAL(data, ofs, 0);
3870 unsigned int align = ndr_align_size(next_offset, 8);
3872 memset(data+next_offset, 0, align);
3873 next_offset += align;
3875 SIVAL(data, ofs, next_offset - ofs);
3884 return NT_STATUS_OK;
3887 /****************************************************************************
3888 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3889 ****************************************************************************/
3891 static void call_trans2qpipeinfo(connection_struct *conn,
3892 struct smb_request *req,
3893 unsigned int tran_call,
3894 char **pparams, int total_params,
3895 char **ppdata, int total_data,
3896 unsigned int max_data_bytes)
3898 char *params = *pparams;
3899 char *pdata = *ppdata;
3900 unsigned int data_size = 0;
3901 unsigned int param_size = 2;
3906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3910 if (total_params < 4) {
3911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3915 fsp = file_fsp(req, SVAL(params,0));
3916 if (!fsp_is_np(fsp)) {
3917 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3921 info_level = SVAL(params,2);
3923 *pparams = (char *)SMB_REALLOC(*pparams,2);
3924 if (*pparams == NULL) {
3925 reply_nterror(req, NT_STATUS_NO_MEMORY);
3930 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3931 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3932 if (*ppdata == NULL ) {
3933 reply_nterror(req, NT_STATUS_NO_MEMORY);
3938 switch (info_level) {
3939 case SMB_FILE_STANDARD_INFORMATION:
3941 SOFF_T(pdata,0,4096LL);
3948 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3952 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3958 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3959 TALLOC_CTX *mem_ctx,
3960 uint16_t info_level,
3962 const struct smb_filename *smb_fname,
3963 bool delete_pending,
3964 struct timespec write_time_ts,
3966 struct ea_list *ea_list,
3967 int lock_data_count,
3970 unsigned int max_data_bytes,
3972 unsigned int *pdata_size)
3974 char *pdata = *ppdata;
3975 char *dstart, *dend;
3976 unsigned int data_size;
3977 struct timespec create_time_ts, mtime_ts, atime_ts;
3978 time_t create_time, mtime, atime;
3979 SMB_STRUCT_STAT sbuf;
3987 uint64_t file_size = 0;
3989 uint64_t allocation_size = 0;
3990 uint64_t file_index = 0;
3991 uint32_t access_mask = 0;
3993 sbuf = smb_fname->st;
3995 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3996 return NT_STATUS_INVALID_LEVEL;
3999 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
4000 if (!NT_STATUS_IS_OK(status)) {
4004 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4005 fname, fsp ? fsp->fnum : -1, info_level, max_data_bytes));
4008 mode = dos_mode_msdfs(conn, smb_fname);
4010 mode = dos_mode(conn, smb_fname);
4013 mode = FILE_ATTRIBUTE_NORMAL;
4015 nlink = sbuf.st_ex_nlink;
4017 if (nlink && (mode&aDIR)) {
4021 if ((nlink > 0) && delete_pending) {
4025 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4026 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4027 if (*ppdata == NULL) {
4028 return NT_STATUS_NO_MEMORY;
4032 dend = dstart + data_size - 1;
4034 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4035 update_stat_ex_mtime(&sbuf, write_time_ts);
4038 create_time_ts = sbuf.st_ex_btime;
4039 mtime_ts = sbuf.st_ex_mtime;
4040 atime_ts = sbuf.st_ex_atime;
4042 if (lp_dos_filetime_resolution(SNUM(conn))) {
4043 dos_filetime_timespec(&create_time_ts);
4044 dos_filetime_timespec(&mtime_ts);
4045 dos_filetime_timespec(&atime_ts);
4048 create_time = convert_timespec_to_time_t(create_time_ts);
4049 mtime = convert_timespec_to_time_t(mtime_ts);
4050 atime = convert_timespec_to_time_t(atime_ts);
4052 p = strrchr_m(smb_fname->base_name,'/');
4054 base_name = smb_fname->base_name;
4058 /* NT expects the name to be in an exact form of the *full*
4059 filename. See the trans2 torture test */
4060 if (ISDOT(base_name)) {
4061 dos_fname = talloc_strdup(mem_ctx, "\\");
4063 return NT_STATUS_NO_MEMORY;
4066 dos_fname = talloc_asprintf(mem_ctx,
4070 return NT_STATUS_NO_MEMORY;
4072 string_replace(dos_fname, '/', '\\');
4075 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4078 /* Do we have this path open ? */
4080 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4081 fsp1 = file_find_di_first(fileid);
4082 if (fsp1 && fsp1->initial_allocation_size) {
4083 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4087 if (!(mode & aDIR)) {
4088 file_size = get_file_size_stat(&sbuf);
4092 pos = fsp->fh->position_information;
4096 access_mask = fsp->access_mask;
4098 /* GENERIC_EXECUTE mapping from Windows */
4099 access_mask = 0x12019F;
4102 /* This should be an index number - looks like
4105 I think this causes us to fail the IFSKIT
4106 BasicFileInformationTest. -tpot */
4107 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4108 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4110 switch (info_level) {
4111 case SMB_INFO_STANDARD:
4112 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4114 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4115 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4116 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4117 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4118 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4119 SSVAL(pdata,l1_attrFile,mode);
4122 case SMB_INFO_QUERY_EA_SIZE:
4124 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4125 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4127 srv_put_dos_date2(pdata,0,create_time);
4128 srv_put_dos_date2(pdata,4,atime);
4129 srv_put_dos_date2(pdata,8,mtime); /* write time */
4130 SIVAL(pdata,12,(uint32)file_size);
4131 SIVAL(pdata,16,(uint32)allocation_size);
4132 SSVAL(pdata,20,mode);
4133 SIVAL(pdata,22,ea_size);
4137 case SMB_INFO_IS_NAME_VALID:
4138 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4140 /* os/2 needs this ? really ?*/
4141 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4143 /* This is only reached for qpathinfo */
4147 case SMB_INFO_QUERY_EAS_FROM_LIST:
4149 size_t total_ea_len = 0;
4150 struct ea_list *ea_file_list = NULL;
4152 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4154 ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4155 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4157 if (!ea_list || (total_ea_len > data_size)) {
4159 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4163 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4167 case SMB_INFO_QUERY_ALL_EAS:
4169 /* We have data_size bytes to put EA's into. */
4170 size_t total_ea_len = 0;
4172 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4174 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4175 if (!ea_list || (total_ea_len > data_size)) {
4177 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4181 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4185 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4187 /* We have data_size bytes to put EA's into. */
4188 size_t total_ea_len = 0;
4189 struct ea_list *ea_file_list = NULL;
4191 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4193 /*TODO: add filtering and index handling */
4195 ea_file_list = get_ea_list_from_file(mem_ctx,
4199 if (!ea_file_list) {
4200 return NT_STATUS_NO_EAS_ON_FILE;
4203 status = fill_ea_chained_buffer(mem_ctx,
4207 conn, ea_file_list);
4208 if (!NT_STATUS_IS_OK(status)) {
4214 case SMB_FILE_BASIC_INFORMATION:
4215 case SMB_QUERY_FILE_BASIC_INFO:
4217 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4218 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4219 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4221 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4225 put_long_date_timespec(pdata,create_time_ts);
4226 put_long_date_timespec(pdata+8,atime_ts);
4227 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4228 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4229 SIVAL(pdata,32,mode);
4231 DEBUG(5,("SMB_QFBI - "));
4232 DEBUG(5,("create: %s ", ctime(&create_time)));
4233 DEBUG(5,("access: %s ", ctime(&atime)));
4234 DEBUG(5,("write: %s ", ctime(&mtime)));
4235 DEBUG(5,("change: %s ", ctime(&mtime)));
4236 DEBUG(5,("mode: %x\n", mode));
4239 case SMB_FILE_STANDARD_INFORMATION:
4240 case SMB_QUERY_FILE_STANDARD_INFO:
4242 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4244 SOFF_T(pdata,0,allocation_size);
4245 SOFF_T(pdata,8,file_size);
4246 SIVAL(pdata,16,nlink);
4247 SCVAL(pdata,20,delete_pending?1:0);
4248 SCVAL(pdata,21,(mode&aDIR)?1:0);
4249 SSVAL(pdata,22,0); /* Padding. */
4252 case SMB_FILE_EA_INFORMATION:
4253 case SMB_QUERY_FILE_EA_INFO:
4255 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4256 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4258 SIVAL(pdata,0,ea_size);
4262 /* Get the 8.3 name - used if NT SMB was negotiated. */
4263 case SMB_QUERY_FILE_ALT_NAME_INFO:
4264 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4267 char mangled_name[13];
4268 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4269 if (!name_to_8_3(base_name,mangled_name,
4270 True,conn->params)) {
4271 return NT_STATUS_NO_MEMORY;
4273 len = srvstr_push(dstart, flags2,
4274 pdata+4, mangled_name,
4275 PTR_DIFF(dend, pdata+4),
4277 data_size = 4 + len;
4282 case SMB_QUERY_FILE_NAME_INFO:
4286 this must be *exactly* right for ACLs on mapped drives to work
4288 len = srvstr_push(dstart, flags2,
4290 PTR_DIFF(dend, pdata+4),
4292 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4293 data_size = 4 + len;
4298 case SMB_FILE_ALLOCATION_INFORMATION:
4299 case SMB_QUERY_FILE_ALLOCATION_INFO:
4300 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4302 SOFF_T(pdata,0,allocation_size);
4305 case SMB_FILE_END_OF_FILE_INFORMATION:
4306 case SMB_QUERY_FILE_END_OF_FILEINFO:
4307 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4309 SOFF_T(pdata,0,file_size);
4312 case SMB_QUERY_FILE_ALL_INFO:
4313 case SMB_FILE_ALL_INFORMATION:
4316 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4317 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4318 put_long_date_timespec(pdata,create_time_ts);
4319 put_long_date_timespec(pdata+8,atime_ts);
4320 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4321 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4322 SIVAL(pdata,32,mode);
4323 SIVAL(pdata,36,0); /* padding. */
4325 SOFF_T(pdata,0,allocation_size);
4326 SOFF_T(pdata,8,file_size);
4327 SIVAL(pdata,16,nlink);
4328 SCVAL(pdata,20,delete_pending);
4329 SCVAL(pdata,21,(mode&aDIR)?1:0);
4332 SIVAL(pdata,0,ea_size);
4333 pdata += 4; /* EA info */
4334 len = srvstr_push(dstart, flags2,
4336 PTR_DIFF(dend, pdata+4),
4340 data_size = PTR_DIFF(pdata,(*ppdata));
4344 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4347 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4348 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4349 put_long_date_timespec(pdata+0x00,create_time_ts);
4350 put_long_date_timespec(pdata+0x08,atime_ts);
4351 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4352 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4353 SIVAL(pdata, 0x20, mode);
4354 SIVAL(pdata, 0x24, 0); /* padding. */
4355 SBVAL(pdata, 0x28, allocation_size);
4356 SBVAL(pdata, 0x30, file_size);
4357 SIVAL(pdata, 0x38, nlink);
4358 SCVAL(pdata, 0x3C, delete_pending);
4359 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4360 SSVAL(pdata, 0x3E, 0); /* padding */
4361 SBVAL(pdata, 0x40, file_index);
4362 SIVAL(pdata, 0x48, ea_size);
4363 SIVAL(pdata, 0x4C, access_mask);
4364 SBVAL(pdata, 0x50, pos);
4365 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4366 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4370 len = srvstr_push(dstart, flags2,
4372 PTR_DIFF(dend, pdata+4),
4376 data_size = PTR_DIFF(pdata,(*ppdata));
4379 case SMB_FILE_INTERNAL_INFORMATION:
4381 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4382 SBVAL(pdata, 0, file_index);
4386 case SMB_FILE_ACCESS_INFORMATION:
4387 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4388 SIVAL(pdata, 0, access_mask);
4392 case SMB_FILE_NAME_INFORMATION:
4393 /* Pathname with leading '\'. */
4396 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4397 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4398 SIVAL(pdata,0,byte_len);
4399 data_size = 4 + byte_len;
4403 case SMB_FILE_DISPOSITION_INFORMATION:
4404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4406 SCVAL(pdata,0,delete_pending);
4409 case SMB_FILE_POSITION_INFORMATION:
4410 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4412 SOFF_T(pdata,0,pos);
4415 case SMB_FILE_MODE_INFORMATION:
4416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4417 SIVAL(pdata,0,mode);
4421 case SMB_FILE_ALIGNMENT_INFORMATION:
4422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4423 SIVAL(pdata,0,0); /* No alignment needed. */
4428 * NT4 server just returns "invalid query" to this - if we try
4429 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4432 /* The first statement above is false - verified using Thursby
4433 * client against NT4 -- gcolley.
4435 case SMB_QUERY_FILE_STREAM_INFO:
4436 case SMB_FILE_STREAM_INFORMATION: {
4437 unsigned int num_streams;
4438 struct stream_struct *streams;
4440 DEBUG(10,("smbd_do_qfilepathinfo: "
4441 "SMB_FILE_STREAM_INFORMATION\n"));
4443 status = SMB_VFS_STREAMINFO(
4444 conn, fsp, fname, talloc_tos(),
4445 &num_streams, &streams);
4447 if (!NT_STATUS_IS_OK(status)) {
4448 DEBUG(10, ("could not get stream info: %s\n",
4449 nt_errstr(status)));
4453 status = marshall_stream_info(num_streams, streams,
4454 pdata, max_data_bytes,
4457 if (!NT_STATUS_IS_OK(status)) {
4458 DEBUG(10, ("marshall_stream_info failed: %s\n",
4459 nt_errstr(status)));
4463 TALLOC_FREE(streams);
4467 case SMB_QUERY_COMPRESSION_INFO:
4468 case SMB_FILE_COMPRESSION_INFORMATION:
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4470 SOFF_T(pdata,0,file_size);
4471 SIVAL(pdata,8,0); /* ??? */
4472 SIVAL(pdata,12,0); /* ??? */
4476 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4477 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4478 put_long_date_timespec(pdata,create_time_ts);
4479 put_long_date_timespec(pdata+8,atime_ts);
4480 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4481 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4482 SOFF_T(pdata,32,allocation_size);
4483 SOFF_T(pdata,40,file_size);
4484 SIVAL(pdata,48,mode);
4485 SIVAL(pdata,52,0); /* ??? */
4489 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4490 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4491 SIVAL(pdata,0,mode);
4497 * CIFS UNIX Extensions.
4500 case SMB_QUERY_FILE_UNIX_BASIC:
4502 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4503 data_size = PTR_DIFF(pdata,(*ppdata));
4507 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4509 for (i=0; i<100; i++)
4510 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4516 case SMB_QUERY_FILE_UNIX_INFO2:
4518 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4519 data_size = PTR_DIFF(pdata,(*ppdata));
4523 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4525 for (i=0; i<100; i++)
4526 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4532 case SMB_QUERY_FILE_UNIX_LINK:
4535 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4538 return NT_STATUS_NO_MEMORY;
4541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4543 if(!S_ISLNK(sbuf.st_ex_mode)) {
4544 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4547 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4549 len = SMB_VFS_READLINK(conn,fname,
4552 return map_nt_error_from_unix(errno);
4555 len = srvstr_push(dstart, flags2,
4557 PTR_DIFF(dend, pdata),
4560 data_size = PTR_DIFF(pdata,(*ppdata));
4565 #if defined(HAVE_POSIX_ACLS)
4566 case SMB_QUERY_POSIX_ACL:
4568 SMB_ACL_T file_acl = NULL;
4569 SMB_ACL_T def_acl = NULL;
4570 uint16 num_file_acls = 0;
4571 uint16 num_def_acls = 0;
4573 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4574 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4576 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4579 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4580 DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4582 return NT_STATUS_NOT_IMPLEMENTED;
4585 if (S_ISDIR(sbuf.st_ex_mode)) {
4586 if (fsp && fsp->is_directory) {
4588 SMB_VFS_SYS_ACL_GET_FILE(
4590 fsp->fsp_name->base_name,
4591 SMB_ACL_TYPE_DEFAULT);
4593 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4595 def_acl = free_empty_sys_acl(conn, def_acl);
4598 num_file_acls = count_acl_entries(conn, file_acl);
4599 num_def_acls = count_acl_entries(conn, def_acl);
4601 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4602 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4604 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4605 SMB_POSIX_ACL_HEADER_SIZE) ));
4607 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4610 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4612 return NT_STATUS_BUFFER_TOO_SMALL;
4615 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4616 SSVAL(pdata,2,num_file_acls);
4617 SSVAL(pdata,4,num_def_acls);
4618 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4620 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4623 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4625 return NT_STATUS_INTERNAL_ERROR;
4627 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4629 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4632 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4634 return NT_STATUS_INTERNAL_ERROR;
4638 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4641 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4643 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4649 case SMB_QUERY_POSIX_LOCK:
4654 enum brl_type lock_type;
4656 /* We need an open file with a real fd for this. */
4657 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4658 return NT_STATUS_INVALID_LEVEL;
4661 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4662 return NT_STATUS_INVALID_PARAMETER;
4665 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4666 case POSIX_LOCK_TYPE_READ:
4667 lock_type = READ_LOCK;
4669 case POSIX_LOCK_TYPE_WRITE:
4670 lock_type = WRITE_LOCK;
4672 case POSIX_LOCK_TYPE_UNLOCK:
4674 /* There's no point in asking for an unlock... */
4675 return NT_STATUS_INVALID_PARAMETER;
4678 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4679 #if defined(HAVE_LONGLONG)
4680 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4681 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4682 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4683 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4684 #else /* HAVE_LONGLONG */
4685 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4686 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4687 #endif /* HAVE_LONGLONG */
4689 status = query_lock(fsp,
4696 if (ERROR_WAS_LOCK_DENIED(status)) {
4697 /* Here we need to report who has it locked... */
4698 data_size = POSIX_LOCK_DATA_SIZE;
4700 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4701 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4702 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4703 #if defined(HAVE_LONGLONG)
4704 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4705 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4706 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4707 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4708 #else /* HAVE_LONGLONG */
4709 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4710 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4711 #endif /* HAVE_LONGLONG */
4713 } else if (NT_STATUS_IS_OK(status)) {
4714 /* For success we just return a copy of what we sent
4715 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4716 data_size = POSIX_LOCK_DATA_SIZE;
4717 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4718 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4726 return NT_STATUS_INVALID_LEVEL;
4729 *pdata_size = data_size;
4730 return NT_STATUS_OK;
4733 /****************************************************************************
4734 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4735 file name or file id).
4736 ****************************************************************************/
4738 static void call_trans2qfilepathinfo(connection_struct *conn,
4739 struct smb_request *req,
4740 unsigned int tran_call,
4741 char **pparams, int total_params,
4742 char **ppdata, int total_data,
4743 unsigned int max_data_bytes)
4745 char *params = *pparams;
4746 char *pdata = *ppdata;
4748 unsigned int data_size = 0;
4749 unsigned int param_size = 2;
4750 struct smb_filename *smb_fname = NULL;
4751 bool delete_pending = False;
4752 struct timespec write_time_ts;
4753 files_struct *fsp = NULL;
4754 struct file_id fileid;
4755 struct ea_list *ea_list = NULL;
4756 int lock_data_count = 0;
4757 char *lock_data = NULL;
4758 bool ms_dfs_link = false;
4759 NTSTATUS status = NT_STATUS_OK;
4762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4766 ZERO_STRUCT(write_time_ts);
4768 if (tran_call == TRANSACT2_QFILEINFO) {
4769 if (total_params < 4) {
4770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4775 call_trans2qpipeinfo(conn, req, tran_call,
4776 pparams, total_params,
4782 fsp = file_fsp(req, SVAL(params,0));
4783 info_level = SVAL(params,2);
4785 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4787 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4788 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4792 /* Initial check for valid fsp ptr. */
4793 if (!check_fsp_open(conn, req, fsp)) {
4797 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4799 if (!NT_STATUS_IS_OK(status)) {
4800 reply_nterror(req, status);
4804 if(fsp->fake_file_handle) {
4806 * This is actually for the QUOTA_FAKE_FILE --metze
4809 /* We know this name is ok, it's already passed the checks. */
4811 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4813 * This is actually a QFILEINFO on a directory
4814 * handle (returned from an NT SMB). NT5.0 seems
4815 * to do this call. JRA.
4818 if (INFO_LEVEL_IS_UNIX(info_level)) {
4819 /* Always do lstat for UNIX calls. */
4820 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4821 DEBUG(3,("call_trans2qfilepathinfo: "
4822 "SMB_VFS_LSTAT of %s failed "
4824 smb_fname_str_dbg(smb_fname),
4827 map_nt_error_from_unix(errno));
4830 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4831 DEBUG(3,("call_trans2qfilepathinfo: "
4832 "SMB_VFS_STAT of %s failed (%s)\n",
4833 smb_fname_str_dbg(smb_fname),
4836 map_nt_error_from_unix(errno));
4840 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4841 get_file_infos(fileid, &delete_pending, &write_time_ts);
4844 * Original code - this is an open file.
4846 if (!check_fsp(conn, req, fsp)) {
4850 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4851 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4852 fsp->fnum, strerror(errno)));
4854 map_nt_error_from_unix(errno));
4857 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4858 get_file_infos(fileid, &delete_pending, &write_time_ts);
4865 if (total_params < 7) {
4866 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4870 info_level = SVAL(params,0);
4872 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4874 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4875 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4879 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4881 STR_TERMINATE, &status);
4882 if (!NT_STATUS_IS_OK(status)) {
4883 reply_nterror(req, status);
4887 status = filename_convert(req,
4889 req->flags2 & FLAGS2_DFS_PATHNAMES,
4892 if (!NT_STATUS_IS_OK(status)) {
4893 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4894 reply_botherror(req,
4895 NT_STATUS_PATH_NOT_COVERED,
4896 ERRSRV, ERRbadpath);
4899 reply_nterror(req, status);
4903 /* If this is a stream, check if there is a delete_pending. */
4904 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4905 && is_ntfs_stream_smb_fname(smb_fname)) {
4906 struct smb_filename *smb_fname_base = NULL;
4908 /* Create an smb_filename with stream_name == NULL. */
4910 create_synthetic_smb_fname(talloc_tos(),
4911 smb_fname->base_name,
4914 if (!NT_STATUS_IS_OK(status)) {
4915 reply_nterror(req, status);
4919 if (INFO_LEVEL_IS_UNIX(info_level)) {
4920 /* Always do lstat for UNIX calls. */
4921 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4922 DEBUG(3,("call_trans2qfilepathinfo: "
4923 "SMB_VFS_LSTAT of %s failed "
4925 smb_fname_str_dbg(smb_fname_base),
4927 TALLOC_FREE(smb_fname_base);
4929 map_nt_error_from_unix(errno));
4933 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4934 DEBUG(3,("call_trans2qfilepathinfo: "
4935 "fileinfo of %s failed "
4937 smb_fname_str_dbg(smb_fname_base),
4939 TALLOC_FREE(smb_fname_base);
4941 map_nt_error_from_unix(errno));
4946 fileid = vfs_file_id_from_sbuf(conn,
4947 &smb_fname_base->st);
4948 TALLOC_FREE(smb_fname_base);
4949 get_file_infos(fileid, &delete_pending, NULL);
4950 if (delete_pending) {
4951 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4956 if (INFO_LEVEL_IS_UNIX(info_level)) {
4957 /* Always do lstat for UNIX calls. */
4958 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4959 DEBUG(3,("call_trans2qfilepathinfo: "
4960 "SMB_VFS_LSTAT of %s failed (%s)\n",
4961 smb_fname_str_dbg(smb_fname),
4964 map_nt_error_from_unix(errno));
4968 } else if (!VALID_STAT(smb_fname->st) &&
4969 SMB_VFS_STAT(conn, smb_fname) &&
4970 (info_level != SMB_INFO_IS_NAME_VALID)) {
4971 ms_dfs_link = check_msdfs_link(conn,
4972 smb_fname->base_name,
4976 DEBUG(3,("call_trans2qfilepathinfo: "
4977 "SMB_VFS_STAT of %s failed (%s)\n",
4978 smb_fname_str_dbg(smb_fname),
4981 map_nt_error_from_unix(errno));
4986 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4987 get_file_infos(fileid, &delete_pending, &write_time_ts);
4988 if (delete_pending) {
4989 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4994 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
4995 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
4996 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4998 /* Pull out any data sent here before we realloc. */
4999 switch (info_level) {
5000 case SMB_INFO_QUERY_EAS_FROM_LIST:
5002 /* Pull any EA list from the data portion. */
5005 if (total_data < 4) {
5007 req, NT_STATUS_INVALID_PARAMETER);
5010 ea_size = IVAL(pdata,0);
5012 if (total_data > 0 && ea_size != total_data) {
5013 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5014 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5016 req, NT_STATUS_INVALID_PARAMETER);
5020 if (!lp_ea_support(SNUM(conn))) {
5021 reply_doserror(req, ERRDOS,
5022 ERReasnotsupported);
5026 /* Pull out the list of names. */
5027 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5030 req, NT_STATUS_INVALID_PARAMETER);
5036 case SMB_QUERY_POSIX_LOCK:
5038 if (fsp == NULL || fsp->fh->fd == -1) {
5039 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5043 if (total_data != POSIX_LOCK_DATA_SIZE) {
5045 req, NT_STATUS_INVALID_PARAMETER);
5049 /* Copy the lock range data. */
5050 lock_data = (char *)TALLOC_MEMDUP(
5051 req, pdata, total_data);
5053 reply_nterror(req, NT_STATUS_NO_MEMORY);
5056 lock_data_count = total_data;
5062 *pparams = (char *)SMB_REALLOC(*pparams,2);
5063 if (*pparams == NULL) {
5064 reply_nterror(req, NT_STATUS_NO_MEMORY);
5071 * draft-leach-cifs-v1-spec-02.txt
5072 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5075 * The requested information is placed in the Data portion of the
5076 * transaction response. For the information levels greater than 0x100,
5077 * the transaction response has 1 parameter word which should be
5078 * ignored by the client.
5080 * However Windows only follows this rule for the IS_NAME_VALID call.
5082 switch (info_level) {
5083 case SMB_INFO_IS_NAME_VALID:
5088 if ((info_level & 0xFF00) == 0xFF00) {
5090 * We use levels that start with 0xFF00
5091 * internally to represent SMB2 specific levels
5093 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5097 status = smbd_do_qfilepathinfo(conn, req, info_level,
5099 delete_pending, write_time_ts,
5100 ms_dfs_link, ea_list,
5101 lock_data_count, lock_data,
5102 req->flags2, max_data_bytes,
5103 ppdata, &data_size);
5104 if (!NT_STATUS_IS_OK(status)) {
5105 reply_nterror(req, status);
5109 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5115 /****************************************************************************
5116 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5118 ****************************************************************************/
5120 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5121 connection_struct *conn,
5122 const struct smb_filename *smb_fname_old,
5123 const struct smb_filename *smb_fname_new)
5125 char *oldname = NULL;
5126 char *newname = NULL;
5127 NTSTATUS status = NT_STATUS_OK;
5129 /* source must already exist. */
5130 if (!VALID_STAT(smb_fname_old->st)) {
5131 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5134 /* Disallow if newname already exists. */
5135 if (VALID_STAT(smb_fname_new->st)) {
5136 return NT_STATUS_OBJECT_NAME_COLLISION;
5139 /* No links from a directory. */
5140 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5141 return NT_STATUS_FILE_IS_A_DIRECTORY;
5144 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
5145 if (!NT_STATUS_IS_OK(status)) {
5148 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
5149 if (!NT_STATUS_IS_OK(status)) {
5153 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
5155 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
5156 status = map_nt_error_from_unix(errno);
5157 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5158 nt_errstr(status), newname, oldname));
5161 TALLOC_FREE(newname);
5162 TALLOC_FREE(oldname);
5166 /****************************************************************************
5167 Deal with setting the time from any of the setfilepathinfo functions.
5168 ****************************************************************************/
5170 NTSTATUS smb_set_file_time(connection_struct *conn,
5172 const struct smb_filename *smb_fname,
5173 struct smb_file_time *ft,
5174 bool setting_write_time)
5176 struct smb_filename *smb_fname_base = NULL;
5178 FILE_NOTIFY_CHANGE_LAST_ACCESS
5179 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5182 if (!VALID_STAT(smb_fname->st)) {
5183 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5186 /* get some defaults (no modifications) if any info is zero or -1. */
5187 if (null_timespec(ft->atime)) {
5188 ft->atime= smb_fname->st.st_ex_atime;
5189 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5192 if (null_timespec(ft->mtime)) {
5193 ft->mtime = smb_fname->st.st_ex_mtime;
5194 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5197 if (!setting_write_time) {
5198 /* ft->mtime comes from change time, not write time. */
5199 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5202 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5203 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5204 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5205 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5206 if (!null_timespec(ft->create_time)) {
5207 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5208 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5212 * Try and set the times of this file if
5213 * they are different from the current values.
5217 struct timespec mts = smb_fname->st.st_ex_mtime;
5218 struct timespec ats = smb_fname->st.st_ex_atime;
5219 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5220 (timespec_compare(&ft->mtime, &mts) == 0)) {
5221 return NT_STATUS_OK;
5225 if (setting_write_time) {
5227 * This was a Windows setfileinfo on an open file.
5228 * NT does this a lot. We also need to
5229 * set the time here, as it can be read by
5230 * FindFirst/FindNext and with the patch for bug #2045
5231 * in smbd/fileio.c it ensures that this timestamp is
5232 * kept sticky even after a write. We save the request
5233 * away and will set it on file close and after a write. JRA.
5236 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5237 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5240 if (fsp->base_fsp) {
5241 set_sticky_write_time_fsp(fsp->base_fsp,
5244 set_sticky_write_time_fsp(fsp, ft->mtime);
5247 set_sticky_write_time_path(
5248 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5253 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5255 /* Always call ntimes on the base, even if a stream was passed in. */
5256 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5257 NULL, &smb_fname->st,
5259 if (!NT_STATUS_IS_OK(status)) {
5263 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5264 TALLOC_FREE(smb_fname_base);
5265 return map_nt_error_from_unix(errno);
5267 TALLOC_FREE(smb_fname_base);
5269 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5270 smb_fname->base_name);
5271 return NT_STATUS_OK;
5274 /****************************************************************************
5275 Deal with setting the dosmode from any of the setfilepathinfo functions.
5276 ****************************************************************************/
5278 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5279 const struct smb_filename *smb_fname,
5282 struct smb_filename *smb_fname_base = NULL;
5285 if (!VALID_STAT(smb_fname->st)) {
5286 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5289 /* Always operate on the base_name, even if a stream was passed in. */
5290 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5291 NULL, &smb_fname->st,
5293 if (!NT_STATUS_IS_OK(status)) {
5298 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5305 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5307 /* check the mode isn't different, before changing it */
5308 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5309 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5310 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5311 (unsigned int)dosmode));
5313 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5315 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5317 smb_fname_str_dbg(smb_fname_base),
5319 status = map_nt_error_from_unix(errno);
5323 status = NT_STATUS_OK;
5325 TALLOC_FREE(smb_fname_base);
5329 /****************************************************************************
5330 Deal with setting the size from any of the setfilepathinfo functions.
5331 ****************************************************************************/
5333 static NTSTATUS smb_set_file_size(connection_struct *conn,
5334 struct smb_request *req,
5336 const struct smb_filename *smb_fname,
5337 const SMB_STRUCT_STAT *psbuf,
5340 NTSTATUS status = NT_STATUS_OK;
5341 struct smb_filename *smb_fname_tmp = NULL;
5342 files_struct *new_fsp = NULL;
5344 if (!VALID_STAT(*psbuf)) {
5345 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5348 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5350 if (size == get_file_size_stat(psbuf)) {
5351 return NT_STATUS_OK;
5354 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5355 smb_fname_str_dbg(smb_fname), (double)size));
5357 if (fsp && fsp->fh->fd != -1) {
5358 /* Handle based call. */
5359 if (vfs_set_filelen(fsp, size) == -1) {
5360 return map_nt_error_from_unix(errno);
5362 trigger_write_time_update_immediate(fsp);
5363 return NT_STATUS_OK;
5366 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5367 if (!NT_STATUS_IS_OK(status)) {
5371 smb_fname_tmp->st = *psbuf;
5373 status = SMB_VFS_CREATE_FILE(
5376 0, /* root_dir_fid */
5377 smb_fname_tmp, /* fname */
5378 FILE_WRITE_ATTRIBUTES, /* access_mask */
5379 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5381 FILE_OPEN, /* create_disposition*/
5382 0, /* create_options */
5383 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5384 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5385 0, /* allocation_size */
5388 &new_fsp, /* result */
5391 TALLOC_FREE(smb_fname_tmp);
5393 if (!NT_STATUS_IS_OK(status)) {
5394 /* NB. We check for open_was_deferred in the caller. */
5398 if (vfs_set_filelen(new_fsp, size) == -1) {
5399 status = map_nt_error_from_unix(errno);
5400 close_file(req, new_fsp,NORMAL_CLOSE);
5404 trigger_write_time_update_immediate(new_fsp);
5405 close_file(req, new_fsp,NORMAL_CLOSE);
5406 return NT_STATUS_OK;
5409 /****************************************************************************
5410 Deal with SMB_INFO_SET_EA.
5411 ****************************************************************************/
5413 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5417 const struct smb_filename *smb_fname)
5419 struct ea_list *ea_list = NULL;
5420 TALLOC_CTX *ctx = NULL;
5421 NTSTATUS status = NT_STATUS_OK;
5423 if (total_data < 10) {
5425 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5426 length. They seem to have no effect. Bug #3212. JRA */
5428 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5429 /* We're done. We only get EA info in this call. */
5430 return NT_STATUS_OK;
5433 return NT_STATUS_INVALID_PARAMETER;
5436 if (IVAL(pdata,0) > total_data) {
5437 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5438 IVAL(pdata,0), (unsigned int)total_data));
5439 return NT_STATUS_INVALID_PARAMETER;
5443 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5445 return NT_STATUS_INVALID_PARAMETER;
5447 status = set_ea(conn, fsp, smb_fname, ea_list);
5452 /****************************************************************************
5453 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5454 ****************************************************************************/
5456 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5460 const struct smb_filename *smb_fname)
5462 NTSTATUS status = NT_STATUS_OK;
5463 bool delete_on_close;
5466 if (total_data < 1) {
5467 return NT_STATUS_INVALID_PARAMETER;
5471 return NT_STATUS_INVALID_HANDLE;
5474 delete_on_close = (CVAL(pdata,0) ? True : False);
5475 dosmode = dos_mode(conn, smb_fname);
5477 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5478 "delete_on_close = %u\n",
5479 smb_fname_str_dbg(smb_fname),
5480 (unsigned int)dosmode,
5481 (unsigned int)delete_on_close ));
5483 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5485 if (!NT_STATUS_IS_OK(status)) {
5489 /* The set is across all open files on this dev/inode pair. */
5490 if (!set_delete_on_close(fsp, delete_on_close,
5491 &conn->server_info->utok)) {
5492 return NT_STATUS_ACCESS_DENIED;
5494 return NT_STATUS_OK;
5497 /****************************************************************************
5498 Deal with SMB_FILE_POSITION_INFORMATION.
5499 ****************************************************************************/
5501 static NTSTATUS smb_file_position_information(connection_struct *conn,
5506 uint64_t position_information;
5508 if (total_data < 8) {
5509 return NT_STATUS_INVALID_PARAMETER;
5513 /* Ignore on pathname based set. */
5514 return NT_STATUS_OK;
5517 position_information = (uint64_t)IVAL(pdata,0);
5518 #ifdef LARGE_SMB_OFF_T
5519 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5520 #else /* LARGE_SMB_OFF_T */
5521 if (IVAL(pdata,4) != 0) {
5522 /* more than 32 bits? */
5523 return NT_STATUS_INVALID_PARAMETER;
5525 #endif /* LARGE_SMB_OFF_T */
5527 DEBUG(10,("smb_file_position_information: Set file position "
5528 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5529 (double)position_information));
5530 fsp->fh->position_information = position_information;
5531 return NT_STATUS_OK;
5534 /****************************************************************************
5535 Deal with SMB_FILE_MODE_INFORMATION.
5536 ****************************************************************************/
5538 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5544 if (total_data < 4) {
5545 return NT_STATUS_INVALID_PARAMETER;
5547 mode = IVAL(pdata,0);
5548 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5549 return NT_STATUS_INVALID_PARAMETER;
5551 return NT_STATUS_OK;
5554 /****************************************************************************
5555 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5556 ****************************************************************************/
5558 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5559 struct smb_request *req,
5564 char *link_target = NULL;
5565 const char *newname = fname;
5566 NTSTATUS status = NT_STATUS_OK;
5567 TALLOC_CTX *ctx = talloc_tos();
5569 /* Set a symbolic link. */
5570 /* Don't allow this if follow links is false. */
5572 if (total_data == 0) {
5573 return NT_STATUS_INVALID_PARAMETER;
5576 if (!lp_symlinks(SNUM(conn))) {
5577 return NT_STATUS_ACCESS_DENIED;
5580 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5581 total_data, STR_TERMINATE);
5584 return NT_STATUS_INVALID_PARAMETER;
5587 /* !widelinks forces the target path to be within the share. */
5588 /* This means we can interpret the target as a pathname. */
5589 if (!lp_widelinks(SNUM(conn))) {
5590 char *rel_name = NULL;
5591 char *last_dirp = NULL;
5593 if (*link_target == '/') {
5594 /* No absolute paths allowed. */
5595 return NT_STATUS_ACCESS_DENIED;
5597 rel_name = talloc_strdup(ctx,newname);
5599 return NT_STATUS_NO_MEMORY;
5601 last_dirp = strrchr_m(rel_name, '/');
5603 last_dirp[1] = '\0';
5605 rel_name = talloc_strdup(ctx,"./");
5607 return NT_STATUS_NO_MEMORY;
5610 rel_name = talloc_asprintf_append(rel_name,
5614 return NT_STATUS_NO_MEMORY;
5617 status = check_name(conn, rel_name);
5618 if (!NT_STATUS_IS_OK(status)) {
5623 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5624 newname, link_target ));
5626 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5627 return map_nt_error_from_unix(errno);
5630 return NT_STATUS_OK;
5633 /****************************************************************************
5634 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5635 ****************************************************************************/
5637 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5638 struct smb_request *req,
5639 const char *pdata, int total_data,
5640 const struct smb_filename *smb_fname_new)
5642 char *oldname = NULL;
5643 struct smb_filename *smb_fname_old = NULL;
5644 TALLOC_CTX *ctx = talloc_tos();
5645 NTSTATUS status = NT_STATUS_OK;
5647 /* Set a hard link. */
5648 if (total_data == 0) {
5649 return NT_STATUS_INVALID_PARAMETER;
5652 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5653 total_data, STR_TERMINATE, &status);
5654 if (!NT_STATUS_IS_OK(status)) {
5658 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5659 smb_fname_str_dbg(smb_fname_new), oldname));
5661 status = filename_convert(ctx,
5663 req->flags2 & FLAGS2_DFS_PATHNAMES,
5666 if (!NT_STATUS_IS_OK(status)) {
5670 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5673 /****************************************************************************
5674 Deal with SMB_FILE_RENAME_INFORMATION.
5675 ****************************************************************************/
5677 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5678 struct smb_request *req,
5687 char *newname = NULL;
5688 char *base_name = NULL;
5689 struct smb_filename *smb_fname = NULL;
5690 bool dest_has_wcard = False;
5691 NTSTATUS status = NT_STATUS_OK;
5693 TALLOC_CTX *ctx = talloc_tos();
5695 if (total_data < 13) {
5696 return NT_STATUS_INVALID_PARAMETER;
5699 overwrite = (CVAL(pdata,0) ? True : False);
5700 root_fid = IVAL(pdata,4);
5701 len = IVAL(pdata,8);
5703 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5704 return NT_STATUS_INVALID_PARAMETER;
5707 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5710 if (!NT_STATUS_IS_OK(status)) {
5714 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5717 status = resolve_dfspath_wcard(ctx, conn,
5718 req->flags2 & FLAGS2_DFS_PATHNAMES,
5722 if (!NT_STATUS_IS_OK(status)) {
5726 /* Check the new name has no '/' characters. */
5727 if (strchr_m(newname, '/')) {
5728 return NT_STATUS_NOT_SUPPORTED;
5731 if (fsp && fsp->base_fsp) {
5732 /* newname must be a stream name. */
5733 if (newname[0] != ':') {
5734 return NT_STATUS_NOT_SUPPORTED;
5737 /* Create an smb_fname to call rename_internals_fsp() with. */
5738 status = create_synthetic_smb_fname(talloc_tos(),
5739 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5741 if (!NT_STATUS_IS_OK(status)) {
5746 * Set the original last component, since
5747 * rename_internals_fsp() requires it.
5749 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5750 if (smb_fname->original_lcomp == NULL) {
5751 status = NT_STATUS_NO_MEMORY;
5755 /* Create a char * to call rename_internals() with. */
5756 base_name = talloc_asprintf(ctx, "%s%s",
5757 fsp->base_fsp->fsp_name->base_name,
5760 status = NT_STATUS_NO_MEMORY;
5764 /* newname must *not* be a stream name. */
5765 if (newname[0] == ':') {
5766 return NT_STATUS_NOT_SUPPORTED;
5769 /* Create the base directory. */
5770 base_name = talloc_strdup(ctx, fname);
5772 return NT_STATUS_NO_MEMORY;
5774 p = strrchr_m(base_name, '/');
5778 base_name = talloc_strdup(ctx, "./");
5780 return NT_STATUS_NO_MEMORY;
5783 /* Append the new name. */
5784 base_name = talloc_asprintf_append(base_name,
5788 return NT_STATUS_NO_MEMORY;
5791 status = unix_convert(ctx, conn, base_name, &smb_fname,
5794 /* If an error we expect this to be
5795 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5797 if (!NT_STATUS_IS_OK(status)) {
5798 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5802 /* Create an smb_fname to call rename_internals_fsp() */
5803 status = create_synthetic_smb_fname(talloc_tos(),
5806 if (!NT_STATUS_IS_OK(status)) {
5814 DEBUG(10,("smb_file_rename_information: "
5815 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5816 fsp->fnum, fsp_str_dbg(fsp), base_name));
5817 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5820 DEBUG(10,("smb_file_rename_information: "
5821 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5823 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5824 overwrite, False, dest_has_wcard,
5825 FILE_WRITE_ATTRIBUTES);
5828 TALLOC_FREE(smb_fname);
5832 /****************************************************************************
5833 Deal with SMB_SET_POSIX_ACL.
5834 ****************************************************************************/
5836 #if defined(HAVE_POSIX_ACLS)
5837 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5842 SMB_STRUCT_STAT *psbuf)
5844 uint16 posix_acl_version;
5845 uint16 num_file_acls;
5846 uint16 num_def_acls;
5847 bool valid_file_acls = True;
5848 bool valid_def_acls = True;
5850 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5851 return NT_STATUS_INVALID_PARAMETER;
5853 posix_acl_version = SVAL(pdata,0);
5854 num_file_acls = SVAL(pdata,2);
5855 num_def_acls = SVAL(pdata,4);
5857 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5858 valid_file_acls = False;
5862 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5863 valid_def_acls = False;
5867 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5868 return NT_STATUS_INVALID_PARAMETER;
5871 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5872 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5873 return NT_STATUS_INVALID_PARAMETER;
5876 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5877 fname ? fname : fsp_str_dbg(fsp),
5878 (unsigned int)num_file_acls,
5879 (unsigned int)num_def_acls));
5881 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5882 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5883 return map_nt_error_from_unix(errno);
5886 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5887 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5888 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5889 return map_nt_error_from_unix(errno);
5891 return NT_STATUS_OK;
5895 /****************************************************************************
5896 Deal with SMB_SET_POSIX_LOCK.
5897 ****************************************************************************/
5899 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5900 struct smb_request *req,
5908 bool blocking_lock = False;
5909 enum brl_type lock_type;
5911 NTSTATUS status = NT_STATUS_OK;
5913 if (fsp == NULL || fsp->fh->fd == -1) {
5914 return NT_STATUS_INVALID_HANDLE;
5917 if (total_data != POSIX_LOCK_DATA_SIZE) {
5918 return NT_STATUS_INVALID_PARAMETER;
5921 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5922 case POSIX_LOCK_TYPE_READ:
5923 lock_type = READ_LOCK;
5925 case POSIX_LOCK_TYPE_WRITE:
5926 /* Return the right POSIX-mappable error code for files opened read-only. */
5927 if (!fsp->can_write) {
5928 return NT_STATUS_INVALID_HANDLE;
5930 lock_type = WRITE_LOCK;
5932 case POSIX_LOCK_TYPE_UNLOCK:
5933 lock_type = UNLOCK_LOCK;
5936 return NT_STATUS_INVALID_PARAMETER;
5939 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5940 blocking_lock = False;
5941 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5942 blocking_lock = True;
5944 return NT_STATUS_INVALID_PARAMETER;
5947 if (!lp_blocking_locks(SNUM(conn))) {
5948 blocking_lock = False;
5951 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5952 #if defined(HAVE_LONGLONG)
5953 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5954 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5955 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5956 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5957 #else /* HAVE_LONGLONG */
5958 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5959 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5960 #endif /* HAVE_LONGLONG */
5962 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5963 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5965 (unsigned int)lock_type,
5966 (unsigned int)lock_pid,
5970 if (lock_type == UNLOCK_LOCK) {
5971 status = do_unlock(smbd_messaging_context(),
5978 uint32 block_smbpid;
5980 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5992 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5994 * A blocking lock was requested. Package up
5995 * this smb into a queued request and push it
5996 * onto the blocking lock queue.
5998 if(push_blocking_lock_request(br_lck,
6001 -1, /* infinite timeout. */
6009 TALLOC_FREE(br_lck);
6013 TALLOC_FREE(br_lck);
6019 /****************************************************************************
6020 Deal with SMB_INFO_STANDARD.
6021 ****************************************************************************/
6023 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6027 const struct smb_filename *smb_fname)
6029 struct smb_file_time ft;
6032 if (total_data < 12) {
6033 return NT_STATUS_INVALID_PARAMETER;
6037 ft.create_time = interpret_long_date(pdata);
6040 ft.atime = interpret_long_date(pdata + 8);
6043 ft.mtime = interpret_long_date(pdata + 16);
6045 DEBUG(10,("smb_set_info_standard: file %s\n",
6046 smb_fname_str_dbg(smb_fname)));
6048 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
6051 /****************************************************************************
6052 Deal with SMB_SET_FILE_BASIC_INFO.
6053 ****************************************************************************/
6055 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6059 const struct smb_filename *smb_fname)
6061 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6062 struct timespec write_time;
6063 struct timespec changed_time;
6064 struct smb_file_time ft;
6066 NTSTATUS status = NT_STATUS_OK;
6067 bool setting_write_time = true;
6071 if (total_data < 36) {
6072 return NT_STATUS_INVALID_PARAMETER;
6075 /* Set the attributes */
6076 dosmode = IVAL(pdata,32);
6077 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6078 if (!NT_STATUS_IS_OK(status)) {
6083 ft.atime = interpret_long_date(pdata+8);
6085 write_time = interpret_long_date(pdata+16);
6086 changed_time = interpret_long_date(pdata+24);
6089 ft.mtime = timespec_min(&write_time, &changed_time);
6092 ft.create_time = interpret_long_date(pdata);
6094 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
6095 !null_timespec(write_time)) {
6096 ft.mtime = write_time;
6099 /* Prefer a defined time to an undefined one. */
6100 if (null_timespec(ft.mtime)) {
6101 if (null_timespec(write_time)) {
6102 ft.mtime = changed_time;
6103 setting_write_time = false;
6105 ft.mtime = write_time;
6109 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6110 smb_fname_str_dbg(smb_fname)));
6112 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6113 setting_write_time);
6116 /****************************************************************************
6117 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6118 ****************************************************************************/
6120 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6121 struct smb_request *req,
6125 struct smb_filename *smb_fname)
6127 uint64_t allocation_size = 0;
6128 NTSTATUS status = NT_STATUS_OK;
6129 files_struct *new_fsp = NULL;
6131 if (!VALID_STAT(smb_fname->st)) {
6132 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6135 if (total_data < 8) {
6136 return NT_STATUS_INVALID_PARAMETER;
6139 allocation_size = (uint64_t)IVAL(pdata,0);
6140 #ifdef LARGE_SMB_OFF_T
6141 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6142 #else /* LARGE_SMB_OFF_T */
6143 if (IVAL(pdata,4) != 0) {
6144 /* more than 32 bits? */
6145 return NT_STATUS_INVALID_PARAMETER;
6147 #endif /* LARGE_SMB_OFF_T */
6149 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6150 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6151 (double)allocation_size));
6153 if (allocation_size) {
6154 allocation_size = smb_roundup(conn, allocation_size);
6157 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6158 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6159 (double)allocation_size));
6161 if (fsp && fsp->fh->fd != -1) {
6162 /* Open file handle. */
6163 /* Only change if needed. */
6164 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6165 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6166 return map_nt_error_from_unix(errno);
6169 /* But always update the time. */
6171 * This is equivalent to a write. Ensure it's seen immediately
6172 * if there are no pending writes.
6174 trigger_write_time_update_immediate(fsp);
6175 return NT_STATUS_OK;
6178 /* Pathname or stat or directory file. */
6179 status = SMB_VFS_CREATE_FILE(
6182 0, /* root_dir_fid */
6183 smb_fname, /* fname */
6184 FILE_WRITE_DATA, /* access_mask */
6185 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6187 FILE_OPEN, /* create_disposition*/
6188 0, /* create_options */
6189 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6190 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6191 0, /* allocation_size */
6194 &new_fsp, /* result */
6197 if (!NT_STATUS_IS_OK(status)) {
6198 /* NB. We check for open_was_deferred in the caller. */
6202 /* Only change if needed. */
6203 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6204 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6205 status = map_nt_error_from_unix(errno);
6206 close_file(req, new_fsp, NORMAL_CLOSE);
6211 /* Changing the allocation size should set the last mod time. */
6213 * This is equivalent to a write. Ensure it's seen immediately
6214 * if there are no pending writes.
6216 trigger_write_time_update_immediate(new_fsp);
6218 close_file(req, new_fsp, NORMAL_CLOSE);
6219 return NT_STATUS_OK;
6222 /****************************************************************************
6223 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6224 ****************************************************************************/
6226 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6227 struct smb_request *req,
6231 const struct smb_filename *smb_fname)
6235 if (total_data < 8) {
6236 return NT_STATUS_INVALID_PARAMETER;
6239 size = IVAL(pdata,0);
6240 #ifdef LARGE_SMB_OFF_T
6241 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6242 #else /* LARGE_SMB_OFF_T */
6243 if (IVAL(pdata,4) != 0) {
6244 /* more than 32 bits? */
6245 return NT_STATUS_INVALID_PARAMETER;
6247 #endif /* LARGE_SMB_OFF_T */
6248 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6249 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6252 return smb_set_file_size(conn, req,
6259 /****************************************************************************
6260 Allow a UNIX info mknod.
6261 ****************************************************************************/
6263 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6266 const struct smb_filename *smb_fname)
6268 uint32 file_type = IVAL(pdata,56);
6269 #if defined(HAVE_MAKEDEV)
6270 uint32 dev_major = IVAL(pdata,60);
6271 uint32 dev_minor = IVAL(pdata,68);
6273 SMB_DEV_T dev = (SMB_DEV_T)0;
6274 uint32 raw_unixmode = IVAL(pdata,84);
6278 if (total_data < 100) {
6279 return NT_STATUS_INVALID_PARAMETER;
6282 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6283 PERM_NEW_FILE, &unixmode);
6284 if (!NT_STATUS_IS_OK(status)) {
6288 #if defined(HAVE_MAKEDEV)
6289 dev = makedev(dev_major, dev_minor);
6292 switch (file_type) {
6293 #if defined(S_IFIFO)
6294 case UNIX_TYPE_FIFO:
6295 unixmode |= S_IFIFO;
6298 #if defined(S_IFSOCK)
6299 case UNIX_TYPE_SOCKET:
6300 unixmode |= S_IFSOCK;
6303 #if defined(S_IFCHR)
6304 case UNIX_TYPE_CHARDEV:
6305 unixmode |= S_IFCHR;
6308 #if defined(S_IFBLK)
6309 case UNIX_TYPE_BLKDEV:
6310 unixmode |= S_IFBLK;
6314 return NT_STATUS_INVALID_PARAMETER;
6317 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6318 "%.0f mode 0%o for file %s\n", (double)dev,
6319 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6321 /* Ok - do the mknod. */
6322 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6323 return map_nt_error_from_unix(errno);
6326 /* If any of the other "set" calls fail we
6327 * don't want to end up with a half-constructed mknod.
6330 if (lp_inherit_perms(SNUM(conn))) {
6332 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6334 return NT_STATUS_NO_MEMORY;
6336 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6338 TALLOC_FREE(parent);
6341 return NT_STATUS_OK;
6344 /****************************************************************************
6345 Deal with SMB_SET_FILE_UNIX_BASIC.
6346 ****************************************************************************/
6348 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6349 struct smb_request *req,
6353 const struct smb_filename *smb_fname)
6355 struct smb_file_time ft;
6356 uint32 raw_unixmode;
6359 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6360 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6361 NTSTATUS status = NT_STATUS_OK;
6362 bool delete_on_fail = False;
6363 enum perm_type ptype;
6364 files_struct *all_fsps = NULL;
6365 bool modify_mtime = true;
6367 SMB_STRUCT_STAT sbuf;
6371 if (total_data < 100) {
6372 return NT_STATUS_INVALID_PARAMETER;
6375 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6376 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6377 size=IVAL(pdata,0); /* first 8 Bytes are size */
6378 #ifdef LARGE_SMB_OFF_T
6379 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6380 #else /* LARGE_SMB_OFF_T */
6381 if (IVAL(pdata,4) != 0) {
6382 /* more than 32 bits? */
6383 return NT_STATUS_INVALID_PARAMETER;
6385 #endif /* LARGE_SMB_OFF_T */
6388 ft.atime = interpret_long_date(pdata+24); /* access_time */
6389 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6390 set_owner = (uid_t)IVAL(pdata,40);
6391 set_grp = (gid_t)IVAL(pdata,48);
6392 raw_unixmode = IVAL(pdata,84);
6394 if (VALID_STAT(smb_fname->st)) {
6395 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6396 ptype = PERM_EXISTING_DIR;
6398 ptype = PERM_EXISTING_FILE;
6401 ptype = PERM_NEW_FILE;
6404 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6406 if (!NT_STATUS_IS_OK(status)) {
6410 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6411 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6412 smb_fname_str_dbg(smb_fname), (double)size,
6413 (unsigned int)set_owner, (unsigned int)set_grp,
6414 (int)raw_unixmode));
6416 sbuf = smb_fname->st;
6418 if (!VALID_STAT(sbuf)) {
6419 struct smb_filename *smb_fname_tmp = NULL;
6421 * The only valid use of this is to create character and block
6422 * devices, and named pipes. This is deprecated (IMHO) and
6423 * a new info level should be used for mknod. JRA.
6426 status = smb_unix_mknod(conn,
6430 if (!NT_STATUS_IS_OK(status)) {
6434 status = copy_smb_filename(talloc_tos(), smb_fname,
6436 if (!NT_STATUS_IS_OK(status)) {
6440 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6441 status = map_nt_error_from_unix(errno);
6442 TALLOC_FREE(smb_fname_tmp);
6443 SMB_VFS_UNLINK(conn, smb_fname);
6447 sbuf = smb_fname_tmp->st;
6448 TALLOC_FREE(smb_fname_tmp);
6450 /* Ensure we don't try and change anything else. */
6451 raw_unixmode = SMB_MODE_NO_CHANGE;
6452 size = get_file_size_stat(&sbuf);
6453 ft.atime = sbuf.st_ex_atime;
6454 ft.mtime = sbuf.st_ex_mtime;
6456 * We continue here as we might want to change the
6459 delete_on_fail = True;
6463 /* Horrible backwards compatibility hack as an old server bug
6464 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6468 size = get_file_size_stat(&sbuf);
6473 * Deal with the UNIX specific mode set.
6476 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6477 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6478 "setting mode 0%o for file %s\n",
6479 (unsigned int)unixmode,
6480 smb_fname_str_dbg(smb_fname)));
6481 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6482 return map_nt_error_from_unix(errno);
6487 * Deal with the UNIX specific uid set.
6490 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6491 (sbuf.st_ex_uid != set_owner)) {
6494 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6495 "changing owner %u for path %s\n",
6496 (unsigned int)set_owner,
6497 smb_fname_str_dbg(smb_fname)));
6499 if (S_ISLNK(sbuf.st_ex_mode)) {
6500 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6501 set_owner, (gid_t)-1);
6503 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6504 set_owner, (gid_t)-1);
6508 status = map_nt_error_from_unix(errno);
6509 if (delete_on_fail) {
6510 SMB_VFS_UNLINK(conn, smb_fname);
6517 * Deal with the UNIX specific gid set.
6520 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6521 (sbuf.st_ex_gid != set_grp)) {
6522 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6523 "changing group %u for file %s\n",
6524 (unsigned int)set_owner,
6525 smb_fname_str_dbg(smb_fname)));
6526 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6528 status = map_nt_error_from_unix(errno);
6529 if (delete_on_fail) {
6530 SMB_VFS_UNLINK(conn, smb_fname);
6536 /* Deal with any size changes. */
6538 status = smb_set_file_size(conn, req,
6543 if (!NT_STATUS_IS_OK(status)) {
6547 /* Deal with any time changes. */
6548 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6549 /* No change, don't cancel anything. */
6553 id = vfs_file_id_from_sbuf(conn, &sbuf);
6554 for(all_fsps = file_find_di_first(id); all_fsps;
6555 all_fsps = file_find_di_next(all_fsps)) {
6557 * We're setting the time explicitly for UNIX.
6558 * Cancel any pending changes over all handles.
6560 all_fsps->update_write_time_on_close = false;
6561 TALLOC_FREE(all_fsps->update_write_time_event);
6565 * Override the "setting_write_time"
6566 * parameter here as it almost does what
6567 * we need. Just remember if we modified
6568 * mtime and send the notify ourselves.
6570 if (null_timespec(ft.mtime)) {
6571 modify_mtime = false;
6574 status = smb_set_file_time(conn,
6580 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6581 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6586 /****************************************************************************
6587 Deal with SMB_SET_FILE_UNIX_INFO2.
6588 ****************************************************************************/
6590 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6591 struct smb_request *req,
6595 const struct smb_filename *smb_fname)
6601 if (total_data < 116) {
6602 return NT_STATUS_INVALID_PARAMETER;
6605 /* Start by setting all the fields that are common between UNIX_BASIC
6608 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6610 if (!NT_STATUS_IS_OK(status)) {
6614 smb_fflags = IVAL(pdata, 108);
6615 smb_fmask = IVAL(pdata, 112);
6617 /* NB: We should only attempt to alter the file flags if the client
6618 * sends a non-zero mask.
6620 if (smb_fmask != 0) {
6621 int stat_fflags = 0;
6623 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6624 smb_fmask, &stat_fflags)) {
6625 /* Client asked to alter a flag we don't understand. */
6626 return NT_STATUS_INVALID_PARAMETER;
6629 if (fsp && fsp->fh->fd != -1) {
6630 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6631 return NT_STATUS_NOT_SUPPORTED;
6633 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6634 stat_fflags) != 0) {
6635 return map_nt_error_from_unix(errno);
6640 /* XXX: need to add support for changing the create_time here. You
6641 * can do this for paths on Darwin with setattrlist(2). The right way
6642 * to hook this up is probably by extending the VFS utimes interface.
6645 return NT_STATUS_OK;
6648 /****************************************************************************
6649 Create a directory with POSIX semantics.
6650 ****************************************************************************/
6652 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6653 struct smb_request *req,
6657 SMB_STRUCT_STAT *psbuf,
6658 int *pdata_return_size)
6660 struct smb_filename *smb_fname;
6661 NTSTATUS status = NT_STATUS_OK;
6662 uint32 raw_unixmode = 0;
6663 uint32 mod_unixmode = 0;
6664 mode_t unixmode = (mode_t)0;
6665 files_struct *fsp = NULL;
6666 uint16 info_level_return = 0;
6668 char *pdata = *ppdata;
6670 if (total_data < 18) {
6671 return NT_STATUS_INVALID_PARAMETER;
6674 raw_unixmode = IVAL(pdata,8);
6675 /* Next 4 bytes are not yet defined. */
6677 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6678 if (!NT_STATUS_IS_OK(status)) {
6682 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6684 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6685 fname, (unsigned int)unixmode ));
6687 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6689 if (!NT_STATUS_IS_OK(status)) {
6693 status = SMB_VFS_CREATE_FILE(
6696 0, /* root_dir_fid */
6697 smb_fname, /* fname */
6698 FILE_READ_ATTRIBUTES, /* access_mask */
6699 FILE_SHARE_NONE, /* share_access */
6700 FILE_CREATE, /* create_disposition*/
6701 FILE_DIRECTORY_FILE, /* create_options */
6702 mod_unixmode, /* file_attributes */
6703 0, /* oplock_request */
6704 0, /* allocation_size */
6710 *psbuf = smb_fname->st;
6711 TALLOC_FREE(smb_fname);
6713 if (NT_STATUS_IS_OK(status)) {
6714 close_file(req, fsp, NORMAL_CLOSE);
6717 info_level_return = SVAL(pdata,16);
6719 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6720 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6721 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6722 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6724 *pdata_return_size = 12;
6727 /* Realloc the data size */
6728 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6729 if (*ppdata == NULL) {
6730 *pdata_return_size = 0;
6731 return NT_STATUS_NO_MEMORY;
6735 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6736 SSVAL(pdata,2,0); /* No fnum. */
6737 SIVAL(pdata,4,info); /* Was directory created. */
6739 switch (info_level_return) {
6740 case SMB_QUERY_FILE_UNIX_BASIC:
6741 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6742 SSVAL(pdata,10,0); /* Padding. */
6743 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6745 case SMB_QUERY_FILE_UNIX_INFO2:
6746 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6747 SSVAL(pdata,10,0); /* Padding. */
6748 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6751 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6752 SSVAL(pdata,10,0); /* Padding. */
6759 /****************************************************************************
6760 Open/Create a file with POSIX semantics.
6761 ****************************************************************************/
6763 static NTSTATUS smb_posix_open(connection_struct *conn,
6764 struct smb_request *req,
6768 SMB_STRUCT_STAT *psbuf,
6769 int *pdata_return_size)
6771 struct smb_filename *smb_fname = NULL;
6772 bool extended_oplock_granted = False;
6773 char *pdata = *ppdata;
6775 uint32 wire_open_mode = 0;
6776 uint32 raw_unixmode = 0;
6777 uint32 mod_unixmode = 0;
6778 uint32 create_disp = 0;
6779 uint32 access_mask = 0;
6780 uint32 create_options = 0;
6781 NTSTATUS status = NT_STATUS_OK;
6782 mode_t unixmode = (mode_t)0;
6783 files_struct *fsp = NULL;
6784 int oplock_request = 0;
6786 uint16 info_level_return = 0;
6788 if (total_data < 18) {
6789 return NT_STATUS_INVALID_PARAMETER;
6792 flags = IVAL(pdata,0);
6793 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6794 if (oplock_request) {
6795 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6798 wire_open_mode = IVAL(pdata,4);
6800 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6801 return smb_posix_mkdir(conn, req,
6809 switch (wire_open_mode & SMB_ACCMODE) {
6811 access_mask = FILE_READ_DATA;
6814 access_mask = FILE_WRITE_DATA;
6817 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6820 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6821 (unsigned int)wire_open_mode ));
6822 return NT_STATUS_INVALID_PARAMETER;
6825 wire_open_mode &= ~SMB_ACCMODE;
6827 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6828 create_disp = FILE_CREATE;
6829 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6830 create_disp = FILE_OVERWRITE_IF;
6831 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6832 create_disp = FILE_OPEN_IF;
6833 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6834 create_disp = FILE_OPEN;
6836 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6837 (unsigned int)wire_open_mode ));
6838 return NT_STATUS_INVALID_PARAMETER;
6841 raw_unixmode = IVAL(pdata,8);
6842 /* Next 4 bytes are not yet defined. */
6844 status = unix_perms_from_wire(conn,
6847 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6850 if (!NT_STATUS_IS_OK(status)) {
6854 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6856 if (wire_open_mode & SMB_O_SYNC) {
6857 create_options |= FILE_WRITE_THROUGH;
6859 if (wire_open_mode & SMB_O_APPEND) {
6860 access_mask |= FILE_APPEND_DATA;
6862 if (wire_open_mode & SMB_O_DIRECT) {
6863 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6866 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6868 (unsigned int)wire_open_mode,
6869 (unsigned int)unixmode ));
6871 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6873 if (!NT_STATUS_IS_OK(status)) {
6877 status = SMB_VFS_CREATE_FILE(
6880 0, /* root_dir_fid */
6881 smb_fname, /* fname */
6882 access_mask, /* access_mask */
6883 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6885 create_disp, /* create_disposition*/
6886 FILE_NON_DIRECTORY_FILE, /* create_options */
6887 mod_unixmode, /* file_attributes */
6888 oplock_request, /* oplock_request */
6889 0, /* allocation_size */
6895 *psbuf = smb_fname->st;
6896 TALLOC_FREE(smb_fname);
6898 if (!NT_STATUS_IS_OK(status)) {
6902 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6903 extended_oplock_granted = True;
6906 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6907 extended_oplock_granted = True;
6910 info_level_return = SVAL(pdata,16);
6912 /* Allocate the correct return size. */
6914 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6915 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6916 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6917 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6919 *pdata_return_size = 12;
6922 /* Realloc the data size */
6923 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6924 if (*ppdata == NULL) {
6925 close_file(req, fsp, ERROR_CLOSE);
6926 *pdata_return_size = 0;
6927 return NT_STATUS_NO_MEMORY;
6931 if (extended_oplock_granted) {
6932 if (flags & REQUEST_BATCH_OPLOCK) {
6933 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6935 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6937 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6938 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6940 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6943 SSVAL(pdata,2,fsp->fnum);
6944 SIVAL(pdata,4,info); /* Was file created etc. */
6946 switch (info_level_return) {
6947 case SMB_QUERY_FILE_UNIX_BASIC:
6948 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6949 SSVAL(pdata,10,0); /* padding. */
6950 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6952 case SMB_QUERY_FILE_UNIX_INFO2:
6953 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6954 SSVAL(pdata,10,0); /* padding. */
6955 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6958 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6959 SSVAL(pdata,10,0); /* padding. */
6962 return NT_STATUS_OK;
6965 /****************************************************************************
6966 Delete a file with POSIX semantics.
6967 ****************************************************************************/
6969 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6970 struct smb_request *req,
6973 struct smb_filename *smb_fname)
6975 NTSTATUS status = NT_STATUS_OK;
6976 files_struct *fsp = NULL;
6980 int create_options = 0;
6982 struct share_mode_lock *lck = NULL;
6984 if (total_data < 2) {
6985 return NT_STATUS_INVALID_PARAMETER;
6988 flags = SVAL(pdata,0);
6990 if (!VALID_STAT(smb_fname->st)) {
6991 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6994 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6995 !VALID_STAT_OF_DIR(smb_fname->st)) {
6996 return NT_STATUS_NOT_A_DIRECTORY;
6999 DEBUG(10,("smb_posix_unlink: %s %s\n",
7000 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7001 smb_fname_str_dbg(smb_fname)));
7003 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7004 create_options |= FILE_DIRECTORY_FILE;
7007 status = SMB_VFS_CREATE_FILE(
7010 0, /* root_dir_fid */
7011 smb_fname, /* fname */
7012 DELETE_ACCESS, /* access_mask */
7013 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7015 FILE_OPEN, /* create_disposition*/
7016 create_options, /* create_options */
7017 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7018 0, /* oplock_request */
7019 0, /* allocation_size */
7025 if (!NT_STATUS_IS_OK(status)) {
7030 * Don't lie to client. If we can't really delete due to
7031 * non-POSIX opens return SHARING_VIOLATION.
7034 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7037 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7038 "lock for file %s\n", fsp_str_dbg(fsp)));
7039 close_file(req, fsp, NORMAL_CLOSE);
7040 return NT_STATUS_INVALID_PARAMETER;
7044 * See if others still have the file open. If this is the case, then
7045 * don't delete. If all opens are POSIX delete we can set the delete
7046 * on close disposition.
7048 for (i=0; i<lck->num_share_modes; i++) {
7049 struct share_mode_entry *e = &lck->share_modes[i];
7050 if (is_valid_share_mode_entry(e)) {
7051 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7054 /* Fail with sharing violation. */
7055 close_file(req, fsp, NORMAL_CLOSE);
7057 return NT_STATUS_SHARING_VIOLATION;
7062 * Set the delete on close.
7064 status = smb_set_file_disposition_info(conn,
7070 if (!NT_STATUS_IS_OK(status)) {
7071 close_file(req, fsp, NORMAL_CLOSE);
7076 return close_file(req, fsp, NORMAL_CLOSE);
7079 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7080 struct smb_request *req,
7081 TALLOC_CTX *mem_ctx,
7082 uint16_t info_level,
7084 struct smb_filename *smb_fname,
7085 char **ppdata, int total_data,
7088 char *pdata = *ppdata;
7089 SMB_STRUCT_STAT sbuf;
7091 NTSTATUS status = NT_STATUS_OK;
7092 int data_return_size = 0;
7096 /* Set sbuf for use below. */
7097 sbuf = smb_fname->st;
7099 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7100 return NT_STATUS_INVALID_LEVEL;
7103 if (!CAN_WRITE(conn)) {
7104 /* Allow POSIX opens. The open path will deny
7105 * any non-readonly opens. */
7106 if (info_level != SMB_POSIX_PATH_OPEN) {
7107 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7111 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
7112 if (!NT_STATUS_IS_OK(status)) {
7116 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d totdata=%d\n",
7117 fname, fsp ? fsp->fnum : -1, info_level, total_data));
7119 switch (info_level) {
7121 case SMB_INFO_STANDARD:
7123 status = smb_set_info_standard(conn,
7131 case SMB_INFO_SET_EA:
7133 status = smb_info_set_ea(conn,
7141 case SMB_SET_FILE_BASIC_INFO:
7142 case SMB_FILE_BASIC_INFORMATION:
7144 status = smb_set_file_basic_info(conn,
7152 case SMB_FILE_ALLOCATION_INFORMATION:
7153 case SMB_SET_FILE_ALLOCATION_INFO:
7155 status = smb_set_file_allocation_info(conn, req,
7163 case SMB_FILE_END_OF_FILE_INFORMATION:
7164 case SMB_SET_FILE_END_OF_FILE_INFO:
7166 status = smb_set_file_end_of_file_info(conn, req,
7174 case SMB_FILE_DISPOSITION_INFORMATION:
7175 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7178 /* JRA - We used to just ignore this on a path ?
7179 * Shouldn't this be invalid level on a pathname
7182 if (tran_call != TRANSACT2_SETFILEINFO) {
7183 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7186 status = smb_set_file_disposition_info(conn,
7194 case SMB_FILE_POSITION_INFORMATION:
7196 status = smb_file_position_information(conn,
7203 /* From tridge Samba4 :
7204 * MODE_INFORMATION in setfileinfo (I have no
7205 * idea what "mode information" on a file is - it takes a value of 0,
7206 * 2, 4 or 6. What could it be?).
7209 case SMB_FILE_MODE_INFORMATION:
7211 status = smb_file_mode_information(conn,
7218 * CIFS UNIX extensions.
7221 case SMB_SET_FILE_UNIX_BASIC:
7223 status = smb_set_file_unix_basic(conn, req,
7231 case SMB_SET_FILE_UNIX_INFO2:
7233 status = smb_set_file_unix_info2(conn, req,
7241 case SMB_SET_FILE_UNIX_LINK:
7244 /* We must have a pathname for this. */
7245 return NT_STATUS_INVALID_LEVEL;
7247 status = smb_set_file_unix_link(conn, req, pdata,
7252 case SMB_SET_FILE_UNIX_HLINK:
7255 /* We must have a pathname for this. */
7256 return NT_STATUS_INVALID_LEVEL;
7258 status = smb_set_file_unix_hlink(conn, req,
7264 case SMB_FILE_RENAME_INFORMATION:
7266 status = smb_file_rename_information(conn, req,
7272 #if defined(HAVE_POSIX_ACLS)
7273 case SMB_SET_POSIX_ACL:
7275 status = smb_set_posix_acl(conn,
7285 case SMB_SET_POSIX_LOCK:
7288 return NT_STATUS_INVALID_LEVEL;
7290 status = smb_set_posix_lock(conn, req,
7291 pdata, total_data, fsp);
7295 case SMB_POSIX_PATH_OPEN:
7298 /* We must have a pathname for this. */
7299 return NT_STATUS_INVALID_LEVEL;
7302 status = smb_posix_open(conn, req,
7311 case SMB_POSIX_PATH_UNLINK:
7314 /* We must have a pathname for this. */
7315 return NT_STATUS_INVALID_LEVEL;
7318 status = smb_posix_unlink(conn, req,
7326 return NT_STATUS_INVALID_LEVEL;
7329 if (!NT_STATUS_IS_OK(status)) {
7333 *ret_data_size = data_return_size;
7334 return NT_STATUS_OK;
7337 /****************************************************************************
7338 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7339 ****************************************************************************/
7341 static void call_trans2setfilepathinfo(connection_struct *conn,
7342 struct smb_request *req,
7343 unsigned int tran_call,
7344 char **pparams, int total_params,
7345 char **ppdata, int total_data,
7346 unsigned int max_data_bytes)
7348 char *params = *pparams;
7349 char *pdata = *ppdata;
7351 struct smb_filename *smb_fname = NULL;
7352 files_struct *fsp = NULL;
7353 NTSTATUS status = NT_STATUS_OK;
7354 int data_return_size = 0;
7357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7361 if (tran_call == TRANSACT2_SETFILEINFO) {
7362 if (total_params < 4) {
7363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7367 fsp = file_fsp(req, SVAL(params,0));
7368 /* Basic check for non-null fsp. */
7369 if (!check_fsp_open(conn, req, fsp)) {
7372 info_level = SVAL(params,2);
7374 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7376 if (!NT_STATUS_IS_OK(status)) {
7377 reply_nterror(req, status);
7381 if(fsp->is_directory || fsp->fh->fd == -1) {
7383 * This is actually a SETFILEINFO on a directory
7384 * handle (returned from an NT SMB). NT5.0 seems
7385 * to do this call. JRA.
7387 if (INFO_LEVEL_IS_UNIX(info_level)) {
7388 /* Always do lstat for UNIX calls. */
7389 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7390 DEBUG(3,("call_trans2setfilepathinfo: "
7391 "SMB_VFS_LSTAT of %s failed "
7393 smb_fname_str_dbg(smb_fname),
7395 reply_nterror(req, map_nt_error_from_unix(errno));
7399 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7400 DEBUG(3,("call_trans2setfilepathinfo: "
7401 "fileinfo of %s failed (%s)\n",
7402 smb_fname_str_dbg(smb_fname),
7404 reply_nterror(req, map_nt_error_from_unix(errno));
7408 } else if (fsp->print_file) {
7410 * Doing a DELETE_ON_CLOSE should cancel a print job.
7412 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7413 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7415 DEBUG(3,("call_trans2setfilepathinfo: "
7416 "Cancelling print job (%s)\n",
7420 send_trans2_replies(conn, req, params, 2,
7425 reply_doserror(req, ERRDOS, ERRbadpath);
7430 * Original code - this is an open file.
7432 if (!check_fsp(conn, req, fsp)) {
7436 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7437 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7438 "of fnum %d failed (%s)\n", fsp->fnum,
7440 reply_nterror(req, map_nt_error_from_unix(errno));
7448 if (total_params < 7) {
7449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7453 info_level = SVAL(params,0);
7454 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7455 total_params - 6, STR_TERMINATE,
7457 if (!NT_STATUS_IS_OK(status)) {
7458 reply_nterror(req, status);
7462 status = filename_convert(req, conn,
7463 req->flags2 & FLAGS2_DFS_PATHNAMES,
7466 if (!NT_STATUS_IS_OK(status)) {
7467 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7468 reply_botherror(req,
7469 NT_STATUS_PATH_NOT_COVERED,
7470 ERRSRV, ERRbadpath);
7473 reply_nterror(req, status);
7477 if (INFO_LEVEL_IS_UNIX(info_level)) {
7479 * For CIFS UNIX extensions the target name may not exist.
7482 /* Always do lstat for UNIX calls. */
7483 SMB_VFS_LSTAT(conn, smb_fname);
7485 } else if (!VALID_STAT(smb_fname->st) &&
7486 SMB_VFS_STAT(conn, smb_fname)) {
7487 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7489 smb_fname_str_dbg(smb_fname),
7491 reply_nterror(req, map_nt_error_from_unix(errno));
7496 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7497 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7498 fsp ? fsp->fnum : -1, info_level,total_data));
7500 /* Realloc the parameter size */
7501 *pparams = (char *)SMB_REALLOC(*pparams,2);
7502 if (*pparams == NULL) {
7503 reply_nterror(req, NT_STATUS_NO_MEMORY);
7510 status = smbd_do_setfilepathinfo(conn, req, req,
7516 if (!NT_STATUS_IS_OK(status)) {
7517 if (open_was_deferred(req->mid)) {
7518 /* We have re-scheduled this call. */
7521 if (blocking_lock_was_deferred(req->mid)) {
7522 /* We have re-scheduled this call. */
7525 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7526 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7527 ERRSRV, ERRbadpath);
7530 if (info_level == SMB_POSIX_PATH_OPEN) {
7531 reply_openerror(req, status);
7535 reply_nterror(req, status);
7539 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7545 /****************************************************************************
7546 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7547 ****************************************************************************/
7549 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7550 char **pparams, int total_params,
7551 char **ppdata, int total_data,
7552 unsigned int max_data_bytes)
7554 struct smb_filename *smb_dname = NULL;
7555 char *params = *pparams;
7556 char *pdata = *ppdata;
7557 char *directory = NULL;
7558 NTSTATUS status = NT_STATUS_OK;
7559 struct ea_list *ea_list = NULL;
7560 TALLOC_CTX *ctx = talloc_tos();
7562 if (!CAN_WRITE(conn)) {
7563 reply_doserror(req, ERRSRV, ERRaccess);
7567 if (total_params < 5) {
7568 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7572 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7573 total_params - 4, STR_TERMINATE,
7575 if (!NT_STATUS_IS_OK(status)) {
7576 reply_nterror(req, status);
7580 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7582 status = filename_convert(ctx,
7584 req->flags2 & FLAGS2_DFS_PATHNAMES,
7588 if (!NT_STATUS_IS_OK(status)) {
7589 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7590 reply_botherror(req,
7591 NT_STATUS_PATH_NOT_COVERED,
7592 ERRSRV, ERRbadpath);
7595 reply_nterror(req, status);
7599 /* Any data in this call is an EA list. */
7600 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7601 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7606 * OS/2 workplace shell seems to send SET_EA requests of "null"
7607 * length (4 bytes containing IVAL 4).
7608 * They seem to have no effect. Bug #3212. JRA.
7611 if (total_data != 4) {
7612 if (total_data < 10) {
7613 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7617 if (IVAL(pdata,0) > total_data) {
7618 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7619 IVAL(pdata,0), (unsigned int)total_data));
7620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7624 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7631 /* If total_data == 4 Windows doesn't care what values
7632 * are placed in that field, it just ignores them.
7633 * The System i QNTC IBM SMB client puts bad values here,
7634 * so ignore them. */
7636 status = create_directory(conn, req, smb_dname);
7638 if (!NT_STATUS_IS_OK(status)) {
7639 reply_nterror(req, status);
7643 /* Try and set any given EA. */
7645 status = set_ea(conn, NULL, smb_dname, ea_list);
7646 if (!NT_STATUS_IS_OK(status)) {
7647 reply_nterror(req, status);
7652 /* Realloc the parameter and data sizes */
7653 *pparams = (char *)SMB_REALLOC(*pparams,2);
7654 if(*pparams == NULL) {
7655 reply_nterror(req, NT_STATUS_NO_MEMORY);
7662 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7665 TALLOC_FREE(smb_dname);
7669 /****************************************************************************
7670 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7671 We don't actually do this - we just send a null response.
7672 ****************************************************************************/
7674 static void call_trans2findnotifyfirst(connection_struct *conn,
7675 struct smb_request *req,
7676 char **pparams, int total_params,
7677 char **ppdata, int total_data,
7678 unsigned int max_data_bytes)
7680 char *params = *pparams;
7683 if (total_params < 6) {
7684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7688 info_level = SVAL(params,4);
7689 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7691 switch (info_level) {
7696 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7700 /* Realloc the parameter and data sizes */
7701 *pparams = (char *)SMB_REALLOC(*pparams,6);
7702 if (*pparams == NULL) {
7703 reply_nterror(req, NT_STATUS_NO_MEMORY);
7708 SSVAL(params,0,fnf_handle);
7709 SSVAL(params,2,0); /* No changes */
7710 SSVAL(params,4,0); /* No EA errors */
7717 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7722 /****************************************************************************
7723 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7724 changes). Currently this does nothing.
7725 ****************************************************************************/
7727 static void call_trans2findnotifynext(connection_struct *conn,
7728 struct smb_request *req,
7729 char **pparams, int total_params,
7730 char **ppdata, int total_data,
7731 unsigned int max_data_bytes)
7733 char *params = *pparams;
7735 DEBUG(3,("call_trans2findnotifynext\n"));
7737 /* Realloc the parameter and data sizes */
7738 *pparams = (char *)SMB_REALLOC(*pparams,4);
7739 if (*pparams == NULL) {
7740 reply_nterror(req, NT_STATUS_NO_MEMORY);
7745 SSVAL(params,0,0); /* No changes */
7746 SSVAL(params,2,0); /* No EA errors */
7748 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7753 /****************************************************************************
7754 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7755 ****************************************************************************/
7757 static void call_trans2getdfsreferral(connection_struct *conn,
7758 struct smb_request *req,
7759 char **pparams, int total_params,
7760 char **ppdata, int total_data,
7761 unsigned int max_data_bytes)
7763 char *params = *pparams;
7764 char *pathname = NULL;
7766 int max_referral_level;
7767 NTSTATUS status = NT_STATUS_OK;
7768 TALLOC_CTX *ctx = talloc_tos();
7770 DEBUG(10,("call_trans2getdfsreferral\n"));
7772 if (total_params < 3) {
7773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7777 max_referral_level = SVAL(params,0);
7779 if(!lp_host_msdfs()) {
7780 reply_doserror(req, ERRDOS, ERRbadfunc);
7784 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7785 total_params - 2, STR_TERMINATE);
7787 reply_nterror(req, NT_STATUS_NOT_FOUND);
7790 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7791 ppdata,&status)) < 0) {
7792 reply_nterror(req, status);
7796 SSVAL(req->inbuf, smb_flg2,
7797 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7798 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7803 #define LMCAT_SPL 0x53
7804 #define LMFUNC_GETJOBID 0x60
7806 /****************************************************************************
7807 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7808 ****************************************************************************/
7810 static void call_trans2ioctl(connection_struct *conn,
7811 struct smb_request *req,
7812 char **pparams, int total_params,
7813 char **ppdata, int total_data,
7814 unsigned int max_data_bytes)
7816 char *pdata = *ppdata;
7817 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7819 /* check for an invalid fid before proceeding */
7822 reply_doserror(req, ERRDOS, ERRbadfid);
7826 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7827 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7828 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7829 if (*ppdata == NULL) {
7830 reply_nterror(req, NT_STATUS_NO_MEMORY);
7835 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7836 CAN ACCEPT THIS IN UNICODE. JRA. */
7838 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7839 srvstr_push(pdata, req->flags2, pdata + 2,
7840 global_myname(), 15,
7841 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7842 srvstr_push(pdata, req->flags2, pdata+18,
7843 lp_servicename(SNUM(conn)), 13,
7844 STR_ASCII|STR_TERMINATE); /* Service name */
7845 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7850 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7851 reply_doserror(req, ERRSRV, ERRerror);
7854 /****************************************************************************
7855 Reply to a SMBfindclose (stop trans2 directory search).
7856 ****************************************************************************/
7858 void reply_findclose(struct smb_request *req)
7862 START_PROFILE(SMBfindclose);
7865 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7866 END_PROFILE(SMBfindclose);
7870 dptr_num = SVALS(req->vwv+0, 0);
7872 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7874 dptr_close(&dptr_num);
7876 reply_outbuf(req, 0, 0);
7878 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7880 END_PROFILE(SMBfindclose);
7884 /****************************************************************************
7885 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7886 ****************************************************************************/
7888 void reply_findnclose(struct smb_request *req)
7892 START_PROFILE(SMBfindnclose);
7895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7896 END_PROFILE(SMBfindnclose);
7900 dptr_num = SVAL(req->vwv+0, 0);
7902 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7904 /* We never give out valid handles for a
7905 findnotifyfirst - so any dptr_num is ok here.
7908 reply_outbuf(req, 0, 0);
7910 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7912 END_PROFILE(SMBfindnclose);
7916 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7917 struct trans_state *state)
7919 if (Protocol >= PROTOCOL_NT1) {
7920 req->flags2 |= 0x40; /* IS_LONG_NAME */
7921 SSVAL(req->inbuf,smb_flg2,req->flags2);
7924 if (conn->encrypt_level == Required && !req->encrypted) {
7925 if (state->call != TRANSACT2_QFSINFO &&
7926 state->call != TRANSACT2_SETFSINFO) {
7927 DEBUG(0,("handle_trans2: encryption required "
7929 (unsigned int)state->call));
7930 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7935 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7937 /* Now we must call the relevant TRANS2 function */
7938 switch(state->call) {
7939 case TRANSACT2_OPEN:
7941 START_PROFILE(Trans2_open);
7942 call_trans2open(conn, req,
7943 &state->param, state->total_param,
7944 &state->data, state->total_data,
7945 state->max_data_return);
7946 END_PROFILE(Trans2_open);
7950 case TRANSACT2_FINDFIRST:
7952 START_PROFILE(Trans2_findfirst);
7953 call_trans2findfirst(conn, req,
7954 &state->param, state->total_param,
7955 &state->data, state->total_data,
7956 state->max_data_return);
7957 END_PROFILE(Trans2_findfirst);
7961 case TRANSACT2_FINDNEXT:
7963 START_PROFILE(Trans2_findnext);
7964 call_trans2findnext(conn, req,
7965 &state->param, state->total_param,
7966 &state->data, state->total_data,
7967 state->max_data_return);
7968 END_PROFILE(Trans2_findnext);
7972 case TRANSACT2_QFSINFO:
7974 START_PROFILE(Trans2_qfsinfo);
7975 call_trans2qfsinfo(conn, req,
7976 &state->param, state->total_param,
7977 &state->data, state->total_data,
7978 state->max_data_return);
7979 END_PROFILE(Trans2_qfsinfo);
7983 case TRANSACT2_SETFSINFO:
7985 START_PROFILE(Trans2_setfsinfo);
7986 call_trans2setfsinfo(conn, req,
7987 &state->param, state->total_param,
7988 &state->data, state->total_data,
7989 state->max_data_return);
7990 END_PROFILE(Trans2_setfsinfo);
7994 case TRANSACT2_QPATHINFO:
7995 case TRANSACT2_QFILEINFO:
7997 START_PROFILE(Trans2_qpathinfo);
7998 call_trans2qfilepathinfo(conn, req, state->call,
7999 &state->param, state->total_param,
8000 &state->data, state->total_data,
8001 state->max_data_return);
8002 END_PROFILE(Trans2_qpathinfo);
8006 case TRANSACT2_SETPATHINFO:
8007 case TRANSACT2_SETFILEINFO:
8009 START_PROFILE(Trans2_setpathinfo);
8010 call_trans2setfilepathinfo(conn, req, state->call,
8011 &state->param, state->total_param,
8012 &state->data, state->total_data,
8013 state->max_data_return);
8014 END_PROFILE(Trans2_setpathinfo);
8018 case TRANSACT2_FINDNOTIFYFIRST:
8020 START_PROFILE(Trans2_findnotifyfirst);
8021 call_trans2findnotifyfirst(conn, req,
8022 &state->param, state->total_param,
8023 &state->data, state->total_data,
8024 state->max_data_return);
8025 END_PROFILE(Trans2_findnotifyfirst);
8029 case TRANSACT2_FINDNOTIFYNEXT:
8031 START_PROFILE(Trans2_findnotifynext);
8032 call_trans2findnotifynext(conn, req,
8033 &state->param, state->total_param,
8034 &state->data, state->total_data,
8035 state->max_data_return);
8036 END_PROFILE(Trans2_findnotifynext);
8040 case TRANSACT2_MKDIR:
8042 START_PROFILE(Trans2_mkdir);
8043 call_trans2mkdir(conn, req,
8044 &state->param, state->total_param,
8045 &state->data, state->total_data,
8046 state->max_data_return);
8047 END_PROFILE(Trans2_mkdir);
8051 case TRANSACT2_GET_DFS_REFERRAL:
8053 START_PROFILE(Trans2_get_dfs_referral);
8054 call_trans2getdfsreferral(conn, req,
8055 &state->param, state->total_param,
8056 &state->data, state->total_data,
8057 state->max_data_return);
8058 END_PROFILE(Trans2_get_dfs_referral);
8062 case TRANSACT2_IOCTL:
8064 START_PROFILE(Trans2_ioctl);
8065 call_trans2ioctl(conn, req,
8066 &state->param, state->total_param,
8067 &state->data, state->total_data,
8068 state->max_data_return);
8069 END_PROFILE(Trans2_ioctl);
8074 /* Error in request */
8075 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8076 reply_doserror(req, ERRSRV,ERRerror);
8080 /****************************************************************************
8081 Reply to a SMBtrans2.
8082 ****************************************************************************/
8084 void reply_trans2(struct smb_request *req)
8086 connection_struct *conn = req->conn;
8091 unsigned int tran_call;
8092 struct trans_state *state;
8095 START_PROFILE(SMBtrans2);
8097 if (req->wct < 14) {
8098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8099 END_PROFILE(SMBtrans2);
8103 dsoff = SVAL(req->vwv+12, 0);
8104 dscnt = SVAL(req->vwv+11, 0);
8105 psoff = SVAL(req->vwv+10, 0);
8106 pscnt = SVAL(req->vwv+9, 0);
8107 tran_call = SVAL(req->vwv+14, 0);
8109 result = allow_new_trans(conn->pending_trans, req->mid);
8110 if (!NT_STATUS_IS_OK(result)) {
8111 DEBUG(2, ("Got invalid trans2 request: %s\n",
8112 nt_errstr(result)));
8113 reply_nterror(req, result);
8114 END_PROFILE(SMBtrans2);
8119 switch (tran_call) {
8120 /* List the allowed trans2 calls on IPC$ */
8121 case TRANSACT2_OPEN:
8122 case TRANSACT2_GET_DFS_REFERRAL:
8123 case TRANSACT2_QFILEINFO:
8124 case TRANSACT2_QFSINFO:
8125 case TRANSACT2_SETFSINFO:
8128 reply_doserror(req, ERRSRV, ERRaccess);
8129 END_PROFILE(SMBtrans2);
8134 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8135 DEBUG(0, ("talloc failed\n"));
8136 reply_nterror(req, NT_STATUS_NO_MEMORY);
8137 END_PROFILE(SMBtrans2);
8141 state->cmd = SMBtrans2;
8143 state->mid = req->mid;
8144 state->vuid = req->vuid;
8145 state->setup_count = SVAL(req->vwv+13, 0);
8146 state->setup = NULL;
8147 state->total_param = SVAL(req->vwv+0, 0);
8148 state->param = NULL;
8149 state->total_data = SVAL(req->vwv+1, 0);
8151 state->max_param_return = SVAL(req->vwv+2, 0);
8152 state->max_data_return = SVAL(req->vwv+3, 0);
8153 state->max_setup_return = SVAL(req->vwv+4, 0);
8154 state->close_on_completion = BITSETW(req->vwv+5, 0);
8155 state->one_way = BITSETW(req->vwv+5, 1);
8157 state->call = tran_call;
8159 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8160 is so as a sanity check */
8161 if (state->setup_count != 1) {
8163 * Need to have rc=0 for ioctl to get job id for OS/2.
8164 * Network printing will fail if function is not successful.
8165 * Similar function in reply.c will be used if protocol
8166 * is LANMAN1.0 instead of LM1.2X002.
8167 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8168 * outbuf doesn't have to be set(only job id is used).
8170 if ( (state->setup_count == 4)
8171 && (tran_call == TRANSACT2_IOCTL)
8172 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8173 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8174 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8176 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8177 DEBUG(2,("Transaction is %d\n",tran_call));
8179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8180 END_PROFILE(SMBtrans2);
8185 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8188 if (state->total_data) {
8190 if (trans_oob(state->total_data, 0, dscnt)
8191 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8195 /* Can't use talloc here, the core routines do realloc on the
8196 * params and data. */
8197 state->data = (char *)SMB_MALLOC(state->total_data);
8198 if (state->data == NULL) {
8199 DEBUG(0,("reply_trans2: data malloc fail for %u "
8200 "bytes !\n", (unsigned int)state->total_data));
8202 reply_nterror(req, NT_STATUS_NO_MEMORY);
8203 END_PROFILE(SMBtrans2);
8207 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8210 if (state->total_param) {
8212 if (trans_oob(state->total_param, 0, pscnt)
8213 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8217 /* Can't use talloc here, the core routines do realloc on the
8218 * params and data. */
8219 state->param = (char *)SMB_MALLOC(state->total_param);
8220 if (state->param == NULL) {
8221 DEBUG(0,("reply_trans: param malloc fail for %u "
8222 "bytes !\n", (unsigned int)state->total_param));
8223 SAFE_FREE(state->data);
8225 reply_nterror(req, NT_STATUS_NO_MEMORY);
8226 END_PROFILE(SMBtrans2);
8230 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8233 state->received_data = dscnt;
8234 state->received_param = pscnt;
8236 if ((state->received_param == state->total_param) &&
8237 (state->received_data == state->total_data)) {
8239 handle_trans2(conn, req, state);
8241 SAFE_FREE(state->data);
8242 SAFE_FREE(state->param);
8244 END_PROFILE(SMBtrans2);
8248 DLIST_ADD(conn->pending_trans, state);
8250 /* We need to send an interim response then receive the rest
8251 of the parameter/data bytes */
8252 reply_outbuf(req, 0, 0);
8253 show_msg((char *)req->outbuf);
8254 END_PROFILE(SMBtrans2);
8259 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8260 SAFE_FREE(state->data);
8261 SAFE_FREE(state->param);
8263 END_PROFILE(SMBtrans2);
8264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8268 /****************************************************************************
8269 Reply to a SMBtranss2
8270 ****************************************************************************/
8272 void reply_transs2(struct smb_request *req)
8274 connection_struct *conn = req->conn;
8275 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8276 struct trans_state *state;
8278 START_PROFILE(SMBtranss2);
8280 show_msg((char *)req->inbuf);
8283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8284 END_PROFILE(SMBtranss2);
8288 for (state = conn->pending_trans; state != NULL;
8289 state = state->next) {
8290 if (state->mid == req->mid) {
8295 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8297 END_PROFILE(SMBtranss2);
8301 /* Revise state->total_param and state->total_data in case they have
8302 changed downwards */
8304 if (SVAL(req->vwv+0, 0) < state->total_param)
8305 state->total_param = SVAL(req->vwv+0, 0);
8306 if (SVAL(req->vwv+1, 0) < state->total_data)
8307 state->total_data = SVAL(req->vwv+1, 0);
8309 pcnt = SVAL(req->vwv+2, 0);
8310 poff = SVAL(req->vwv+3, 0);
8311 pdisp = SVAL(req->vwv+4, 0);
8313 dcnt = SVAL(req->vwv+5, 0);
8314 doff = SVAL(req->vwv+6, 0);
8315 ddisp = SVAL(req->vwv+7, 0);
8317 state->received_param += pcnt;
8318 state->received_data += dcnt;
8320 if ((state->received_data > state->total_data) ||
8321 (state->received_param > state->total_param))
8325 if (trans_oob(state->total_param, pdisp, pcnt)
8326 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8329 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8333 if (trans_oob(state->total_data, ddisp, dcnt)
8334 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8337 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8340 if ((state->received_param < state->total_param) ||
8341 (state->received_data < state->total_data)) {
8342 END_PROFILE(SMBtranss2);
8346 handle_trans2(conn, req, state);
8348 DLIST_REMOVE(conn->pending_trans, state);
8349 SAFE_FREE(state->data);
8350 SAFE_FREE(state->param);
8353 END_PROFILE(SMBtranss2);
8358 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8359 DLIST_REMOVE(conn->pending_trans, state);
8360 SAFE_FREE(state->data);
8361 SAFE_FREE(state->param);
8363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8364 END_PROFILE(SMBtranss2);