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 unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
372 size_t total_ea_len = 0;
373 TALLOC_CTX *mem_ctx = NULL;
375 if (!lp_ea_support(SNUM(conn))) {
378 mem_ctx = talloc_tos();
379 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
383 /****************************************************************************
384 Ensure the EA name is case insensitive by matching any existing EA name.
385 ****************************************************************************/
387 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
390 TALLOC_CTX *mem_ctx = talloc_tos();
391 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
393 for (; ea_list; ea_list = ea_list->next) {
394 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
395 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
396 &unix_ea_name[5], ea_list->ea.name));
397 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
403 /****************************************************************************
404 Set or delete an extended attribute.
405 ****************************************************************************/
407 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
408 const struct smb_filename *smb_fname, struct ea_list *ea_list)
413 if (!lp_ea_support(SNUM(conn))) {
414 return NT_STATUS_EAS_NOT_SUPPORTED;
417 status = get_full_smb_filename(talloc_tos(), smb_fname,
419 if (!NT_STATUS_IS_OK(status)) {
423 for (;ea_list; ea_list = ea_list->next) {
425 fstring unix_ea_name;
427 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
428 fstrcat(unix_ea_name, ea_list->ea.name);
430 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
432 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
434 if (samba_private_attr_name(unix_ea_name)) {
435 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
436 return NT_STATUS_ACCESS_DENIED;
439 if (ea_list->ea.value.length == 0) {
440 /* Remove the attribute. */
441 if (fsp && (fsp->fh->fd != -1)) {
442 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
443 unix_ea_name, fsp->fsp_name));
444 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
446 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
447 unix_ea_name, fname));
448 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
451 /* Removing a non existent attribute always succeeds. */
452 if (ret == -1 && errno == ENOATTR) {
453 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
459 if (fsp && (fsp->fh->fd != -1)) {
460 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
461 unix_ea_name, fsp->fsp_name));
462 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
463 ea_list->ea.value.data, ea_list->ea.value.length, 0);
465 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
466 unix_ea_name, fname));
467 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
468 ea_list->ea.value.data, ea_list->ea.value.length, 0);
474 if (errno == ENOTSUP) {
475 return NT_STATUS_EAS_NOT_SUPPORTED;
478 return map_nt_error_from_unix(errno);
484 /****************************************************************************
485 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
486 ****************************************************************************/
488 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
490 struct ea_list *ea_list_head = NULL;
491 size_t converted_size, offset = 0;
493 while (offset + 2 < data_size) {
494 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
495 unsigned int namelen = CVAL(pdata,offset);
497 offset++; /* Go past the namelen byte. */
499 /* integer wrap paranioa. */
500 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
501 (offset > data_size) || (namelen > data_size) ||
502 (offset + namelen >= data_size)) {
505 /* Ensure the name is null terminated. */
506 if (pdata[offset + namelen] != '\0') {
509 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
511 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
512 "failed: %s", strerror(errno)));
518 offset += (namelen + 1); /* Go past the name + terminating zero. */
519 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
520 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
526 /****************************************************************************
527 Read one EA list entry from the buffer.
528 ****************************************************************************/
530 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
532 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
534 unsigned int namelen;
535 size_t converted_size;
545 eal->ea.flags = CVAL(pdata,0);
546 namelen = CVAL(pdata,1);
547 val_len = SVAL(pdata,2);
549 if (4 + namelen + 1 + val_len > data_size) {
553 /* Ensure the name is null terminated. */
554 if (pdata[namelen + 4] != '\0') {
557 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
558 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
565 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
566 if (!eal->ea.value.data) {
570 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
572 /* Ensure we're null terminated just in case we print the value. */
573 eal->ea.value.data[val_len] = '\0';
574 /* But don't count the null. */
575 eal->ea.value.length--;
578 *pbytes_used = 4 + namelen + 1 + val_len;
581 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
582 dump_data(10, eal->ea.value.data, eal->ea.value.length);
587 /****************************************************************************
588 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
589 ****************************************************************************/
591 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
593 struct ea_list *ea_list_head = NULL;
595 size_t bytes_used = 0;
597 while (offset < data_size) {
598 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
604 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
605 offset += bytes_used;
611 /****************************************************************************
612 Count the total EA size needed.
613 ****************************************************************************/
615 static size_t ea_list_size(struct ea_list *ealist)
618 struct ea_list *listp;
621 for (listp = ealist; listp; listp = listp->next) {
622 push_ascii_fstring(dos_ea_name, listp->ea.name);
623 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
625 /* Add on 4 for total length. */
633 /****************************************************************************
634 Return a union of EA's from a file list and a list of names.
635 The TALLOC context for the two lists *MUST* be identical as we steal
636 memory from one list to add to another. JRA.
637 ****************************************************************************/
639 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
641 struct ea_list *nlistp, *flistp;
643 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
644 for (flistp = file_list; flistp; flistp = flistp->next) {
645 if (strequal(nlistp->ea.name, flistp->ea.name)) {
651 /* Copy the data from this entry. */
652 nlistp->ea.flags = flistp->ea.flags;
653 nlistp->ea.value = flistp->ea.value;
656 nlistp->ea.flags = 0;
657 ZERO_STRUCT(nlistp->ea.value);
661 *total_ea_len = ea_list_size(name_list);
665 /****************************************************************************
666 Send the required number of replies back.
667 We assume all fields other than the data fields are
668 set correctly for the type of call.
669 HACK ! Always assumes smb_setup field is zero.
670 ****************************************************************************/
672 void send_trans2_replies(connection_struct *conn,
673 struct smb_request *req,
680 /* As we are using a protocol > LANMAN1 then the max_send
681 variable must have been set in the sessetupX call.
682 This takes precedence over the max_xmit field in the
683 global struct. These different max_xmit variables should
684 be merged as this is now too confusing */
686 int data_to_send = datasize;
687 int params_to_send = paramsize;
689 const char *pp = params;
690 const char *pd = pdata;
691 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
692 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
693 int data_alignment_offset = 0;
694 bool overflow = False;
695 struct smbd_server_connection *sconn = smbd_server_conn;
696 int max_send = sconn->smb1.sessions.max_send;
698 /* Modify the data_to_send and datasize and set the error if
699 we're trying to send more than max_data_bytes. We still send
700 the part of the packet(s) that fit. Strange, but needed
703 if (max_data_bytes > 0 && datasize > max_data_bytes) {
704 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
705 max_data_bytes, datasize ));
706 datasize = data_to_send = max_data_bytes;
710 /* If there genuinely are no parameters or data to send just send the empty packet */
712 if(params_to_send == 0 && data_to_send == 0) {
713 reply_outbuf(req, 10, 0);
714 show_msg((char *)req->outbuf);
715 if (!srv_send_smb(smbd_server_fd(),
718 IS_CONN_ENCRYPTED(conn),
720 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
722 TALLOC_FREE(req->outbuf);
726 /* When sending params and data ensure that both are nicely aligned */
727 /* Only do this alignment when there is also data to send - else
728 can cause NT redirector problems. */
730 if (((params_to_send % 4) != 0) && (data_to_send != 0))
731 data_alignment_offset = 4 - (params_to_send % 4);
733 /* Space is bufsize minus Netbios over TCP header minus SMB header */
734 /* The alignment_offset is to align the param bytes on an even byte
735 boundary. NT 4.0 Beta needs this to work correctly. */
737 useable_space = max_send - (smb_size
740 + data_alignment_offset);
742 if (useable_space < 0) {
743 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
744 "= %d!!!", useable_space));
745 exit_server_cleanly("send_trans2_replies: Not enough space");
748 while (params_to_send || data_to_send) {
749 /* Calculate whether we will totally or partially fill this packet */
751 total_sent_thistime = params_to_send + data_to_send;
753 /* We can never send more than useable_space */
755 * Note that 'useable_space' does not include the alignment offsets,
756 * but we must include the alignment offsets in the calculation of
757 * the length of the data we send over the wire, as the alignment offsets
758 * are sent here. Fix from Marc_Jacobsen@hp.com.
761 total_sent_thistime = MIN(total_sent_thistime, useable_space);
763 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
764 + data_alignment_offset);
767 * We might have SMBtrans2s in req which was transferred to
768 * the outbuf, fix that.
770 SCVAL(req->outbuf, smb_com, SMBtrans2);
772 /* Set total params and data to be sent */
773 SSVAL(req->outbuf,smb_tprcnt,paramsize);
774 SSVAL(req->outbuf,smb_tdrcnt,datasize);
776 /* Calculate how many parameters and data we can fit into
777 * this packet. Parameters get precedence
780 params_sent_thistime = MIN(params_to_send,useable_space);
781 data_sent_thistime = useable_space - params_sent_thistime;
782 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
784 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
786 /* smb_proff is the offset from the start of the SMB header to the
787 parameter bytes, however the first 4 bytes of outbuf are
788 the Netbios over TCP header. Thus use smb_base() to subtract
789 them from the calculation */
791 SSVAL(req->outbuf,smb_proff,
792 ((smb_buf(req->outbuf)+alignment_offset)
793 - smb_base(req->outbuf)));
795 if(params_sent_thistime == 0)
796 SSVAL(req->outbuf,smb_prdisp,0);
798 /* Absolute displacement of param bytes sent in this packet */
799 SSVAL(req->outbuf,smb_prdisp,pp - params);
801 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
802 if(data_sent_thistime == 0) {
803 SSVAL(req->outbuf,smb_droff,0);
804 SSVAL(req->outbuf,smb_drdisp, 0);
806 /* The offset of the data bytes is the offset of the
807 parameter bytes plus the number of parameters being sent this time */
808 SSVAL(req->outbuf, smb_droff,
809 ((smb_buf(req->outbuf)+alignment_offset)
810 - smb_base(req->outbuf))
811 + params_sent_thistime + data_alignment_offset);
812 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
815 /* Initialize the padding for alignment */
817 if (alignment_offset != 0) {
818 memset(smb_buf(req->outbuf), 0, alignment_offset);
821 /* Copy the param bytes into the packet */
823 if(params_sent_thistime) {
824 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
825 params_sent_thistime);
828 /* Copy in the data bytes */
829 if(data_sent_thistime) {
830 if (data_alignment_offset != 0) {
831 memset((smb_buf(req->outbuf)+alignment_offset+
832 params_sent_thistime), 0,
833 data_alignment_offset);
835 memcpy(smb_buf(req->outbuf)+alignment_offset
836 +params_sent_thistime+data_alignment_offset,
837 pd,data_sent_thistime);
840 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
841 params_sent_thistime, data_sent_thistime, useable_space));
842 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
843 params_to_send, data_to_send, paramsize, datasize));
846 error_packet_set((char *)req->outbuf,
847 ERRDOS,ERRbufferoverflow,
848 STATUS_BUFFER_OVERFLOW,
852 /* Send the packet */
853 show_msg((char *)req->outbuf);
854 if (!srv_send_smb(smbd_server_fd(),
857 IS_CONN_ENCRYPTED(conn),
859 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
861 TALLOC_FREE(req->outbuf);
863 pp += params_sent_thistime;
864 pd += data_sent_thistime;
866 params_to_send -= params_sent_thistime;
867 data_to_send -= data_sent_thistime;
870 if(params_to_send < 0 || data_to_send < 0) {
871 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
872 params_to_send, data_to_send));
880 /****************************************************************************
881 Reply to a TRANSACT2_OPEN.
882 ****************************************************************************/
884 static void call_trans2open(connection_struct *conn,
885 struct smb_request *req,
886 char **pparams, int total_params,
887 char **ppdata, int total_data,
888 unsigned int max_data_bytes)
890 struct smb_filename *smb_fname = NULL;
891 char *params = *pparams;
892 char *pdata = *ppdata;
897 bool return_additional_info;
910 struct ea_list *ea_list = NULL;
915 uint32 create_disposition;
916 uint32 create_options = 0;
917 TALLOC_CTX *ctx = talloc_tos();
920 * Ensure we have enough parameters to perform the operation.
923 if (total_params < 29) {
924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
928 flags = SVAL(params, 0);
929 deny_mode = SVAL(params, 2);
930 open_attr = SVAL(params,6);
931 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
932 if (oplock_request) {
933 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
937 return_additional_info = BITSETW(params,0);
938 open_sattr = SVAL(params, 4);
939 open_time = make_unix_date3(params+8);
941 open_ofun = SVAL(params,12);
942 open_size = IVAL(params,14);
946 reply_doserror(req, ERRSRV, ERRaccess);
950 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
951 total_params - 28, STR_TERMINATE,
953 if (!NT_STATUS_IS_OK(status)) {
954 reply_nterror(req, status);
958 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
959 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
960 (unsigned int)open_ofun, open_size));
962 status = filename_convert(ctx,
964 req->flags2 & FLAGS2_DFS_PATHNAMES,
968 if (!NT_STATUS_IS_OK(status)) {
969 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
971 NT_STATUS_PATH_NOT_COVERED,
975 reply_nterror(req, status);
979 if (open_ofun == 0) {
980 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
984 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
990 reply_doserror(req, ERRDOS, ERRbadaccess);
994 /* Any data in this call is an EA list. */
995 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
996 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1000 if (total_data != 4) {
1001 if (total_data < 10) {
1002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1006 if (IVAL(pdata,0) > total_data) {
1007 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1008 IVAL(pdata,0), (unsigned int)total_data));
1009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1013 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1019 } else if (IVAL(pdata,0) != 4) {
1020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1024 status = SMB_VFS_CREATE_FILE(
1027 0, /* root_dir_fid */
1028 smb_fname, /* fname */
1029 access_mask, /* access_mask */
1030 share_mode, /* share_access */
1031 create_disposition, /* create_disposition*/
1032 create_options, /* create_options */
1033 open_attr, /* file_attributes */
1034 oplock_request, /* oplock_request */
1035 open_size, /* allocation_size */
1037 ea_list, /* ea_list */
1039 &smb_action); /* psbuf */
1041 if (!NT_STATUS_IS_OK(status)) {
1042 if (open_was_deferred(req->mid)) {
1043 /* We have re-scheduled this call. */
1046 reply_openerror(req, status);
1050 size = get_file_size_stat(&smb_fname->st);
1051 fattr = dos_mode(conn, smb_fname);
1052 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1053 inode = smb_fname->st.st_ex_ino;
1055 close_file(req, fsp, ERROR_CLOSE);
1056 reply_doserror(req, ERRDOS,ERRnoaccess);
1060 /* Realloc the size of parameters and data we will return */
1061 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1062 if(*pparams == NULL ) {
1063 reply_nterror(req, NT_STATUS_NO_MEMORY);
1068 SSVAL(params,0,fsp->fnum);
1069 SSVAL(params,2,fattr);
1070 srv_put_dos_date2(params,4, mtime);
1071 SIVAL(params,8, (uint32)size);
1072 SSVAL(params,12,deny_mode);
1073 SSVAL(params,14,0); /* open_type - file or directory. */
1074 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1076 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1077 smb_action |= EXTENDED_OPLOCK_GRANTED;
1080 SSVAL(params,18,smb_action);
1083 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1085 SIVAL(params,20,inode);
1086 SSVAL(params,24,0); /* Padding. */
1088 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1089 SIVAL(params, 26, ea_size);
1091 SIVAL(params, 26, 0);
1094 /* Send the required number of replies */
1095 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1097 TALLOC_FREE(smb_fname);
1100 /*********************************************************
1101 Routine to check if a given string matches exactly.
1102 as a special case a mask of "." does NOT match. That
1103 is required for correct wildcard semantics
1104 Case can be significant or not.
1105 **********************************************************/
1107 static bool exact_match(connection_struct *conn,
1111 if (mask[0] == '.' && mask[1] == 0)
1113 if (dptr_has_wild(conn->dirptr)) {
1116 if (conn->case_sensitive)
1117 return strcmp(str,mask)==0;
1119 return StrCaseCmp(str,mask) == 0;
1122 /****************************************************************************
1123 Return the filetype for UNIX extensions.
1124 ****************************************************************************/
1126 static uint32 unix_filetype(mode_t mode)
1129 return UNIX_TYPE_FILE;
1130 else if(S_ISDIR(mode))
1131 return UNIX_TYPE_DIR;
1133 else if(S_ISLNK(mode))
1134 return UNIX_TYPE_SYMLINK;
1137 else if(S_ISCHR(mode))
1138 return UNIX_TYPE_CHARDEV;
1141 else if(S_ISBLK(mode))
1142 return UNIX_TYPE_BLKDEV;
1145 else if(S_ISFIFO(mode))
1146 return UNIX_TYPE_FIFO;
1149 else if(S_ISSOCK(mode))
1150 return UNIX_TYPE_SOCKET;
1153 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1154 return UNIX_TYPE_UNKNOWN;
1157 /****************************************************************************
1158 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1159 ****************************************************************************/
1161 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1163 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1164 const SMB_STRUCT_STAT *psbuf,
1166 enum perm_type ptype,
1171 if (perms == SMB_MODE_NO_CHANGE) {
1172 if (!VALID_STAT(*psbuf)) {
1173 return NT_STATUS_INVALID_PARAMETER;
1175 *ret_perms = psbuf->st_ex_mode;
1176 return NT_STATUS_OK;
1180 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1181 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1182 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1183 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1184 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1185 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1186 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1187 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1188 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1190 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1193 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1196 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1201 /* Apply mode mask */
1202 ret &= lp_create_mask(SNUM(conn));
1203 /* Add in force bits */
1204 ret |= lp_force_create_mode(SNUM(conn));
1207 ret &= lp_dir_mask(SNUM(conn));
1208 /* Add in force bits */
1209 ret |= lp_force_dir_mode(SNUM(conn));
1211 case PERM_EXISTING_FILE:
1212 /* Apply mode mask */
1213 ret &= lp_security_mask(SNUM(conn));
1214 /* Add in force bits */
1215 ret |= lp_force_security_mode(SNUM(conn));
1217 case PERM_EXISTING_DIR:
1218 /* Apply mode mask */
1219 ret &= lp_dir_security_mask(SNUM(conn));
1220 /* Add in force bits */
1221 ret |= lp_force_dir_security_mode(SNUM(conn));
1226 return NT_STATUS_OK;
1229 /****************************************************************************
1230 Needed to show the msdfs symlinks as directories. Modifies psbuf
1231 to be a directory if it's a msdfs link.
1232 ****************************************************************************/
1234 static bool check_msdfs_link(connection_struct *conn,
1235 const char *pathname,
1236 SMB_STRUCT_STAT *psbuf)
1238 int saved_errno = errno;
1239 if(lp_host_msdfs() &&
1240 lp_msdfs_root(SNUM(conn)) &&
1241 is_msdfs_link(conn, pathname, psbuf)) {
1243 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1246 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1247 errno = saved_errno;
1250 errno = saved_errno;
1255 /****************************************************************************
1256 Get a level dependent lanman2 dir entry.
1257 ****************************************************************************/
1259 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1260 connection_struct *conn,
1262 const char *path_mask,
1265 int requires_resume_key,
1271 int space_remaining,
1273 bool *got_exact_match,
1274 int *last_entry_off,
1275 struct ea_list *name_list)
1279 SMB_STRUCT_STAT sbuf;
1280 const char *mask = NULL;
1281 char *pathreal = NULL;
1283 char *p, *q, *pdata = *ppdata;
1287 SMB_OFF_T file_size = 0;
1288 uint64_t allocation_size = 0;
1290 struct timespec mdate_ts, adate_ts, create_date_ts;
1291 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1293 char *last_entry_ptr;
1295 uint32 nt_extmode; /* Used for NT connections instead of mode */
1296 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1297 bool check_mangled_names = lp_manglednames(conn->params);
1298 char mangled_name[13]; /* mangled 8.3 name. */
1300 *out_of_space = False;
1301 *got_exact_match = False;
1303 ZERO_STRUCT(mdate_ts);
1304 ZERO_STRUCT(adate_ts);
1305 ZERO_STRUCT(create_date_ts);
1307 if (!conn->dirptr) {
1311 p = strrchr_m(path_mask,'/');
1314 mask = talloc_strdup(ctx,"*.*");
1324 bool ms_dfs_link = False;
1326 /* Needed if we run out of space */
1327 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1328 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1331 * Due to bugs in NT client redirectors we are not using
1332 * resume keys any more - set them to zero.
1333 * Check out the related comments in findfirst/findnext.
1339 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1340 (long)conn->dirptr,curr_dirpos));
1347 * fname may get mangled, dname is never mangled.
1348 * Whenever we're accessing the filesystem we use
1349 * pathreal which is composed from dname.
1355 /* Mangle fname if it's an illegal name. */
1356 if (mangle_must_mangle(dname,conn->params)) {
1357 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1359 continue; /* Error - couldn't mangle. */
1361 fname = talloc_strdup(ctx, mangled_name);
1367 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1368 got_match = mask_match(fname, mask, conn->case_sensitive);
1371 if(!got_match && check_mangled_names &&
1372 !mangle_is_8_3(fname, False, conn->params)) {
1374 * It turns out that NT matches wildcards against
1375 * both long *and* short names. This may explain some
1376 * of the wildcard wierdness from old DOS clients
1377 * that some people have been seeing.... JRA.
1379 /* Force the mangling into 8.3. */
1380 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1382 continue; /* Error - couldn't mangle. */
1385 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1386 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1391 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1392 struct smb_filename *smb_fname = NULL;
1395 if (dont_descend && !isdots) {
1402 pathreal = talloc_asprintf(ctx,
1407 pathreal = talloc_asprintf(ctx,
1418 /* A dirent from dptr_ReadDirName isn't a stream. */
1419 status = create_synthetic_smb_fname(ctx, pathreal,
1422 if (!NT_STATUS_IS_OK(status)) {
1427 if (INFO_LEVEL_IS_UNIX(info_level)) {
1428 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
1429 DEBUG(5,("get_lanman2_dir_entry: "
1430 "Couldn't lstat [%s] (%s)\n",
1431 smb_fname_str_dbg(smb_fname),
1433 TALLOC_FREE(smb_fname);
1434 TALLOC_FREE(pathreal);
1438 } else if (!VALID_STAT(smb_fname->st) &&
1439 SMB_VFS_STAT(conn, smb_fname) != 0) {
1440 /* Needed to show the msdfs symlinks as
1444 check_msdfs_link(conn,
1445 smb_fname->base_name,
1448 DEBUG(5,("get_lanman2_dir_entry: "
1449 "Couldn't stat [%s] (%s)\n",
1450 smb_fname_str_dbg(smb_fname),
1452 TALLOC_FREE(smb_fname);
1453 TALLOC_FREE(pathreal);
1460 mode = dos_mode_msdfs(conn, smb_fname);
1462 mode = dos_mode(conn, smb_fname);
1465 if (!dir_check_ftype(conn,mode,dirtype)) {
1466 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1467 TALLOC_FREE(smb_fname);
1468 TALLOC_FREE(pathreal);
1473 if (!(mode & aDIR)) {
1474 file_size = get_file_size_stat(&smb_fname->st);
1477 SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1479 if (ask_sharemode) {
1480 struct timespec write_time_ts;
1481 struct file_id fileid;
1483 ZERO_STRUCT(write_time_ts);
1484 fileid = vfs_file_id_from_sbuf(conn,
1486 get_file_infos(fileid, NULL, &write_time_ts);
1487 if (!null_timespec(write_time_ts)) {
1488 update_stat_ex_mtime(&smb_fname->st,
1493 mdate_ts = smb_fname->st.st_ex_mtime;
1494 adate_ts = smb_fname->st.st_ex_atime;
1495 create_date_ts = smb_fname->st.st_ex_btime;
1497 if (lp_dos_filetime_resolution(SNUM(conn))) {
1498 dos_filetime_timespec(&create_date_ts);
1499 dos_filetime_timespec(&mdate_ts);
1500 dos_filetime_timespec(&adate_ts);
1503 create_date = convert_timespec_to_time_t(create_date_ts);
1504 mdate = convert_timespec_to_time_t(mdate_ts);
1505 adate = convert_timespec_to_time_t(adate_ts);
1507 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1508 smb_fname_str_dbg(smb_fname), fname));
1512 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1513 sbuf = smb_fname->st;
1515 TALLOC_FREE(smb_fname);
1525 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1527 switch (info_level) {
1528 case SMB_FIND_INFO_STANDARD:
1529 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1530 if(requires_resume_key) {
1534 srv_put_dos_date2(p,0,create_date);
1535 srv_put_dos_date2(p,4,adate);
1536 srv_put_dos_date2(p,8,mdate);
1537 SIVAL(p,12,(uint32)file_size);
1538 SIVAL(p,16,(uint32)allocation_size);
1542 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1543 p += ucs2_align(base_data, p, 0);
1545 len = srvstr_push(base_data, flags2, p,
1546 fname, PTR_DIFF(end_data, p),
1548 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1550 SCVAL(nameptr, -1, len - 2);
1552 SCVAL(nameptr, -1, 0);
1556 SCVAL(nameptr, -1, len - 1);
1558 SCVAL(nameptr, -1, 0);
1564 case SMB_FIND_EA_SIZE:
1565 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1566 if(requires_resume_key) {
1570 srv_put_dos_date2(p,0,create_date);
1571 srv_put_dos_date2(p,4,adate);
1572 srv_put_dos_date2(p,8,mdate);
1573 SIVAL(p,12,(uint32)file_size);
1574 SIVAL(p,16,(uint32)allocation_size);
1577 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1578 SIVAL(p,22,ea_size); /* Extended attributes */
1582 len = srvstr_push(base_data, flags2,
1583 p, fname, PTR_DIFF(end_data, p),
1584 STR_TERMINATE | STR_NOALIGN);
1585 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1598 SCVAL(nameptr,0,len);
1600 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1603 case SMB_FIND_EA_LIST:
1605 struct ea_list *file_list = NULL;
1608 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1612 if(requires_resume_key) {
1616 srv_put_dos_date2(p,0,create_date);
1617 srv_put_dos_date2(p,4,adate);
1618 srv_put_dos_date2(p,8,mdate);
1619 SIVAL(p,12,(uint32)file_size);
1620 SIVAL(p,16,(uint32)allocation_size);
1622 p += 22; /* p now points to the EA area. */
1624 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1625 name_list = ea_list_union(name_list, file_list, &ea_len);
1627 /* We need to determine if this entry will fit in the space available. */
1628 /* Max string size is 255 bytes. */
1629 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1630 /* Move the dirptr back to prev_dirpos */
1631 dptr_SeekDir(conn->dirptr, prev_dirpos);
1632 *out_of_space = True;
1633 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1634 return False; /* Not finished - just out of space */
1637 /* Push the ea_data followed by the name. */
1638 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1640 len = srvstr_push(base_data, flags2,
1641 p + 1, fname, PTR_DIFF(end_data, p+1),
1642 STR_TERMINATE | STR_NOALIGN);
1643 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1656 SCVAL(nameptr,0,len);
1658 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1662 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1663 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1664 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1666 SIVAL(p,0,reskey); p += 4;
1667 put_long_date_timespec(p,create_date_ts); p += 8;
1668 put_long_date_timespec(p,adate_ts); p += 8;
1669 put_long_date_timespec(p,mdate_ts); p += 8;
1670 put_long_date_timespec(p,mdate_ts); p += 8;
1671 SOFF_T(p,0,file_size); p += 8;
1672 SOFF_T(p,0,allocation_size); p += 8;
1673 SIVAL(p,0,nt_extmode); p += 4;
1674 q = p; p += 4; /* q is placeholder for name length. */
1676 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1677 SIVAL(p,0,ea_size); /* Extended attributes */
1680 /* Clear the short name buffer. This is
1681 * IMPORTANT as not doing so will trigger
1682 * a Win2k client bug. JRA.
1684 if (!was_8_3 && check_mangled_names) {
1685 if (!name_to_8_3(fname,mangled_name,True,
1687 /* Error - mangle failed ! */
1688 memset(mangled_name,'\0',12);
1690 mangled_name[12] = 0;
1691 len = srvstr_push(base_data, flags2,
1692 p+2, mangled_name, 24,
1693 STR_UPPER|STR_UNICODE);
1695 memset(p + 2 + len,'\0',24 - len);
1702 len = srvstr_push(base_data, flags2, p,
1703 fname, PTR_DIFF(end_data, p),
1704 STR_TERMINATE_ASCII);
1707 SIVAL(p,0,0); /* Ensure any padding is null. */
1708 len = PTR_DIFF(p, pdata);
1709 len = (len + 3) & ~3;
1714 case SMB_FIND_FILE_DIRECTORY_INFO:
1715 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1717 SIVAL(p,0,reskey); p += 4;
1718 put_long_date_timespec(p,create_date_ts); p += 8;
1719 put_long_date_timespec(p,adate_ts); p += 8;
1720 put_long_date_timespec(p,mdate_ts); p += 8;
1721 put_long_date_timespec(p,mdate_ts); p += 8;
1722 SOFF_T(p,0,file_size); p += 8;
1723 SOFF_T(p,0,allocation_size); p += 8;
1724 SIVAL(p,0,nt_extmode); p += 4;
1725 len = srvstr_push(base_data, flags2,
1726 p + 4, fname, PTR_DIFF(end_data, p+4),
1727 STR_TERMINATE_ASCII);
1730 SIVAL(p,0,0); /* Ensure any padding is null. */
1731 len = PTR_DIFF(p, pdata);
1732 len = (len + 3) & ~3;
1737 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1738 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1740 SIVAL(p,0,reskey); p += 4;
1741 put_long_date_timespec(p,create_date_ts); p += 8;
1742 put_long_date_timespec(p,adate_ts); p += 8;
1743 put_long_date_timespec(p,mdate_ts); p += 8;
1744 put_long_date_timespec(p,mdate_ts); p += 8;
1745 SOFF_T(p,0,file_size); p += 8;
1746 SOFF_T(p,0,allocation_size); p += 8;
1747 SIVAL(p,0,nt_extmode); p += 4;
1748 q = p; p += 4; /* q is placeholder for name length. */
1750 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1751 SIVAL(p,0,ea_size); /* Extended attributes */
1754 len = srvstr_push(base_data, flags2, p,
1755 fname, PTR_DIFF(end_data, p),
1756 STR_TERMINATE_ASCII);
1760 SIVAL(p,0,0); /* Ensure any padding is null. */
1761 len = PTR_DIFF(p, pdata);
1762 len = (len + 3) & ~3;
1767 case SMB_FIND_FILE_NAMES_INFO:
1768 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1770 SIVAL(p,0,reskey); p += 4;
1772 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1773 acl on a dir (tridge) */
1774 len = srvstr_push(base_data, flags2, p,
1775 fname, PTR_DIFF(end_data, p),
1776 STR_TERMINATE_ASCII);
1779 SIVAL(p,0,0); /* Ensure any padding is null. */
1780 len = PTR_DIFF(p, pdata);
1781 len = (len + 3) & ~3;
1786 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1787 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1789 SIVAL(p,0,reskey); p += 4;
1790 put_long_date_timespec(p,create_date_ts); p += 8;
1791 put_long_date_timespec(p,adate_ts); p += 8;
1792 put_long_date_timespec(p,mdate_ts); p += 8;
1793 put_long_date_timespec(p,mdate_ts); p += 8;
1794 SOFF_T(p,0,file_size); p += 8;
1795 SOFF_T(p,0,allocation_size); p += 8;
1796 SIVAL(p,0,nt_extmode); p += 4;
1797 q = p; p += 4; /* q is placeholder for name length. */
1799 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1800 SIVAL(p,0,ea_size); /* Extended attributes */
1803 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1804 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1805 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1806 len = srvstr_push(base_data, flags2, p,
1807 fname, PTR_DIFF(end_data, p),
1808 STR_TERMINATE_ASCII);
1811 SIVAL(p,0,0); /* Ensure any padding is null. */
1812 len = PTR_DIFF(p, pdata);
1813 len = (len + 3) & ~3;
1818 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1819 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1820 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1822 SIVAL(p,0,reskey); p += 4;
1823 put_long_date_timespec(p,create_date_ts); p += 8;
1824 put_long_date_timespec(p,adate_ts); p += 8;
1825 put_long_date_timespec(p,mdate_ts); p += 8;
1826 put_long_date_timespec(p,mdate_ts); p += 8;
1827 SOFF_T(p,0,file_size); p += 8;
1828 SOFF_T(p,0,allocation_size); p += 8;
1829 SIVAL(p,0,nt_extmode); p += 4;
1830 q = p; p += 4; /* q is placeholder for name length */
1832 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1833 SIVAL(p,0,ea_size); /* Extended attributes */
1836 /* Clear the short name buffer. This is
1837 * IMPORTANT as not doing so will trigger
1838 * a Win2k client bug. JRA.
1840 if (!was_8_3 && check_mangled_names) {
1841 if (!name_to_8_3(fname,mangled_name,True,
1843 /* Error - mangle failed ! */
1844 memset(mangled_name,'\0',12);
1846 mangled_name[12] = 0;
1847 len = srvstr_push(base_data, flags2,
1848 p+2, mangled_name, 24,
1849 STR_UPPER|STR_UNICODE);
1852 memset(p + 2 + len,'\0',24 - len);
1859 SSVAL(p,0,0); p += 2; /* Reserved ? */
1860 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1861 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1862 len = srvstr_push(base_data, flags2, p,
1863 fname, PTR_DIFF(end_data, p),
1864 STR_TERMINATE_ASCII);
1867 SIVAL(p,0,0); /* Ensure any padding is null. */
1868 len = PTR_DIFF(p, pdata);
1869 len = (len + 3) & ~3;
1874 /* CIFS UNIX Extension. */
1876 case SMB_FIND_FILE_UNIX:
1877 case SMB_FIND_FILE_UNIX_INFO2:
1879 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1881 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1883 if (info_level == SMB_FIND_FILE_UNIX) {
1884 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1885 p = store_file_unix_basic(conn, p,
1887 len = srvstr_push(base_data, flags2, p,
1888 fname, PTR_DIFF(end_data, p),
1891 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1892 p = store_file_unix_basic_info2(conn, p,
1896 len = srvstr_push(base_data, flags2, p, fname,
1897 PTR_DIFF(end_data, p), 0);
1898 SIVAL(nameptr, 0, len);
1902 SIVAL(p,0,0); /* Ensure any padding is null. */
1904 len = PTR_DIFF(p, pdata);
1905 len = (len + 3) & ~3;
1906 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1908 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1918 if (PTR_DIFF(p,pdata) > space_remaining) {
1919 /* Move the dirptr back to prev_dirpos */
1920 dptr_SeekDir(conn->dirptr, prev_dirpos);
1921 *out_of_space = True;
1922 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1923 return False; /* Not finished - just out of space */
1926 /* Setup the last entry pointer, as an offset from base_data */
1927 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1928 /* Advance the data pointer to the next slot */
1934 /****************************************************************************
1935 Reply to a TRANS2_FINDFIRST.
1936 ****************************************************************************/
1938 static void call_trans2findfirst(connection_struct *conn,
1939 struct smb_request *req,
1940 char **pparams, int total_params,
1941 char **ppdata, int total_data,
1942 unsigned int max_data_bytes)
1944 /* We must be careful here that we don't return more than the
1945 allowed number of data bytes. If this means returning fewer than
1946 maxentries then so be it. We assume that the redirector has
1947 enough room for the fixed number of parameter bytes it has
1949 struct smb_filename *smb_dname = NULL;
1950 char *params = *pparams;
1951 char *pdata = *ppdata;
1955 uint16 findfirst_flags;
1956 bool close_after_first;
1958 bool requires_resume_key;
1960 char *directory = NULL;
1963 int last_entry_off=0;
1967 bool finished = False;
1968 bool dont_descend = False;
1969 bool out_of_space = False;
1970 int space_remaining;
1971 bool mask_contains_wcard = False;
1972 struct ea_list *ea_list = NULL;
1973 NTSTATUS ntstatus = NT_STATUS_OK;
1974 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1975 TALLOC_CTX *ctx = talloc_tos();
1977 if (total_params < 13) {
1978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1982 dirtype = SVAL(params,0);
1983 maxentries = SVAL(params,2);
1984 findfirst_flags = SVAL(params,4);
1985 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1986 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1987 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1988 info_level = SVAL(params,6);
1990 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1991 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1992 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1993 info_level, max_data_bytes));
1996 /* W2K3 seems to treat zero as 1. */
2000 switch (info_level) {
2001 case SMB_FIND_INFO_STANDARD:
2002 case SMB_FIND_EA_SIZE:
2003 case SMB_FIND_EA_LIST:
2004 case SMB_FIND_FILE_DIRECTORY_INFO:
2005 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2006 case SMB_FIND_FILE_NAMES_INFO:
2007 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2008 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2009 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2011 case SMB_FIND_FILE_UNIX:
2012 case SMB_FIND_FILE_UNIX_INFO2:
2013 /* Always use filesystem for UNIX mtime query. */
2014 ask_sharemode = false;
2015 if (!lp_unix_extensions()) {
2016 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2021 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2025 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2026 params+12, total_params - 12,
2027 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2028 if (!NT_STATUS_IS_OK(ntstatus)) {
2029 reply_nterror(req, ntstatus);
2033 ntstatus = resolve_dfspath_wcard(ctx, conn,
2034 req->flags2 & FLAGS2_DFS_PATHNAMES,
2037 &mask_contains_wcard);
2038 if (!NT_STATUS_IS_OK(ntstatus)) {
2039 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2040 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2041 ERRSRV, ERRbadpath);
2044 reply_nterror(req, ntstatus);
2048 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2049 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2050 if (!NT_STATUS_IS_OK(ntstatus)) {
2051 reply_nterror(req, ntstatus);
2055 mask = smb_dname->original_lcomp;
2057 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2058 TALLOC_FREE(smb_dname);
2059 if (!NT_STATUS_IS_OK(ntstatus)) {
2060 reply_nterror(req, ntstatus);
2064 ntstatus = check_name(conn, directory);
2065 if (!NT_STATUS_IS_OK(ntstatus)) {
2066 reply_nterror(req, ntstatus);
2070 p = strrchr_m(directory,'/');
2072 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2073 if((directory[0] == '.') && (directory[1] == '\0')) {
2074 mask = talloc_strdup(ctx,"*");
2076 reply_nterror(req, NT_STATUS_NO_MEMORY);
2079 mask_contains_wcard = True;
2081 directory = talloc_strdup(talloc_tos(), "./");
2083 reply_nterror(req, NT_STATUS_NO_MEMORY);
2090 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2092 if (info_level == SMB_FIND_EA_LIST) {
2095 if (total_data < 4) {
2096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2100 ea_size = IVAL(pdata,0);
2101 if (ea_size != total_data) {
2102 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2103 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2108 if (!lp_ea_support(SNUM(conn))) {
2109 reply_doserror(req, ERRDOS, ERReasnotsupported);
2113 /* Pull out the list of names. */
2114 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2116 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2121 *ppdata = (char *)SMB_REALLOC(
2122 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2123 if(*ppdata == NULL ) {
2124 reply_nterror(req, NT_STATUS_NO_MEMORY);
2128 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2130 /* Realloc the params space */
2131 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2132 if (*pparams == NULL) {
2133 reply_nterror(req, NT_STATUS_NO_MEMORY);
2138 /* Save the wildcard match and attribs we are using on this directory -
2139 needed as lanman2 assumes these are being saved between calls */
2141 ntstatus = dptr_create(conn,
2147 mask_contains_wcard,
2151 if (!NT_STATUS_IS_OK(ntstatus)) {
2152 reply_nterror(req, ntstatus);
2156 dptr_num = dptr_dnum(conn->dirptr);
2157 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2159 /* Initialize per TRANS2_FIND_FIRST operation data */
2160 dptr_init_search_op(conn->dirptr);
2162 /* We don't need to check for VOL here as this is returned by
2163 a different TRANS2 call. */
2165 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2166 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2167 dont_descend = True;
2170 space_remaining = max_data_bytes;
2171 out_of_space = False;
2173 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2174 bool got_exact_match = False;
2176 /* this is a heuristic to avoid seeking the dirptr except when
2177 absolutely necessary. It allows for a filename of about 40 chars */
2178 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2179 out_of_space = True;
2182 finished = !get_lanman2_dir_entry(ctx,
2185 mask,dirtype,info_level,
2186 requires_resume_key,dont_descend,
2189 space_remaining, &out_of_space,
2191 &last_entry_off, ea_list);
2194 if (finished && out_of_space)
2197 if (!finished && !out_of_space)
2201 * As an optimisation if we know we aren't looking
2202 * for a wildcard name (ie. the name matches the wildcard exactly)
2203 * then we can finish on any (first) match.
2204 * This speeds up large directory searches. JRA.
2210 /* Ensure space_remaining never goes -ve. */
2211 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2212 space_remaining = 0;
2213 out_of_space = true;
2215 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2219 /* Check if we can close the dirptr */
2220 if(close_after_first || (finished && close_if_end)) {
2221 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2222 dptr_close(&dptr_num);
2226 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2227 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2228 * the protocol level is less than NT1. Tested with smbclient. JRA.
2229 * This should fix the OS/2 client bug #2335.
2232 if(numentries == 0) {
2233 dptr_close(&dptr_num);
2234 if (Protocol < PROTOCOL_NT1) {
2235 reply_doserror(req, ERRDOS, ERRnofiles);
2238 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2239 ERRDOS, ERRbadfile);
2244 /* At this point pdata points to numentries directory entries. */
2246 /* Set up the return parameter block */
2247 SSVAL(params,0,dptr_num);
2248 SSVAL(params,2,numentries);
2249 SSVAL(params,4,finished);
2250 SSVAL(params,6,0); /* Never an EA error */
2251 SSVAL(params,8,last_entry_off);
2253 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2256 if ((! *directory) && dptr_path(dptr_num)) {
2257 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2259 reply_nterror(req, NT_STATUS_NO_MEMORY);
2263 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2264 smb_fn_name(req->cmd),
2265 mask, directory, dirtype, numentries ) );
2268 * Force a name mangle here to ensure that the
2269 * mask as an 8.3 name is top of the mangled cache.
2270 * The reasons for this are subtle. Don't remove
2271 * this code unless you know what you are doing
2272 * (see PR#13758). JRA.
2275 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2276 char mangled_name[13];
2277 name_to_8_3(mask, mangled_name, True, conn->params);
2283 /****************************************************************************
2284 Reply to a TRANS2_FINDNEXT.
2285 ****************************************************************************/
2287 static void call_trans2findnext(connection_struct *conn,
2288 struct smb_request *req,
2289 char **pparams, int total_params,
2290 char **ppdata, int total_data,
2291 unsigned int max_data_bytes)
2293 /* We must be careful here that we don't return more than the
2294 allowed number of data bytes. If this means returning fewer than
2295 maxentries then so be it. We assume that the redirector has
2296 enough room for the fixed number of parameter bytes it has
2298 char *params = *pparams;
2299 char *pdata = *ppdata;
2305 uint16 findnext_flags;
2306 bool close_after_request;
2308 bool requires_resume_key;
2310 bool mask_contains_wcard = False;
2311 char *resume_name = NULL;
2312 const char *mask = NULL;
2313 const char *directory = NULL;
2317 int i, last_entry_off=0;
2318 bool finished = False;
2319 bool dont_descend = False;
2320 bool out_of_space = False;
2321 int space_remaining;
2322 struct ea_list *ea_list = NULL;
2323 NTSTATUS ntstatus = NT_STATUS_OK;
2324 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2325 TALLOC_CTX *ctx = talloc_tos();
2327 if (total_params < 13) {
2328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2332 dptr_num = SVAL(params,0);
2333 maxentries = SVAL(params,2);
2334 info_level = SVAL(params,4);
2335 resume_key = IVAL(params,6);
2336 findnext_flags = SVAL(params,10);
2337 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2338 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2339 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2340 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2342 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2344 total_params - 12, STR_TERMINATE, &ntstatus,
2345 &mask_contains_wcard);
2346 if (!NT_STATUS_IS_OK(ntstatus)) {
2347 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2348 complain (it thinks we're asking for the directory above the shared
2349 path or an invalid name). Catch this as the resume name is only compared, never used in
2350 a file access. JRA. */
2351 srvstr_pull_talloc(ctx, params, req->flags2,
2352 &resume_name, params+12,
2356 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2357 reply_nterror(req, ntstatus);
2362 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2363 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2364 resume_key = %d resume name = %s continue=%d level = %d\n",
2365 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2366 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2369 /* W2K3 seems to treat zero as 1. */
2373 switch (info_level) {
2374 case SMB_FIND_INFO_STANDARD:
2375 case SMB_FIND_EA_SIZE:
2376 case SMB_FIND_EA_LIST:
2377 case SMB_FIND_FILE_DIRECTORY_INFO:
2378 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2379 case SMB_FIND_FILE_NAMES_INFO:
2380 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2381 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2382 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2384 case SMB_FIND_FILE_UNIX:
2385 case SMB_FIND_FILE_UNIX_INFO2:
2386 /* Always use filesystem for UNIX mtime query. */
2387 ask_sharemode = false;
2388 if (!lp_unix_extensions()) {
2389 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2394 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2398 if (info_level == SMB_FIND_EA_LIST) {
2401 if (total_data < 4) {
2402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2406 ea_size = IVAL(pdata,0);
2407 if (ea_size != total_data) {
2408 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2409 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2410 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2414 if (!lp_ea_support(SNUM(conn))) {
2415 reply_doserror(req, ERRDOS, ERReasnotsupported);
2419 /* Pull out the list of names. */
2420 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2422 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2427 *ppdata = (char *)SMB_REALLOC(
2428 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2429 if(*ppdata == NULL) {
2430 reply_nterror(req, NT_STATUS_NO_MEMORY);
2435 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2437 /* Realloc the params space */
2438 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2439 if(*pparams == NULL ) {
2440 reply_nterror(req, NT_STATUS_NO_MEMORY);
2446 /* Check that the dptr is valid */
2447 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2448 reply_doserror(req, ERRDOS, ERRnofiles);
2452 string_set(&conn->dirpath,dptr_path(dptr_num));
2454 /* Get the wildcard mask from the dptr */
2455 if((p = dptr_wcard(dptr_num))== NULL) {
2456 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2457 reply_doserror(req, ERRDOS, ERRnofiles);
2462 directory = conn->dirpath;
2464 /* Get the attr mask from the dptr */
2465 dirtype = dptr_attr(dptr_num);
2467 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2468 dptr_num, mask, dirtype,
2470 dptr_TellDir(conn->dirptr)));
2472 /* Initialize per TRANS2_FIND_NEXT operation data */
2473 dptr_init_search_op(conn->dirptr);
2475 /* We don't need to check for VOL here as this is returned by
2476 a different TRANS2 call. */
2478 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2479 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2480 dont_descend = True;
2483 space_remaining = max_data_bytes;
2484 out_of_space = False;
2487 * Seek to the correct position. We no longer use the resume key but
2488 * depend on the last file name instead.
2491 if(*resume_name && !continue_bit) {
2494 long current_pos = 0;
2496 * Remember, name_to_8_3 is called by
2497 * get_lanman2_dir_entry(), so the resume name
2498 * could be mangled. Ensure we check the unmangled name.
2501 if (mangle_is_mangled(resume_name, conn->params)) {
2502 char *new_resume_name = NULL;
2503 mangle_lookup_name_from_8_3(ctx,
2507 if (new_resume_name) {
2508 resume_name = new_resume_name;
2513 * Fix for NT redirector problem triggered by resume key indexes
2514 * changing between directory scans. We now return a resume key of 0
2515 * and instead look for the filename to continue from (also given
2516 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2517 * findfirst/findnext (as is usual) then the directory pointer
2518 * should already be at the correct place.
2521 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2522 } /* end if resume_name && !continue_bit */
2524 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2525 bool got_exact_match = False;
2527 /* this is a heuristic to avoid seeking the dirptr except when
2528 absolutely necessary. It allows for a filename of about 40 chars */
2529 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2530 out_of_space = True;
2533 finished = !get_lanman2_dir_entry(ctx,
2536 mask,dirtype,info_level,
2537 requires_resume_key,dont_descend,
2540 space_remaining, &out_of_space,
2542 &last_entry_off, ea_list);
2545 if (finished && out_of_space)
2548 if (!finished && !out_of_space)
2552 * As an optimisation if we know we aren't looking
2553 * for a wildcard name (ie. the name matches the wildcard exactly)
2554 * then we can finish on any (first) match.
2555 * This speeds up large directory searches. JRA.
2561 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2564 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2565 smb_fn_name(req->cmd),
2566 mask, directory, dirtype, numentries ) );
2568 /* Check if we can close the dirptr */
2569 if(close_after_request || (finished && close_if_end)) {
2570 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2571 dptr_close(&dptr_num); /* This frees up the saved mask */
2574 /* Set up the return parameter block */
2575 SSVAL(params,0,numentries);
2576 SSVAL(params,2,finished);
2577 SSVAL(params,4,0); /* Never an EA error */
2578 SSVAL(params,6,last_entry_off);
2580 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2586 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2588 E_md4hash(lp_servicename(SNUM(conn)),objid);
2592 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2594 SMB_ASSERT(extended_info != NULL);
2596 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2597 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2598 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2599 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2600 #ifdef SAMBA_VERSION_REVISION
2601 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2603 extended_info->samba_subversion = 0;
2604 #ifdef SAMBA_VERSION_RC_RELEASE
2605 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2607 #ifdef SAMBA_VERSION_PRE_RELEASE
2608 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2611 #ifdef SAMBA_VERSION_VENDOR_PATCH
2612 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2614 extended_info->samba_gitcommitdate = 0;
2615 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2616 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2619 memset(extended_info->samba_version_string, 0,
2620 sizeof(extended_info->samba_version_string));
2622 snprintf (extended_info->samba_version_string,
2623 sizeof(extended_info->samba_version_string),
2624 "%s", samba_version_string());
2627 /****************************************************************************
2628 Reply to a TRANS2_QFSINFO (query filesystem info).
2629 ****************************************************************************/
2631 static void call_trans2qfsinfo(connection_struct *conn,
2632 struct smb_request *req,
2633 char **pparams, int total_params,
2634 char **ppdata, int total_data,
2635 unsigned int max_data_bytes)
2637 char *pdata, *end_data;
2638 char *params = *pparams;
2642 const char *vname = volume_label(SNUM(conn));
2643 int snum = SNUM(conn);
2644 char *fstype = lp_fstype(SNUM(conn));
2645 uint32 additional_flags = 0;
2647 if (total_params < 2) {
2648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2652 info_level = SVAL(params,0);
2655 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2656 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2657 "info level (0x%x) on IPC$.\n",
2658 (unsigned int)info_level));
2659 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2664 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2665 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2666 DEBUG(0,("call_trans2qfsinfo: encryption required "
2667 "and info level 0x%x sent.\n",
2668 (unsigned int)info_level));
2669 exit_server_cleanly("encryption required "
2675 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2677 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
2678 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2679 reply_doserror(req, ERRSRV, ERRinvdevice);
2683 *ppdata = (char *)SMB_REALLOC(
2684 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2685 if (*ppdata == NULL ) {
2686 reply_nterror(req, NT_STATUS_NO_MEMORY);
2691 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2692 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2694 switch (info_level) {
2695 case SMB_INFO_ALLOCATION:
2697 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2699 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2700 reply_nterror(req, map_nt_error_from_unix(errno));
2704 block_size = lp_block_size(snum);
2705 if (bsize < block_size) {
2706 uint64_t factor = block_size/bsize;
2711 if (bsize > block_size) {
2712 uint64_t factor = bsize/block_size;
2717 bytes_per_sector = 512;
2718 sectors_per_unit = bsize/bytes_per_sector;
2720 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2721 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2722 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2724 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2725 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2726 SIVAL(pdata,l1_cUnit,dsize);
2727 SIVAL(pdata,l1_cUnitAvail,dfree);
2728 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2732 case SMB_INFO_VOLUME:
2733 /* Return volume name */
2735 * Add volume serial number - hash of a combination of
2736 * the called hostname and the service name.
2738 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2740 * Win2k3 and previous mess this up by sending a name length
2741 * one byte short. I believe only older clients (OS/2 Win9x) use
2742 * this call so try fixing this by adding a terminating null to
2743 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2747 pdata+l2_vol_szVolLabel, vname,
2748 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2749 STR_NOALIGN|STR_TERMINATE);
2750 SCVAL(pdata,l2_vol_cch,len);
2751 data_len = l2_vol_szVolLabel + len;
2752 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2753 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2757 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2758 case SMB_FS_ATTRIBUTE_INFORMATION:
2760 additional_flags = 0;
2761 #if defined(HAVE_SYS_QUOTAS)
2762 additional_flags |= FILE_VOLUME_QUOTAS;
2765 if(lp_nt_acl_support(SNUM(conn))) {
2766 additional_flags |= FILE_PERSISTENT_ACLS;
2769 /* Capabilities are filled in at connection time through STATVFS call */
2770 additional_flags |= conn->fs_capabilities;
2772 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2773 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2774 additional_flags); /* FS ATTRIBUTES */
2776 SIVAL(pdata,4,255); /* Max filename component length */
2777 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2778 and will think we can't do long filenames */
2779 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2780 PTR_DIFF(end_data, pdata+12),
2783 data_len = 12 + len;
2786 case SMB_QUERY_FS_LABEL_INFO:
2787 case SMB_FS_LABEL_INFORMATION:
2788 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2789 PTR_DIFF(end_data, pdata+4), 0);
2794 case SMB_QUERY_FS_VOLUME_INFO:
2795 case SMB_FS_VOLUME_INFORMATION:
2798 * Add volume serial number - hash of a combination of
2799 * the called hostname and the service name.
2801 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2802 (str_checksum(get_local_machine_name())<<16));
2804 /* Max label len is 32 characters. */
2805 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2806 PTR_DIFF(end_data, pdata+18),
2808 SIVAL(pdata,12,len);
2811 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2812 (int)strlen(vname),vname, lp_servicename(snum)));
2815 case SMB_QUERY_FS_SIZE_INFO:
2816 case SMB_FS_SIZE_INFORMATION:
2818 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2820 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2821 reply_nterror(req, map_nt_error_from_unix(errno));
2824 block_size = lp_block_size(snum);
2825 if (bsize < block_size) {
2826 uint64_t factor = block_size/bsize;
2831 if (bsize > block_size) {
2832 uint64_t factor = bsize/block_size;
2837 bytes_per_sector = 512;
2838 sectors_per_unit = bsize/bytes_per_sector;
2839 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2840 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2841 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2842 SBIG_UINT(pdata,0,dsize);
2843 SBIG_UINT(pdata,8,dfree);
2844 SIVAL(pdata,16,sectors_per_unit);
2845 SIVAL(pdata,20,bytes_per_sector);
2849 case SMB_FS_FULL_SIZE_INFORMATION:
2851 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2853 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2854 reply_nterror(req, map_nt_error_from_unix(errno));
2857 block_size = lp_block_size(snum);
2858 if (bsize < block_size) {
2859 uint64_t factor = block_size/bsize;
2864 if (bsize > block_size) {
2865 uint64_t factor = bsize/block_size;
2870 bytes_per_sector = 512;
2871 sectors_per_unit = bsize/bytes_per_sector;
2872 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2873 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2874 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2875 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2876 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2877 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2878 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2879 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2883 case SMB_QUERY_FS_DEVICE_INFO:
2884 case SMB_FS_DEVICE_INFORMATION:
2886 SIVAL(pdata,0,0); /* dev type */
2887 SIVAL(pdata,4,0); /* characteristics */
2890 #ifdef HAVE_SYS_QUOTAS
2891 case SMB_FS_QUOTA_INFORMATION:
2893 * what we have to send --metze:
2895 * Unknown1: 24 NULL bytes
2896 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2897 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2898 * Quota Flags: 2 byte :
2899 * Unknown3: 6 NULL bytes
2903 * details for Quota Flags:
2905 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2906 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2907 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2908 * 0x0001 Enable Quotas: enable quota for this fs
2912 /* we need to fake up a fsp here,
2913 * because its not send in this call
2916 SMB_NTQUOTA_STRUCT quotas;
2919 ZERO_STRUCT(quotas);
2925 if (conn->server_info->utok.uid != 0) {
2926 DEBUG(0,("set_user_quota: access_denied "
2927 "service [%s] user [%s]\n",
2928 lp_servicename(SNUM(conn)),
2929 conn->server_info->unix_name));
2930 reply_doserror(req, ERRDOS, ERRnoaccess);
2934 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2935 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2936 reply_doserror(req, ERRSRV, ERRerror);
2942 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2944 /* Unknown1 24 NULL bytes*/
2945 SBIG_UINT(pdata,0,(uint64_t)0);
2946 SBIG_UINT(pdata,8,(uint64_t)0);
2947 SBIG_UINT(pdata,16,(uint64_t)0);
2949 /* Default Soft Quota 8 bytes */
2950 SBIG_UINT(pdata,24,quotas.softlim);
2952 /* Default Hard Quota 8 bytes */
2953 SBIG_UINT(pdata,32,quotas.hardlim);
2955 /* Quota flag 2 bytes */
2956 SSVAL(pdata,40,quotas.qflags);
2958 /* Unknown3 6 NULL bytes */
2964 #endif /* HAVE_SYS_QUOTAS */
2965 case SMB_FS_OBJECTID_INFORMATION:
2967 unsigned char objid[16];
2968 struct smb_extended_info extended_info;
2969 memcpy(pdata,create_volume_objectid(conn, objid),16);
2970 samba_extended_info_version (&extended_info);
2971 SIVAL(pdata,16,extended_info.samba_magic);
2972 SIVAL(pdata,20,extended_info.samba_version);
2973 SIVAL(pdata,24,extended_info.samba_subversion);
2974 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2975 memcpy(pdata+36,extended_info.samba_version_string,28);
2981 * Query the version and capabilities of the CIFS UNIX extensions
2985 case SMB_QUERY_CIFS_UNIX_INFO:
2987 bool large_write = lp_min_receive_file_size() &&
2988 !srv_is_signing_active(smbd_server_conn);
2989 bool large_read = !srv_is_signing_active(smbd_server_conn);
2990 int encrypt_caps = 0;
2992 if (!lp_unix_extensions()) {
2993 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2997 switch (conn->encrypt_level) {
3003 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3006 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3007 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3008 large_write = false;
3014 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3015 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3017 /* We have POSIX ACLs, pathname, encryption,
3018 * large read/write, and locking capability. */
3020 SBIG_UINT(pdata,4,((uint64_t)(
3021 CIFS_UNIX_POSIX_ACLS_CAP|
3022 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3023 CIFS_UNIX_FCNTL_LOCKS_CAP|
3024 CIFS_UNIX_EXTATTR_CAP|
3025 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3027 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3029 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3033 case SMB_QUERY_POSIX_FS_INFO:
3036 vfs_statvfs_struct svfs;
3038 if (!lp_unix_extensions()) {
3039 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3043 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3047 SIVAL(pdata,0,svfs.OptimalTransferSize);
3048 SIVAL(pdata,4,svfs.BlockSize);
3049 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3050 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3051 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3052 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3053 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3054 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3055 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3057 } else if (rc == EOPNOTSUPP) {
3058 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3060 #endif /* EOPNOTSUPP */
3062 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3063 reply_doserror(req, ERRSRV, ERRerror);
3069 case SMB_QUERY_POSIX_WHOAMI:
3075 if (!lp_unix_extensions()) {
3076 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3080 if (max_data_bytes < 40) {
3081 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3085 /* We ARE guest if global_sid_Builtin_Guests is
3086 * in our list of SIDs.
3088 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3089 conn->server_info->ptok)) {
3090 flags |= SMB_WHOAMI_GUEST;
3093 /* We are NOT guest if global_sid_Authenticated_Users
3094 * is in our list of SIDs.
3096 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3097 conn->server_info->ptok)) {
3098 flags &= ~SMB_WHOAMI_GUEST;
3101 /* NOTE: 8 bytes for UID/GID, irrespective of native
3102 * platform size. This matches
3103 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3105 data_len = 4 /* flags */
3112 + 4 /* pad/reserved */
3113 + (conn->server_info->utok.ngroups * 8)
3115 + (conn->server_info->ptok->num_sids *
3119 SIVAL(pdata, 0, flags);
3120 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3122 (uint64_t)conn->server_info->utok.uid);
3123 SBIG_UINT(pdata, 16,
3124 (uint64_t)conn->server_info->utok.gid);
3127 if (data_len >= max_data_bytes) {
3128 /* Potential overflow, skip the GIDs and SIDs. */
3130 SIVAL(pdata, 24, 0); /* num_groups */
3131 SIVAL(pdata, 28, 0); /* num_sids */
3132 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3133 SIVAL(pdata, 36, 0); /* reserved */
3139 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3140 SIVAL(pdata, 28, conn->server_info->num_sids);
3142 /* We walk the SID list twice, but this call is fairly
3143 * infrequent, and I don't expect that it's performance
3144 * sensitive -- jpeach
3146 for (i = 0, sid_bytes = 0;
3147 i < conn->server_info->ptok->num_sids; ++i) {
3148 sid_bytes += ndr_size_dom_sid(
3149 &conn->server_info->ptok->user_sids[i],
3154 /* SID list byte count */
3155 SIVAL(pdata, 32, sid_bytes);
3157 /* 4 bytes pad/reserved - must be zero */
3158 SIVAL(pdata, 36, 0);
3162 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3163 SBIG_UINT(pdata, data_len,
3164 (uint64_t)conn->server_info->utok.groups[i]);
3170 i < conn->server_info->ptok->num_sids; ++i) {
3171 int sid_len = ndr_size_dom_sid(
3172 &conn->server_info->ptok->user_sids[i],
3176 sid_linearize(pdata + data_len, sid_len,
3177 &conn->server_info->ptok->user_sids[i]);
3178 data_len += sid_len;
3184 case SMB_MAC_QUERY_FS_INFO:
3186 * Thursby MAC extension... ONLY on NTFS filesystems
3187 * once we do streams then we don't need this
3189 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3191 SIVAL(pdata,84,0x100); /* Don't support mac... */
3196 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3201 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3204 DEBUG( 4, ( "%s info_level = %d\n",
3205 smb_fn_name(req->cmd), info_level) );
3210 /****************************************************************************
3211 Reply to a TRANS2_SETFSINFO (set filesystem info).
3212 ****************************************************************************/
3214 static void call_trans2setfsinfo(connection_struct *conn,
3215 struct smb_request *req,
3216 char **pparams, int total_params,
3217 char **ppdata, int total_data,
3218 unsigned int max_data_bytes)
3220 char *pdata = *ppdata;
3221 char *params = *pparams;
3224 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3227 if (total_params < 4) {
3228 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3234 info_level = SVAL(params,2);
3237 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3238 info_level != SMB_SET_CIFS_UNIX_INFO) {
3239 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3240 "info level (0x%x) on IPC$.\n",
3241 (unsigned int)info_level));
3242 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3247 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3248 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3249 DEBUG(0,("call_trans2setfsinfo: encryption required "
3250 "and info level 0x%x sent.\n",
3251 (unsigned int)info_level));
3252 exit_server_cleanly("encryption required "
3258 switch(info_level) {
3259 case SMB_SET_CIFS_UNIX_INFO:
3261 uint16 client_unix_major;
3262 uint16 client_unix_minor;
3263 uint32 client_unix_cap_low;
3264 uint32 client_unix_cap_high;
3266 if (!lp_unix_extensions()) {
3268 NT_STATUS_INVALID_LEVEL);
3272 /* There should be 12 bytes of capabilities set. */
3273 if (total_data < 8) {
3276 NT_STATUS_INVALID_PARAMETER);
3279 client_unix_major = SVAL(pdata,0);
3280 client_unix_minor = SVAL(pdata,2);
3281 client_unix_cap_low = IVAL(pdata,4);
3282 client_unix_cap_high = IVAL(pdata,8);
3283 /* Just print these values for now. */
3284 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3285 cap_low = 0x%x, cap_high = 0x%x\n",
3286 (unsigned int)client_unix_major,
3287 (unsigned int)client_unix_minor,
3288 (unsigned int)client_unix_cap_low,
3289 (unsigned int)client_unix_cap_high ));
3291 /* Here is where we must switch to posix pathname processing... */
3292 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3293 lp_set_posix_pathnames();
3294 mangle_change_to_posix();
3297 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3298 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3299 /* Client that knows how to do posix locks,
3300 * but not posix open/mkdir operations. Set a
3301 * default type for read/write checks. */
3303 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3309 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3312 size_t param_len = 0;
3313 size_t data_len = total_data;
3315 if (!lp_unix_extensions()) {
3318 NT_STATUS_INVALID_LEVEL);
3322 if (lp_smb_encrypt(SNUM(conn)) == false) {
3325 NT_STATUS_NOT_SUPPORTED);
3329 DEBUG( 4,("call_trans2setfsinfo: "
3330 "request transport encryption.\n"));
3332 status = srv_request_encryption_setup(conn,
3333 (unsigned char **)ppdata,
3335 (unsigned char **)pparams,
3338 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3339 !NT_STATUS_IS_OK(status)) {
3340 reply_nterror(req, status);
3344 send_trans2_replies(conn, req,
3351 if (NT_STATUS_IS_OK(status)) {
3352 /* Server-side transport
3353 * encryption is now *on*. */
3354 status = srv_encryption_start(conn);
3355 if (!NT_STATUS_IS_OK(status)) {
3356 exit_server_cleanly(
3357 "Failure in setting "
3358 "up encrypted transport");
3364 case SMB_FS_QUOTA_INFORMATION:
3366 files_struct *fsp = NULL;
3367 SMB_NTQUOTA_STRUCT quotas;
3369 ZERO_STRUCT(quotas);
3372 if ((conn->server_info->utok.uid != 0)
3373 ||!CAN_WRITE(conn)) {
3374 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3375 lp_servicename(SNUM(conn)),
3376 conn->server_info->unix_name));
3377 reply_doserror(req, ERRSRV, ERRaccess);
3381 /* note: normaly there're 48 bytes,
3382 * but we didn't use the last 6 bytes for now
3385 fsp = file_fsp(req, SVAL(params,0));
3387 if (!check_fsp_ntquota_handle(conn, req,
3389 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3391 req, NT_STATUS_INVALID_HANDLE);
3395 if (total_data < 42) {
3396 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3400 NT_STATUS_INVALID_PARAMETER);
3404 /* unknown_1 24 NULL bytes in pdata*/
3406 /* the soft quotas 8 bytes (uint64_t)*/
3407 quotas.softlim = (uint64_t)IVAL(pdata,24);
3408 #ifdef LARGE_SMB_OFF_T
3409 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3410 #else /* LARGE_SMB_OFF_T */
3411 if ((IVAL(pdata,28) != 0)&&
3412 ((quotas.softlim != 0xFFFFFFFF)||
3413 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3414 /* more than 32 bits? */
3417 NT_STATUS_INVALID_PARAMETER);
3420 #endif /* LARGE_SMB_OFF_T */
3422 /* the hard quotas 8 bytes (uint64_t)*/
3423 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3424 #ifdef LARGE_SMB_OFF_T
3425 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3426 #else /* LARGE_SMB_OFF_T */
3427 if ((IVAL(pdata,36) != 0)&&
3428 ((quotas.hardlim != 0xFFFFFFFF)||
3429 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3430 /* more than 32 bits? */
3433 NT_STATUS_INVALID_PARAMETER);
3436 #endif /* LARGE_SMB_OFF_T */
3438 /* quota_flags 2 bytes **/
3439 quotas.qflags = SVAL(pdata,40);
3441 /* unknown_2 6 NULL bytes follow*/
3443 /* now set the quotas */
3444 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3445 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3446 reply_doserror(req, ERRSRV, ERRerror);
3453 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3455 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3461 * sending this reply works fine,
3462 * but I'm not sure it's the same
3463 * like windows do...
3466 reply_outbuf(req, 10, 0);
3469 #if defined(HAVE_POSIX_ACLS)
3470 /****************************************************************************
3471 Utility function to count the number of entries in a POSIX acl.
3472 ****************************************************************************/
3474 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3476 unsigned int ace_count = 0;
3477 int entry_id = SMB_ACL_FIRST_ENTRY;
3478 SMB_ACL_ENTRY_T entry;
3480 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3482 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3483 entry_id = SMB_ACL_NEXT_ENTRY;
3490 /****************************************************************************
3491 Utility function to marshall a POSIX acl into wire format.
3492 ****************************************************************************/
3494 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3496 int entry_id = SMB_ACL_FIRST_ENTRY;
3497 SMB_ACL_ENTRY_T entry;
3499 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3500 SMB_ACL_TAG_T tagtype;
3501 SMB_ACL_PERMSET_T permset;
3502 unsigned char perms = 0;
3503 unsigned int own_grp;
3506 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3507 entry_id = SMB_ACL_NEXT_ENTRY;
3510 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3511 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3515 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3516 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3520 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3521 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3522 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3524 SCVAL(pdata,1,perms);
3527 case SMB_ACL_USER_OBJ:
3528 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3529 own_grp = (unsigned int)pst->st_ex_uid;
3530 SIVAL(pdata,2,own_grp);
3535 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3537 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3540 own_grp = (unsigned int)*puid;
3541 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3542 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3543 SIVAL(pdata,2,own_grp);
3547 case SMB_ACL_GROUP_OBJ:
3548 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3549 own_grp = (unsigned int)pst->st_ex_gid;
3550 SIVAL(pdata,2,own_grp);
3555 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3557 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3560 own_grp = (unsigned int)*pgid;
3561 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3562 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3563 SIVAL(pdata,2,own_grp);
3568 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3569 SIVAL(pdata,2,0xFFFFFFFF);
3570 SIVAL(pdata,6,0xFFFFFFFF);
3573 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3574 SIVAL(pdata,2,0xFFFFFFFF);
3575 SIVAL(pdata,6,0xFFFFFFFF);
3578 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3581 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3588 /****************************************************************************
3589 Store the FILE_UNIX_BASIC info.
3590 ****************************************************************************/
3592 static char *store_file_unix_basic(connection_struct *conn,
3595 const SMB_STRUCT_STAT *psbuf)
3597 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3598 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3600 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3603 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3606 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3607 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3608 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3611 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3615 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3619 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3622 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3626 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3630 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3633 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3637 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3644 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3645 * the chflags(2) (or equivalent) flags.
3647 * XXX: this really should be behind the VFS interface. To do this, we would
3648 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3649 * Each VFS module could then implement its own mapping as appropriate for the
3650 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3652 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3656 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3660 { UF_IMMUTABLE, EXT_IMMUTABLE },
3664 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3668 { UF_HIDDEN, EXT_HIDDEN },
3671 /* Do not remove. We need to guarantee that this array has at least one
3672 * entry to build on HP-UX.
3678 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3679 uint32 *smb_fflags, uint32 *smb_fmask)
3683 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3684 *smb_fmask |= info2_flags_map[i].smb_fflag;
3685 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3686 *smb_fflags |= info2_flags_map[i].smb_fflag;
3691 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3692 const uint32 smb_fflags,
3693 const uint32 smb_fmask,
3696 uint32 max_fmask = 0;
3699 *stat_fflags = psbuf->st_ex_flags;
3701 /* For each flags requested in smb_fmask, check the state of the
3702 * corresponding flag in smb_fflags and set or clear the matching
3706 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3707 max_fmask |= info2_flags_map[i].smb_fflag;
3708 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3709 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3710 *stat_fflags |= info2_flags_map[i].stat_fflag;
3712 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3717 /* If smb_fmask is asking to set any bits that are not supported by
3718 * our flag mappings, we should fail.
3720 if ((smb_fmask & max_fmask) != smb_fmask) {
3728 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3729 * of file flags and birth (create) time.
3731 static char *store_file_unix_basic_info2(connection_struct *conn,
3734 const SMB_STRUCT_STAT *psbuf)
3736 uint32 file_flags = 0;
3737 uint32 flags_mask = 0;
3739 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3741 /* Create (birth) time 64 bit */
3742 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3745 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3746 SIVAL(pdata, 0, file_flags); /* flags */
3747 SIVAL(pdata, 4, flags_mask); /* mask */
3753 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3754 const struct stream_struct *streams,
3756 unsigned int max_data_bytes,
3757 unsigned int *data_size)
3760 unsigned int ofs = 0;
3762 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3763 unsigned int next_offset;
3765 smb_ucs2_t *namebuf;
3767 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3768 streams[i].name, &namelen) ||
3771 return NT_STATUS_INVALID_PARAMETER;
3775 * name_buf is now null-terminated, we need to marshall as not
3781 SIVAL(data, ofs+4, namelen);
3782 SOFF_T(data, ofs+8, streams[i].size);
3783 SOFF_T(data, ofs+16, streams[i].alloc_size);
3784 memcpy(data+ofs+24, namebuf, namelen);
3785 TALLOC_FREE(namebuf);
3787 next_offset = ofs + 24 + namelen;
3789 if (i == num_streams-1) {
3790 SIVAL(data, ofs, 0);
3793 unsigned int align = ndr_align_size(next_offset, 8);
3795 memset(data+next_offset, 0, align);
3796 next_offset += align;
3798 SIVAL(data, ofs, next_offset - ofs);
3807 return NT_STATUS_OK;
3810 /****************************************************************************
3811 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3812 ****************************************************************************/
3814 static void call_trans2qpipeinfo(connection_struct *conn,
3815 struct smb_request *req,
3816 unsigned int tran_call,
3817 char **pparams, int total_params,
3818 char **ppdata, int total_data,
3819 unsigned int max_data_bytes)
3821 char *params = *pparams;
3822 char *pdata = *ppdata;
3823 unsigned int data_size = 0;
3824 unsigned int param_size = 2;
3829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3833 if (total_params < 4) {
3834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3838 fsp = file_fsp(req, SVAL(params,0));
3839 if (!fsp_is_np(fsp)) {
3840 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3844 info_level = SVAL(params,2);
3846 *pparams = (char *)SMB_REALLOC(*pparams,2);
3847 if (*pparams == NULL) {
3848 reply_nterror(req, NT_STATUS_NO_MEMORY);
3853 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3854 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3855 if (*ppdata == NULL ) {
3856 reply_nterror(req, NT_STATUS_NO_MEMORY);
3861 switch (info_level) {
3862 case SMB_FILE_STANDARD_INFORMATION:
3864 SOFF_T(pdata,0,4096LL);
3871 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3875 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3881 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3882 TALLOC_CTX *mem_ctx,
3883 uint16_t info_level,
3885 const struct smb_filename *smb_fname,
3886 bool delete_pending,
3887 struct timespec write_time_ts,
3889 struct ea_list *ea_list,
3890 int lock_data_count,
3893 unsigned int max_data_bytes,
3895 unsigned int *pdata_size)
3897 char *pdata = *ppdata;
3898 char *dstart, *dend;
3899 unsigned int data_size;
3900 struct timespec create_time_ts, mtime_ts, atime_ts;
3901 time_t create_time, mtime, atime;
3902 SMB_STRUCT_STAT sbuf;
3910 uint64_t file_size = 0;
3912 uint64_t allocation_size = 0;
3913 uint64_t file_index = 0;
3914 uint32_t access_mask = 0;
3916 sbuf = smb_fname->st;
3918 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3919 return NT_STATUS_INVALID_LEVEL;
3922 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
3923 if (!NT_STATUS_IS_OK(status)) {
3927 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
3928 fname, fsp ? fsp->fnum : -1, info_level, max_data_bytes));
3931 mode = dos_mode_msdfs(conn, smb_fname);
3933 mode = dos_mode(conn, smb_fname);
3936 mode = FILE_ATTRIBUTE_NORMAL;
3938 nlink = sbuf.st_ex_nlink;
3940 if (nlink && (mode&aDIR)) {
3944 if ((nlink > 0) && delete_pending) {
3948 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3949 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3950 if (*ppdata == NULL) {
3951 return NT_STATUS_NO_MEMORY;
3955 dend = dstart + data_size - 1;
3957 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
3958 update_stat_ex_mtime(&sbuf, write_time_ts);
3961 create_time_ts = sbuf.st_ex_btime;
3962 mtime_ts = sbuf.st_ex_mtime;
3963 atime_ts = sbuf.st_ex_atime;
3965 if (lp_dos_filetime_resolution(SNUM(conn))) {
3966 dos_filetime_timespec(&create_time_ts);
3967 dos_filetime_timespec(&mtime_ts);
3968 dos_filetime_timespec(&atime_ts);
3971 create_time = convert_timespec_to_time_t(create_time_ts);
3972 mtime = convert_timespec_to_time_t(mtime_ts);
3973 atime = convert_timespec_to_time_t(atime_ts);
3975 p = strrchr_m(smb_fname->base_name,'/');
3977 base_name = smb_fname->base_name;
3981 /* NT expects the name to be in an exact form of the *full*
3982 filename. See the trans2 torture test */
3983 if (ISDOT(base_name)) {
3984 dos_fname = talloc_strdup(mem_ctx, "\\");
3986 return NT_STATUS_NO_MEMORY;
3989 dos_fname = talloc_asprintf(mem_ctx,
3993 return NT_STATUS_NO_MEMORY;
3995 string_replace(dos_fname, '/', '\\');
3998 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4001 /* Do we have this path open ? */
4003 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4004 fsp1 = file_find_di_first(fileid);
4005 if (fsp1 && fsp1->initial_allocation_size) {
4006 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4010 if (!(mode & aDIR)) {
4011 file_size = get_file_size_stat(&sbuf);
4014 if (fsp && fsp->fh) {
4015 pos = fsp->fh->position_information;
4019 access_mask = fsp->access_mask;
4021 /* GENERIC_EXECUTE mapping from Windows */
4022 access_mask = 0x12019F;
4025 /* This should be an index number - looks like
4028 I think this causes us to fail the IFSKIT
4029 BasicFileInformationTest. -tpot */
4030 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4031 file_index |= ((sbuf.st_ex_dev) & UINT32_MAX) << 32; /* FileIndexHigh */
4033 switch (info_level) {
4034 case SMB_INFO_STANDARD:
4035 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4037 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4038 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4039 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4040 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4041 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4042 SSVAL(pdata,l1_attrFile,mode);
4045 case SMB_INFO_QUERY_EA_SIZE:
4047 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4048 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4050 srv_put_dos_date2(pdata,0,create_time);
4051 srv_put_dos_date2(pdata,4,atime);
4052 srv_put_dos_date2(pdata,8,mtime); /* write time */
4053 SIVAL(pdata,12,(uint32)file_size);
4054 SIVAL(pdata,16,(uint32)allocation_size);
4055 SSVAL(pdata,20,mode);
4056 SIVAL(pdata,22,ea_size);
4060 case SMB_INFO_IS_NAME_VALID:
4061 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4063 /* os/2 needs this ? really ?*/
4064 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4066 /* This is only reached for qpathinfo */
4070 case SMB_INFO_QUERY_EAS_FROM_LIST:
4072 size_t total_ea_len = 0;
4073 struct ea_list *ea_file_list = NULL;
4075 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4077 ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4078 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4080 if (!ea_list || (total_ea_len > data_size)) {
4082 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4086 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4090 case SMB_INFO_QUERY_ALL_EAS:
4092 /* We have data_size bytes to put EA's into. */
4093 size_t total_ea_len = 0;
4095 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4097 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4098 if (!ea_list || (total_ea_len > data_size)) {
4100 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4104 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4108 case SMB_FILE_BASIC_INFORMATION:
4109 case SMB_QUERY_FILE_BASIC_INFO:
4111 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4112 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4113 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4115 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4119 put_long_date_timespec(pdata,create_time_ts);
4120 put_long_date_timespec(pdata+8,atime_ts);
4121 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4122 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4123 SIVAL(pdata,32,mode);
4125 DEBUG(5,("SMB_QFBI - "));
4126 DEBUG(5,("create: %s ", ctime(&create_time)));
4127 DEBUG(5,("access: %s ", ctime(&atime)));
4128 DEBUG(5,("write: %s ", ctime(&mtime)));
4129 DEBUG(5,("change: %s ", ctime(&mtime)));
4130 DEBUG(5,("mode: %x\n", mode));
4133 case SMB_FILE_STANDARD_INFORMATION:
4134 case SMB_QUERY_FILE_STANDARD_INFO:
4136 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4138 SOFF_T(pdata,0,allocation_size);
4139 SOFF_T(pdata,8,file_size);
4140 SIVAL(pdata,16,nlink);
4141 SCVAL(pdata,20,delete_pending?1:0);
4142 SCVAL(pdata,21,(mode&aDIR)?1:0);
4143 SSVAL(pdata,22,0); /* Padding. */
4146 case SMB_FILE_EA_INFORMATION:
4147 case SMB_QUERY_FILE_EA_INFO:
4149 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4150 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4152 SIVAL(pdata,0,ea_size);
4156 /* Get the 8.3 name - used if NT SMB was negotiated. */
4157 case SMB_QUERY_FILE_ALT_NAME_INFO:
4158 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4161 char mangled_name[13];
4162 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4163 if (!name_to_8_3(base_name,mangled_name,
4164 True,conn->params)) {
4165 return NT_STATUS_NO_MEMORY;
4167 len = srvstr_push(dstart, flags2,
4168 pdata+4, mangled_name,
4169 PTR_DIFF(dend, pdata+4),
4171 data_size = 4 + len;
4176 case SMB_QUERY_FILE_NAME_INFO:
4180 this must be *exactly* right for ACLs on mapped drives to work
4182 len = srvstr_push(dstart, flags2,
4184 PTR_DIFF(dend, pdata+4),
4186 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4187 data_size = 4 + len;
4192 case SMB_FILE_ALLOCATION_INFORMATION:
4193 case SMB_QUERY_FILE_ALLOCATION_INFO:
4194 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4196 SOFF_T(pdata,0,allocation_size);
4199 case SMB_FILE_END_OF_FILE_INFORMATION:
4200 case SMB_QUERY_FILE_END_OF_FILEINFO:
4201 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4203 SOFF_T(pdata,0,file_size);
4206 case SMB_QUERY_FILE_ALL_INFO:
4207 case SMB_FILE_ALL_INFORMATION:
4210 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4211 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4212 put_long_date_timespec(pdata,create_time_ts);
4213 put_long_date_timespec(pdata+8,atime_ts);
4214 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4215 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4216 SIVAL(pdata,32,mode);
4217 SIVAL(pdata,36,0); /* padding. */
4219 SOFF_T(pdata,0,allocation_size);
4220 SOFF_T(pdata,8,file_size);
4221 SIVAL(pdata,16,nlink);
4222 SCVAL(pdata,20,delete_pending);
4223 SCVAL(pdata,21,(mode&aDIR)?1:0);
4226 SIVAL(pdata,0,ea_size);
4227 pdata += 4; /* EA info */
4228 len = srvstr_push(dstart, flags2,
4230 PTR_DIFF(dend, pdata+4),
4234 data_size = PTR_DIFF(pdata,(*ppdata));
4238 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4241 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4242 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4243 put_long_date_timespec(pdata+0x00,create_time_ts);
4244 put_long_date_timespec(pdata+0x08,atime_ts);
4245 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4246 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4247 SIVAL(pdata, 0x20, mode);
4248 SIVAL(pdata, 0x24, 0); /* padding. */
4249 SBVAL(pdata, 0x28, allocation_size);
4250 SBVAL(pdata, 0x30, file_size);
4251 SIVAL(pdata, 0x38, nlink);
4252 SCVAL(pdata, 0x3C, delete_pending);
4253 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4254 SSVAL(pdata, 0x3E, 0); /* padding */
4255 SBVAL(pdata, 0x40, file_index);
4256 SIVAL(pdata, 0x48, ea_size);
4257 SIVAL(pdata, 0x4C, access_mask);
4258 SBVAL(pdata, 0x50, pos);
4259 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4260 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4264 len = srvstr_push(dstart, flags2,
4266 PTR_DIFF(dend, pdata+4),
4270 data_size = PTR_DIFF(pdata,(*ppdata));
4273 case SMB_FILE_INTERNAL_INFORMATION:
4275 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4276 SBVAL(pdata, 0, file_index);
4280 case SMB_FILE_ACCESS_INFORMATION:
4281 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4282 SIVAL(pdata, 0, access_mask);
4286 case SMB_FILE_NAME_INFORMATION:
4287 /* Pathname with leading '\'. */
4290 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4291 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4292 SIVAL(pdata,0,byte_len);
4293 data_size = 4 + byte_len;
4297 case SMB_FILE_DISPOSITION_INFORMATION:
4298 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4300 SCVAL(pdata,0,delete_pending);
4303 case SMB_FILE_POSITION_INFORMATION:
4304 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4306 SOFF_T(pdata,0,pos);
4309 case SMB_FILE_MODE_INFORMATION:
4310 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4311 SIVAL(pdata,0,mode);
4315 case SMB_FILE_ALIGNMENT_INFORMATION:
4316 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4317 SIVAL(pdata,0,0); /* No alignment needed. */
4322 * NT4 server just returns "invalid query" to this - if we try
4323 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4326 /* The first statement above is false - verified using Thursby
4327 * client against NT4 -- gcolley.
4329 case SMB_QUERY_FILE_STREAM_INFO:
4330 case SMB_FILE_STREAM_INFORMATION: {
4331 unsigned int num_streams;
4332 struct stream_struct *streams;
4334 DEBUG(10,("smbd_do_qfilepathinfo: "
4335 "SMB_FILE_STREAM_INFORMATION\n"));
4337 status = SMB_VFS_STREAMINFO(
4338 conn, fsp, fname, talloc_tos(),
4339 &num_streams, &streams);
4341 if (!NT_STATUS_IS_OK(status)) {
4342 DEBUG(10, ("could not get stream info: %s\n",
4343 nt_errstr(status)));
4347 status = marshall_stream_info(num_streams, streams,
4348 pdata, max_data_bytes,
4351 if (!NT_STATUS_IS_OK(status)) {
4352 DEBUG(10, ("marshall_stream_info failed: %s\n",
4353 nt_errstr(status)));
4357 TALLOC_FREE(streams);
4361 case SMB_QUERY_COMPRESSION_INFO:
4362 case SMB_FILE_COMPRESSION_INFORMATION:
4363 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4364 SOFF_T(pdata,0,file_size);
4365 SIVAL(pdata,8,0); /* ??? */
4366 SIVAL(pdata,12,0); /* ??? */
4370 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4371 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4372 put_long_date_timespec(pdata,create_time_ts);
4373 put_long_date_timespec(pdata+8,atime_ts);
4374 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4375 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4376 SOFF_T(pdata,32,allocation_size);
4377 SOFF_T(pdata,40,file_size);
4378 SIVAL(pdata,48,mode);
4379 SIVAL(pdata,52,0); /* ??? */
4383 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4384 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4385 SIVAL(pdata,0,mode);
4391 * CIFS UNIX Extensions.
4394 case SMB_QUERY_FILE_UNIX_BASIC:
4396 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4397 data_size = PTR_DIFF(pdata,(*ppdata));
4401 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4403 for (i=0; i<100; i++)
4404 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4410 case SMB_QUERY_FILE_UNIX_INFO2:
4412 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4413 data_size = PTR_DIFF(pdata,(*ppdata));
4417 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4419 for (i=0; i<100; i++)
4420 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4426 case SMB_QUERY_FILE_UNIX_LINK:
4429 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4432 return NT_STATUS_NO_MEMORY;
4435 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4437 if(!S_ISLNK(sbuf.st_ex_mode)) {
4438 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4441 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4443 len = SMB_VFS_READLINK(conn,fname,
4446 return map_nt_error_from_unix(errno);
4449 len = srvstr_push(dstart, flags2,
4451 PTR_DIFF(dend, pdata),
4454 data_size = PTR_DIFF(pdata,(*ppdata));
4459 #if defined(HAVE_POSIX_ACLS)
4460 case SMB_QUERY_POSIX_ACL:
4462 SMB_ACL_T file_acl = NULL;
4463 SMB_ACL_T def_acl = NULL;
4464 uint16 num_file_acls = 0;
4465 uint16 num_def_acls = 0;
4467 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4468 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4470 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4473 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4474 DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4476 return NT_STATUS_NOT_IMPLEMENTED;
4479 if (S_ISDIR(sbuf.st_ex_mode)) {
4480 if (fsp && fsp->is_directory) {
4481 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4483 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4485 def_acl = free_empty_sys_acl(conn, def_acl);
4488 num_file_acls = count_acl_entries(conn, file_acl);
4489 num_def_acls = count_acl_entries(conn, def_acl);
4491 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4492 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4494 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4495 SMB_POSIX_ACL_HEADER_SIZE) ));
4497 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4500 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4502 return NT_STATUS_BUFFER_TOO_SMALL;
4505 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4506 SSVAL(pdata,2,num_file_acls);
4507 SSVAL(pdata,4,num_def_acls);
4508 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4510 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4513 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4515 return NT_STATUS_INTERNAL_ERROR;
4517 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4519 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4522 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4524 return NT_STATUS_INTERNAL_ERROR;
4528 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4531 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4533 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4539 case SMB_QUERY_POSIX_LOCK:
4544 enum brl_type lock_type;
4546 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4547 return NT_STATUS_INVALID_PARAMETER;
4550 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4551 case POSIX_LOCK_TYPE_READ:
4552 lock_type = READ_LOCK;
4554 case POSIX_LOCK_TYPE_WRITE:
4555 lock_type = WRITE_LOCK;
4557 case POSIX_LOCK_TYPE_UNLOCK:
4559 /* There's no point in asking for an unlock... */
4560 return NT_STATUS_INVALID_PARAMETER;
4563 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4564 #if defined(HAVE_LONGLONG)
4565 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4566 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4567 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4568 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4569 #else /* HAVE_LONGLONG */
4570 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4571 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4572 #endif /* HAVE_LONGLONG */
4574 status = query_lock(fsp,
4581 if (ERROR_WAS_LOCK_DENIED(status)) {
4582 /* Here we need to report who has it locked... */
4583 data_size = POSIX_LOCK_DATA_SIZE;
4585 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4586 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4587 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4588 #if defined(HAVE_LONGLONG)
4589 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4590 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4591 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4592 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4593 #else /* HAVE_LONGLONG */
4594 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4595 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4596 #endif /* HAVE_LONGLONG */
4598 } else if (NT_STATUS_IS_OK(status)) {
4599 /* For success we just return a copy of what we sent
4600 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4601 data_size = POSIX_LOCK_DATA_SIZE;
4602 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4603 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4611 return NT_STATUS_INVALID_LEVEL;
4614 *pdata_size = data_size;
4615 return NT_STATUS_OK;
4618 /****************************************************************************
4619 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4620 file name or file id).
4621 ****************************************************************************/
4623 static void call_trans2qfilepathinfo(connection_struct *conn,
4624 struct smb_request *req,
4625 unsigned int tran_call,
4626 char **pparams, int total_params,
4627 char **ppdata, int total_data,
4628 unsigned int max_data_bytes)
4630 char *params = *pparams;
4631 char *pdata = *ppdata;
4633 unsigned int data_size = 0;
4634 unsigned int param_size = 2;
4636 struct smb_filename *smb_fname = NULL;
4637 bool delete_pending = False;
4638 struct timespec write_time_ts;
4639 files_struct *fsp = NULL;
4640 struct file_id fileid;
4641 struct ea_list *ea_list = NULL;
4642 int lock_data_count = 0;
4643 char *lock_data = NULL;
4644 bool ms_dfs_link = false;
4645 NTSTATUS status = NT_STATUS_OK;
4648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4652 ZERO_STRUCT(write_time_ts);
4654 if (tran_call == TRANSACT2_QFILEINFO) {
4655 if (total_params < 4) {
4656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4661 call_trans2qpipeinfo(conn, req, tran_call,
4662 pparams, total_params,
4668 fsp = file_fsp(req, SVAL(params,0));
4669 info_level = SVAL(params,2);
4671 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4673 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4674 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4678 /* Initial check for valid fsp ptr. */
4679 if (!check_fsp_open(conn, req, fsp)) {
4683 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
4685 reply_nterror(req, NT_STATUS_NO_MEMORY);
4689 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
4691 if (!NT_STATUS_IS_OK(status)) {
4692 reply_nterror(req, status);
4696 if(fsp->fake_file_handle) {
4698 * This is actually for the QUOTA_FAKE_FILE --metze
4701 /* We know this name is ok, it's already passed the checks. */
4703 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
4705 * This is actually a QFILEINFO on a directory
4706 * handle (returned from an NT SMB). NT5.0 seems
4707 * to do this call. JRA.
4710 if (INFO_LEVEL_IS_UNIX(info_level)) {
4711 /* Always do lstat for UNIX calls. */
4712 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4713 DEBUG(3,("call_trans2qfilepathinfo: "
4714 "SMB_VFS_LSTAT of %s failed "
4716 smb_fname_str_dbg(smb_fname),
4719 map_nt_error_from_unix(errno));
4722 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4723 DEBUG(3,("call_trans2qfilepathinfo: "
4724 "SMB_VFS_STAT of %s failed (%s)\n",
4725 smb_fname_str_dbg(smb_fname),
4728 map_nt_error_from_unix(errno));
4732 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4733 get_file_infos(fileid, &delete_pending, &write_time_ts);
4736 * Original code - this is an open file.
4738 if (!check_fsp(conn, req, fsp)) {
4742 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4743 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4744 fsp->fnum, strerror(errno)));
4746 map_nt_error_from_unix(errno));
4749 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4750 get_file_infos(fileid, &delete_pending, &write_time_ts);
4755 if (total_params < 7) {
4756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4760 info_level = SVAL(params,0);
4762 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4764 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4765 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4769 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4771 STR_TERMINATE, &status);
4772 if (!NT_STATUS_IS_OK(status)) {
4773 reply_nterror(req, status);
4777 status = filename_convert(req,
4779 req->flags2 & FLAGS2_DFS_PATHNAMES,
4783 if (!NT_STATUS_IS_OK(status)) {
4784 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4785 reply_botherror(req,
4786 NT_STATUS_PATH_NOT_COVERED,
4787 ERRSRV, ERRbadpath);
4790 reply_nterror(req, status);
4794 /* If this is a stream, check if there is a delete_pending. */
4795 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4796 && is_ntfs_stream_smb_fname(smb_fname)) {
4797 struct smb_filename *smb_fname_base = NULL;
4799 /* Create an smb_filename with stream_name == NULL. */
4801 create_synthetic_smb_fname(talloc_tos(),
4802 smb_fname->base_name,
4805 if (!NT_STATUS_IS_OK(status)) {
4806 reply_nterror(req, status);
4810 if (INFO_LEVEL_IS_UNIX(info_level)) {
4811 /* Always do lstat for UNIX calls. */
4812 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4813 DEBUG(3,("call_trans2qfilepathinfo: "
4814 "SMB_VFS_LSTAT of %s failed "
4816 smb_fname_str_dbg(smb_fname_base),
4818 TALLOC_FREE(smb_fname_base);
4820 map_nt_error_from_unix(errno));
4824 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4825 DEBUG(3,("call_trans2qfilepathinfo: "
4826 "fileinfo of %s failed "
4828 smb_fname_str_dbg(smb_fname_base),
4830 TALLOC_FREE(smb_fname_base);
4832 map_nt_error_from_unix(errno));
4837 fileid = vfs_file_id_from_sbuf(conn,
4838 &smb_fname_base->st);
4839 TALLOC_FREE(smb_fname_base);
4840 get_file_infos(fileid, &delete_pending, NULL);
4841 if (delete_pending) {
4842 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4847 if (INFO_LEVEL_IS_UNIX(info_level)) {
4848 /* Always do lstat for UNIX calls. */
4849 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4850 DEBUG(3,("call_trans2qfilepathinfo: "
4851 "SMB_VFS_LSTAT of %s failed (%s)\n",
4852 smb_fname_str_dbg(smb_fname),
4855 map_nt_error_from_unix(errno));
4859 } else if (!VALID_STAT(smb_fname->st) &&
4860 SMB_VFS_STAT(conn, smb_fname) &&
4861 (info_level != SMB_INFO_IS_NAME_VALID)) {
4862 ms_dfs_link = check_msdfs_link(conn, fname,
4866 DEBUG(3,("call_trans2qfilepathinfo: "
4867 "SMB_VFS_STAT of %s failed (%s)\n",
4868 smb_fname_str_dbg(smb_fname),
4871 map_nt_error_from_unix(errno));
4876 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4877 get_file_infos(fileid, &delete_pending, &write_time_ts);
4878 if (delete_pending) {
4879 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4884 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4885 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4887 /* Pull out any data sent here before we realloc. */
4888 switch (info_level) {
4889 case SMB_INFO_QUERY_EAS_FROM_LIST:
4891 /* Pull any EA list from the data portion. */
4894 if (total_data < 4) {
4896 req, NT_STATUS_INVALID_PARAMETER);
4899 ea_size = IVAL(pdata,0);
4901 if (total_data > 0 && ea_size != total_data) {
4902 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4903 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4905 req, NT_STATUS_INVALID_PARAMETER);
4909 if (!lp_ea_support(SNUM(conn))) {
4910 reply_doserror(req, ERRDOS,
4911 ERReasnotsupported);
4915 /* Pull out the list of names. */
4916 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
4919 req, NT_STATUS_INVALID_PARAMETER);
4925 case SMB_QUERY_POSIX_LOCK:
4927 if (fsp == NULL || fsp->fh->fd == -1) {
4928 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4932 if (total_data != POSIX_LOCK_DATA_SIZE) {
4934 req, NT_STATUS_INVALID_PARAMETER);
4938 /* Copy the lock range data. */
4939 lock_data = (char *)TALLOC_MEMDUP(
4940 req, pdata, total_data);
4942 reply_nterror(req, NT_STATUS_NO_MEMORY);
4945 lock_data_count = total_data;
4951 *pparams = (char *)SMB_REALLOC(*pparams,2);
4952 if (*pparams == NULL) {
4953 reply_nterror(req, NT_STATUS_NO_MEMORY);
4960 * draft-leach-cifs-v1-spec-02.txt
4961 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
4964 * The requested information is placed in the Data portion of the
4965 * transaction response. For the information levels greater than 0x100,
4966 * the transaction response has 1 parameter word which should be
4967 * ignored by the client.
4969 * However Windows only follows this rule for the IS_NAME_VALID call.
4971 switch (info_level) {
4972 case SMB_INFO_IS_NAME_VALID:
4977 if ((info_level & 0xFF00) == 0xFF00) {
4979 * We use levels that start with 0xFF00
4980 * internally to represent SMB2 specific levels
4982 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4986 status = smbd_do_qfilepathinfo(conn, req, info_level,
4988 delete_pending, write_time_ts,
4989 ms_dfs_link, ea_list,
4990 lock_data_count, lock_data,
4991 req->flags2, max_data_bytes,
4992 ppdata, &data_size);
4993 if (!NT_STATUS_IS_OK(status)) {
4994 reply_nterror(req, status);
4998 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5004 /****************************************************************************
5005 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5007 ****************************************************************************/
5009 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5010 connection_struct *conn,
5011 const struct smb_filename *smb_fname_old,
5012 const struct smb_filename *smb_fname_new)
5014 char *oldname = NULL;
5015 char *newname = NULL;
5016 NTSTATUS status = NT_STATUS_OK;
5018 /* source must already exist. */
5019 if (!VALID_STAT(smb_fname_old->st)) {
5020 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5023 /* Disallow if newname already exists. */
5024 if (VALID_STAT(smb_fname_new->st)) {
5025 return NT_STATUS_OBJECT_NAME_COLLISION;
5028 /* No links from a directory. */
5029 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5030 return NT_STATUS_FILE_IS_A_DIRECTORY;
5033 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
5034 if (!NT_STATUS_IS_OK(status)) {
5037 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
5038 if (!NT_STATUS_IS_OK(status)) {
5042 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
5044 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
5045 status = map_nt_error_from_unix(errno);
5046 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5047 nt_errstr(status), newname, oldname));
5050 TALLOC_FREE(newname);
5051 TALLOC_FREE(oldname);
5055 /****************************************************************************
5056 Deal with setting the time from any of the setfilepathinfo functions.
5057 ****************************************************************************/
5059 NTSTATUS smb_set_file_time(connection_struct *conn,
5061 const struct smb_filename *smb_fname,
5062 struct smb_file_time *ft,
5063 bool setting_write_time)
5065 struct smb_filename *smb_fname_base = NULL;
5067 FILE_NOTIFY_CHANGE_LAST_ACCESS
5068 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5071 if (!VALID_STAT(smb_fname->st)) {
5072 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5075 /* get some defaults (no modifications) if any info is zero or -1. */
5076 if (null_timespec(ft->atime)) {
5077 ft->atime= smb_fname->st.st_ex_atime;
5078 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5081 if (null_timespec(ft->mtime)) {
5082 ft->mtime = smb_fname->st.st_ex_mtime;
5083 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5086 if (!setting_write_time) {
5087 /* ft->mtime comes from change time, not write time. */
5088 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5091 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5092 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5093 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5094 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5095 if (!null_timespec(ft->create_time)) {
5096 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5097 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5101 * Try and set the times of this file if
5102 * they are different from the current values.
5106 struct timespec mts = smb_fname->st.st_ex_mtime;
5107 struct timespec ats = smb_fname->st.st_ex_atime;
5108 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5109 (timespec_compare(&ft->mtime, &mts) == 0)) {
5110 return NT_STATUS_OK;
5114 if (setting_write_time) {
5116 * This was a Windows setfileinfo on an open file.
5117 * NT does this a lot. We also need to
5118 * set the time here, as it can be read by
5119 * FindFirst/FindNext and with the patch for bug #2045
5120 * in smbd/fileio.c it ensures that this timestamp is
5121 * kept sticky even after a write. We save the request
5122 * away and will set it on file close and after a write. JRA.
5125 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5126 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5129 if (fsp->base_fsp) {
5130 set_sticky_write_time_fsp(fsp->base_fsp,
5133 set_sticky_write_time_fsp(fsp, ft->mtime);
5136 set_sticky_write_time_path(
5137 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5142 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5144 /* Always call ntimes on the base, even if a stream was passed in. */
5145 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5146 NULL, &smb_fname->st,
5148 if (!NT_STATUS_IS_OK(status)) {
5152 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5153 TALLOC_FREE(smb_fname_base);
5154 return map_nt_error_from_unix(errno);
5156 TALLOC_FREE(smb_fname_base);
5158 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5159 smb_fname->base_name);
5160 return NT_STATUS_OK;
5163 /****************************************************************************
5164 Deal with setting the dosmode from any of the setfilepathinfo functions.
5165 ****************************************************************************/
5167 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5168 const struct smb_filename *smb_fname,
5171 struct smb_filename *smb_fname_base = NULL;
5174 if (!VALID_STAT(smb_fname->st)) {
5175 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5178 /* Always operate on the base_name, even if a stream was passed in. */
5179 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5180 NULL, &smb_fname->st,
5182 if (!NT_STATUS_IS_OK(status)) {
5187 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5194 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5196 /* check the mode isn't different, before changing it */
5197 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5198 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5199 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5200 (unsigned int)dosmode));
5202 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5204 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5206 smb_fname_str_dbg(smb_fname_base),
5208 status = map_nt_error_from_unix(errno);
5212 status = NT_STATUS_OK;
5214 TALLOC_FREE(smb_fname_base);
5218 /****************************************************************************
5219 Deal with setting the size from any of the setfilepathinfo functions.
5220 ****************************************************************************/
5222 static NTSTATUS smb_set_file_size(connection_struct *conn,
5223 struct smb_request *req,
5225 const struct smb_filename *smb_fname,
5226 const SMB_STRUCT_STAT *psbuf,
5229 NTSTATUS status = NT_STATUS_OK;
5230 struct smb_filename *smb_fname_tmp = NULL;
5231 files_struct *new_fsp = NULL;
5233 if (!VALID_STAT(*psbuf)) {
5234 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5237 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5239 if (size == get_file_size_stat(psbuf)) {
5240 return NT_STATUS_OK;
5243 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5244 smb_fname_str_dbg(smb_fname), (double)size));
5246 if (fsp && fsp->fh->fd != -1) {
5247 /* Handle based call. */
5248 if (vfs_set_filelen(fsp, size) == -1) {
5249 return map_nt_error_from_unix(errno);
5251 trigger_write_time_update_immediate(fsp);
5252 return NT_STATUS_OK;
5255 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5256 if (!NT_STATUS_IS_OK(status)) {
5260 smb_fname_tmp->st = *psbuf;
5262 status = SMB_VFS_CREATE_FILE(
5265 0, /* root_dir_fid */
5266 smb_fname_tmp, /* fname */
5267 FILE_WRITE_ATTRIBUTES, /* access_mask */
5268 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5270 FILE_OPEN, /* create_disposition*/
5271 0, /* create_options */
5272 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5273 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5274 0, /* allocation_size */
5277 &new_fsp, /* result */
5280 TALLOC_FREE(smb_fname_tmp);
5282 if (!NT_STATUS_IS_OK(status)) {
5283 /* NB. We check for open_was_deferred in the caller. */
5287 if (vfs_set_filelen(new_fsp, size) == -1) {
5288 status = map_nt_error_from_unix(errno);
5289 close_file(req, new_fsp,NORMAL_CLOSE);
5293 trigger_write_time_update_immediate(new_fsp);
5294 close_file(req, new_fsp,NORMAL_CLOSE);
5295 return NT_STATUS_OK;
5298 /****************************************************************************
5299 Deal with SMB_INFO_SET_EA.
5300 ****************************************************************************/
5302 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5306 const struct smb_filename *smb_fname)
5308 struct ea_list *ea_list = NULL;
5309 TALLOC_CTX *ctx = NULL;
5310 NTSTATUS status = NT_STATUS_OK;
5312 if (total_data < 10) {
5314 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5315 length. They seem to have no effect. Bug #3212. JRA */
5317 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5318 /* We're done. We only get EA info in this call. */
5319 return NT_STATUS_OK;
5322 return NT_STATUS_INVALID_PARAMETER;
5325 if (IVAL(pdata,0) > total_data) {
5326 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5327 IVAL(pdata,0), (unsigned int)total_data));
5328 return NT_STATUS_INVALID_PARAMETER;
5332 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5334 return NT_STATUS_INVALID_PARAMETER;
5336 status = set_ea(conn, fsp, smb_fname, ea_list);
5341 /****************************************************************************
5342 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5343 ****************************************************************************/
5345 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5349 const struct smb_filename *smb_fname)
5351 NTSTATUS status = NT_STATUS_OK;
5352 bool delete_on_close;
5355 if (total_data < 1) {
5356 return NT_STATUS_INVALID_PARAMETER;
5360 return NT_STATUS_INVALID_HANDLE;
5363 delete_on_close = (CVAL(pdata,0) ? True : False);
5364 dosmode = dos_mode(conn, smb_fname);
5366 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5367 "delete_on_close = %u\n",
5368 smb_fname_str_dbg(smb_fname),
5369 (unsigned int)dosmode,
5370 (unsigned int)delete_on_close ));
5372 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5374 if (!NT_STATUS_IS_OK(status)) {
5378 /* The set is across all open files on this dev/inode pair. */
5379 if (!set_delete_on_close(fsp, delete_on_close,
5380 &conn->server_info->utok)) {
5381 return NT_STATUS_ACCESS_DENIED;
5383 return NT_STATUS_OK;
5386 /****************************************************************************
5387 Deal with SMB_FILE_POSITION_INFORMATION.
5388 ****************************************************************************/
5390 static NTSTATUS smb_file_position_information(connection_struct *conn,
5395 uint64_t position_information;
5397 if (total_data < 8) {
5398 return NT_STATUS_INVALID_PARAMETER;
5402 /* Ignore on pathname based set. */
5403 return NT_STATUS_OK;
5406 position_information = (uint64_t)IVAL(pdata,0);
5407 #ifdef LARGE_SMB_OFF_T
5408 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5409 #else /* LARGE_SMB_OFF_T */
5410 if (IVAL(pdata,4) != 0) {
5411 /* more than 32 bits? */
5412 return NT_STATUS_INVALID_PARAMETER;
5414 #endif /* LARGE_SMB_OFF_T */
5416 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5417 fsp->fsp_name, (double)position_information ));
5418 fsp->fh->position_information = position_information;
5419 return NT_STATUS_OK;
5422 /****************************************************************************
5423 Deal with SMB_FILE_MODE_INFORMATION.
5424 ****************************************************************************/
5426 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5432 if (total_data < 4) {
5433 return NT_STATUS_INVALID_PARAMETER;
5435 mode = IVAL(pdata,0);
5436 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5437 return NT_STATUS_INVALID_PARAMETER;
5439 return NT_STATUS_OK;
5442 /****************************************************************************
5443 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5444 ****************************************************************************/
5446 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5447 struct smb_request *req,
5452 char *link_target = NULL;
5453 const char *newname = fname;
5454 NTSTATUS status = NT_STATUS_OK;
5455 TALLOC_CTX *ctx = talloc_tos();
5457 /* Set a symbolic link. */
5458 /* Don't allow this if follow links is false. */
5460 if (total_data == 0) {
5461 return NT_STATUS_INVALID_PARAMETER;
5464 if (!lp_symlinks(SNUM(conn))) {
5465 return NT_STATUS_ACCESS_DENIED;
5468 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5469 total_data, STR_TERMINATE);
5472 return NT_STATUS_INVALID_PARAMETER;
5475 /* !widelinks forces the target path to be within the share. */
5476 /* This means we can interpret the target as a pathname. */
5477 if (!lp_widelinks(SNUM(conn))) {
5478 char *rel_name = NULL;
5479 char *last_dirp = NULL;
5481 if (*link_target == '/') {
5482 /* No absolute paths allowed. */
5483 return NT_STATUS_ACCESS_DENIED;
5485 rel_name = talloc_strdup(ctx,newname);
5487 return NT_STATUS_NO_MEMORY;
5489 last_dirp = strrchr_m(rel_name, '/');
5491 last_dirp[1] = '\0';
5493 rel_name = talloc_strdup(ctx,"./");
5495 return NT_STATUS_NO_MEMORY;
5498 rel_name = talloc_asprintf_append(rel_name,
5502 return NT_STATUS_NO_MEMORY;
5505 status = check_name(conn, rel_name);
5506 if (!NT_STATUS_IS_OK(status)) {
5511 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5512 newname, link_target ));
5514 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5515 return map_nt_error_from_unix(errno);
5518 return NT_STATUS_OK;
5521 /****************************************************************************
5522 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5523 ****************************************************************************/
5525 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5526 struct smb_request *req,
5527 const char *pdata, int total_data,
5528 const struct smb_filename *smb_fname_new)
5530 char *oldname = NULL;
5531 struct smb_filename *smb_fname_old = NULL;
5532 TALLOC_CTX *ctx = talloc_tos();
5533 NTSTATUS status = NT_STATUS_OK;
5535 /* Set a hard link. */
5536 if (total_data == 0) {
5537 return NT_STATUS_INVALID_PARAMETER;
5540 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5541 total_data, STR_TERMINATE, &status);
5542 if (!NT_STATUS_IS_OK(status)) {
5546 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5547 smb_fname_str_dbg(smb_fname_new), oldname));
5549 status = filename_convert(ctx,
5551 req->flags2 & FLAGS2_DFS_PATHNAMES,
5555 if (!NT_STATUS_IS_OK(status)) {
5559 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5562 /****************************************************************************
5563 Deal with SMB_FILE_RENAME_INFORMATION.
5564 ****************************************************************************/
5566 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5567 struct smb_request *req,
5576 char *newname = NULL;
5577 char *base_name = NULL;
5578 struct smb_filename *smb_fname = NULL;
5579 bool dest_has_wcard = False;
5580 NTSTATUS status = NT_STATUS_OK;
5582 TALLOC_CTX *ctx = talloc_tos();
5584 if (total_data < 13) {
5585 return NT_STATUS_INVALID_PARAMETER;
5588 overwrite = (CVAL(pdata,0) ? True : False);
5589 root_fid = IVAL(pdata,4);
5590 len = IVAL(pdata,8);
5592 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5593 return NT_STATUS_INVALID_PARAMETER;
5596 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5599 if (!NT_STATUS_IS_OK(status)) {
5603 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5606 status = resolve_dfspath_wcard(ctx, conn,
5607 req->flags2 & FLAGS2_DFS_PATHNAMES,
5611 if (!NT_STATUS_IS_OK(status)) {
5615 /* Check the new name has no '/' characters. */
5616 if (strchr_m(newname, '/')) {
5617 return NT_STATUS_NOT_SUPPORTED;
5620 if (fsp && fsp->base_fsp) {
5621 /* newname must be a stream name. */
5622 if (newname[0] != ':') {
5623 return NT_STATUS_NOT_SUPPORTED;
5626 /* Create an smb_fname to call rename_internals_fsp() with. */
5627 status = create_synthetic_smb_fname(talloc_tos(),
5628 fsp->base_fsp->fsp_name,
5629 newname, NULL, &smb_fname);
5630 if (!NT_STATUS_IS_OK(status)) {
5635 * Set the original last component, since
5636 * rename_internals_fsp() requires it.
5638 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5639 if (smb_fname->original_lcomp == NULL) {
5640 status = NT_STATUS_NO_MEMORY;
5644 /* Create a char * to call rename_internals() with. */
5645 base_name = talloc_asprintf(ctx, "%s%s",
5646 fsp->base_fsp->fsp_name,
5649 status = NT_STATUS_NO_MEMORY;
5653 /* newname must *not* be a stream name. */
5654 if (newname[0] == ':') {
5655 return NT_STATUS_NOT_SUPPORTED;
5658 /* Create the base directory. */
5659 base_name = talloc_strdup(ctx, fname);
5661 return NT_STATUS_NO_MEMORY;
5663 p = strrchr_m(base_name, '/');
5667 base_name = talloc_strdup(ctx, "./");
5669 return NT_STATUS_NO_MEMORY;
5672 /* Append the new name. */
5673 base_name = talloc_asprintf_append(base_name,
5677 return NT_STATUS_NO_MEMORY;
5680 status = unix_convert(ctx, conn, base_name, &smb_fname,
5683 /* If an error we expect this to be
5684 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5686 if (!NT_STATUS_IS_OK(status)) {
5687 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5691 /* Create an smb_fname to call rename_internals_fsp() */
5692 status = create_synthetic_smb_fname(talloc_tos(),
5695 if (!NT_STATUS_IS_OK(status)) {
5703 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5704 fsp->fnum, fsp->fsp_name, base_name ));
5705 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5708 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5709 fname, base_name ));
5710 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5711 overwrite, False, dest_has_wcard,
5712 FILE_WRITE_ATTRIBUTES);
5715 TALLOC_FREE(smb_fname);
5719 /****************************************************************************
5720 Deal with SMB_SET_POSIX_ACL.
5721 ****************************************************************************/
5723 #if defined(HAVE_POSIX_ACLS)
5724 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5729 SMB_STRUCT_STAT *psbuf)
5731 uint16 posix_acl_version;
5732 uint16 num_file_acls;
5733 uint16 num_def_acls;
5734 bool valid_file_acls = True;
5735 bool valid_def_acls = True;
5737 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5738 return NT_STATUS_INVALID_PARAMETER;
5740 posix_acl_version = SVAL(pdata,0);
5741 num_file_acls = SVAL(pdata,2);
5742 num_def_acls = SVAL(pdata,4);
5744 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5745 valid_file_acls = False;
5749 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5750 valid_def_acls = False;
5754 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5755 return NT_STATUS_INVALID_PARAMETER;
5758 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5759 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5760 return NT_STATUS_INVALID_PARAMETER;
5763 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5764 fname ? fname : fsp->fsp_name,
5765 (unsigned int)num_file_acls,
5766 (unsigned int)num_def_acls));
5768 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5769 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5770 return map_nt_error_from_unix(errno);
5773 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5774 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5775 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5776 return map_nt_error_from_unix(errno);
5778 return NT_STATUS_OK;
5782 /****************************************************************************
5783 Deal with SMB_SET_POSIX_LOCK.
5784 ****************************************************************************/
5786 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5787 struct smb_request *req,
5795 bool blocking_lock = False;
5796 enum brl_type lock_type;
5798 NTSTATUS status = NT_STATUS_OK;
5800 if (fsp == NULL || fsp->fh->fd == -1) {
5801 return NT_STATUS_INVALID_HANDLE;
5804 if (total_data != POSIX_LOCK_DATA_SIZE) {
5805 return NT_STATUS_INVALID_PARAMETER;
5808 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5809 case POSIX_LOCK_TYPE_READ:
5810 lock_type = READ_LOCK;
5812 case POSIX_LOCK_TYPE_WRITE:
5813 /* Return the right POSIX-mappable error code for files opened read-only. */
5814 if (!fsp->can_write) {
5815 return NT_STATUS_INVALID_HANDLE;
5817 lock_type = WRITE_LOCK;
5819 case POSIX_LOCK_TYPE_UNLOCK:
5820 lock_type = UNLOCK_LOCK;
5823 return NT_STATUS_INVALID_PARAMETER;
5826 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5827 blocking_lock = False;
5828 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5829 blocking_lock = True;
5831 return NT_STATUS_INVALID_PARAMETER;
5834 if (!lp_blocking_locks(SNUM(conn))) {
5835 blocking_lock = False;
5838 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5839 #if defined(HAVE_LONGLONG)
5840 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5841 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5842 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5843 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5844 #else /* HAVE_LONGLONG */
5845 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5846 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5847 #endif /* HAVE_LONGLONG */
5849 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5850 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5852 (unsigned int)lock_type,
5853 (unsigned int)lock_pid,
5857 if (lock_type == UNLOCK_LOCK) {
5858 status = do_unlock(smbd_messaging_context(),
5865 uint32 block_smbpid;
5867 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5879 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5881 * A blocking lock was requested. Package up
5882 * this smb into a queued request and push it
5883 * onto the blocking lock queue.
5885 if(push_blocking_lock_request(br_lck,
5888 -1, /* infinite timeout. */
5896 TALLOC_FREE(br_lck);
5900 TALLOC_FREE(br_lck);
5906 /****************************************************************************
5907 Deal with SMB_INFO_STANDARD.
5908 ****************************************************************************/
5910 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5914 const struct smb_filename *smb_fname)
5916 struct smb_file_time ft;
5919 if (total_data < 12) {
5920 return NT_STATUS_INVALID_PARAMETER;
5924 ft.create_time = interpret_long_date(pdata);
5927 ft.atime = interpret_long_date(pdata + 8);
5930 ft.mtime = interpret_long_date(pdata + 16);
5932 DEBUG(10,("smb_set_info_standard: file %s\n",
5933 smb_fname_str_dbg(smb_fname)));
5935 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5938 /****************************************************************************
5939 Deal with SMB_SET_FILE_BASIC_INFO.
5940 ****************************************************************************/
5942 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5946 const struct smb_filename *smb_fname)
5948 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5949 struct timespec write_time;
5950 struct timespec changed_time;
5951 struct smb_file_time ft;
5953 NTSTATUS status = NT_STATUS_OK;
5954 bool setting_write_time = true;
5958 if (total_data < 36) {
5959 return NT_STATUS_INVALID_PARAMETER;
5962 /* Set the attributes */
5963 dosmode = IVAL(pdata,32);
5964 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
5965 if (!NT_STATUS_IS_OK(status)) {
5970 ft.atime = interpret_long_date(pdata+8);
5972 write_time = interpret_long_date(pdata+16);
5973 changed_time = interpret_long_date(pdata+24);
5976 ft.mtime = timespec_min(&write_time, &changed_time);
5979 ft.create_time = interpret_long_date(pdata);
5981 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5982 !null_timespec(write_time)) {
5983 ft.mtime = write_time;
5986 /* Prefer a defined time to an undefined one. */
5987 if (null_timespec(ft.mtime)) {
5988 if (null_timespec(write_time)) {
5989 ft.mtime = changed_time;
5990 setting_write_time = false;
5992 ft.mtime = write_time;
5996 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
5997 smb_fname_str_dbg(smb_fname)));
5999 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6000 setting_write_time);
6003 /****************************************************************************
6004 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6005 ****************************************************************************/
6007 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6008 struct smb_request *req,
6012 struct smb_filename *smb_fname)
6014 uint64_t allocation_size = 0;
6015 NTSTATUS status = NT_STATUS_OK;
6016 files_struct *new_fsp = NULL;
6018 if (!VALID_STAT(smb_fname->st)) {
6019 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6022 if (total_data < 8) {
6023 return NT_STATUS_INVALID_PARAMETER;
6026 allocation_size = (uint64_t)IVAL(pdata,0);
6027 #ifdef LARGE_SMB_OFF_T
6028 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6029 #else /* LARGE_SMB_OFF_T */
6030 if (IVAL(pdata,4) != 0) {
6031 /* more than 32 bits? */
6032 return NT_STATUS_INVALID_PARAMETER;
6034 #endif /* LARGE_SMB_OFF_T */
6036 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6037 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6038 (double)allocation_size));
6040 if (allocation_size) {
6041 allocation_size = smb_roundup(conn, allocation_size);
6044 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6045 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6046 (double)allocation_size));
6048 if (fsp && fsp->fh->fd != -1) {
6049 /* Open file handle. */
6050 /* Only change if needed. */
6051 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6052 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6053 return map_nt_error_from_unix(errno);
6056 /* But always update the time. */
6058 * This is equivalent to a write. Ensure it's seen immediately
6059 * if there are no pending writes.
6061 trigger_write_time_update_immediate(fsp);
6062 return NT_STATUS_OK;
6065 /* Pathname or stat or directory file. */
6066 status = SMB_VFS_CREATE_FILE(
6069 0, /* root_dir_fid */
6070 smb_fname, /* fname */
6071 FILE_WRITE_DATA, /* access_mask */
6072 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6074 FILE_OPEN, /* create_disposition*/
6075 0, /* create_options */
6076 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6077 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6078 0, /* allocation_size */
6081 &new_fsp, /* result */
6084 if (!NT_STATUS_IS_OK(status)) {
6085 /* NB. We check for open_was_deferred in the caller. */
6089 /* Only change if needed. */
6090 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6091 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6092 status = map_nt_error_from_unix(errno);
6093 close_file(req, new_fsp, NORMAL_CLOSE);
6098 /* Changing the allocation size should set the last mod time. */
6100 * This is equivalent to a write. Ensure it's seen immediately
6101 * if there are no pending writes.
6103 trigger_write_time_update_immediate(new_fsp);
6105 close_file(req, new_fsp, NORMAL_CLOSE);
6106 return NT_STATUS_OK;
6109 /****************************************************************************
6110 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6111 ****************************************************************************/
6113 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6114 struct smb_request *req,
6118 const struct smb_filename *smb_fname)
6122 if (total_data < 8) {
6123 return NT_STATUS_INVALID_PARAMETER;
6126 size = IVAL(pdata,0);
6127 #ifdef LARGE_SMB_OFF_T
6128 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6129 #else /* LARGE_SMB_OFF_T */
6130 if (IVAL(pdata,4) != 0) {
6131 /* more than 32 bits? */
6132 return NT_STATUS_INVALID_PARAMETER;
6134 #endif /* LARGE_SMB_OFF_T */
6135 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6136 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6139 return smb_set_file_size(conn, req,
6146 /****************************************************************************
6147 Allow a UNIX info mknod.
6148 ****************************************************************************/
6150 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6153 const struct smb_filename *smb_fname)
6155 uint32 file_type = IVAL(pdata,56);
6156 #if defined(HAVE_MAKEDEV)
6157 uint32 dev_major = IVAL(pdata,60);
6158 uint32 dev_minor = IVAL(pdata,68);
6160 SMB_DEV_T dev = (SMB_DEV_T)0;
6161 uint32 raw_unixmode = IVAL(pdata,84);
6165 if (total_data < 100) {
6166 return NT_STATUS_INVALID_PARAMETER;
6169 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6170 PERM_NEW_FILE, &unixmode);
6171 if (!NT_STATUS_IS_OK(status)) {
6175 #if defined(HAVE_MAKEDEV)
6176 dev = makedev(dev_major, dev_minor);
6179 switch (file_type) {
6180 #if defined(S_IFIFO)
6181 case UNIX_TYPE_FIFO:
6182 unixmode |= S_IFIFO;
6185 #if defined(S_IFSOCK)
6186 case UNIX_TYPE_SOCKET:
6187 unixmode |= S_IFSOCK;
6190 #if defined(S_IFCHR)
6191 case UNIX_TYPE_CHARDEV:
6192 unixmode |= S_IFCHR;
6195 #if defined(S_IFBLK)
6196 case UNIX_TYPE_BLKDEV:
6197 unixmode |= S_IFBLK;
6201 return NT_STATUS_INVALID_PARAMETER;
6204 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6205 "%.0f mode 0%o for file %s\n", (double)dev,
6206 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6208 /* Ok - do the mknod. */
6209 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6210 return map_nt_error_from_unix(errno);
6213 /* If any of the other "set" calls fail we
6214 * don't want to end up with a half-constructed mknod.
6217 if (lp_inherit_perms(SNUM(conn))) {
6219 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6221 return NT_STATUS_NO_MEMORY;
6223 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6225 TALLOC_FREE(parent);
6228 return NT_STATUS_OK;
6231 /****************************************************************************
6232 Deal with SMB_SET_FILE_UNIX_BASIC.
6233 ****************************************************************************/
6235 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6236 struct smb_request *req,
6240 const struct smb_filename *smb_fname)
6242 struct smb_file_time ft;
6243 uint32 raw_unixmode;
6246 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6247 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6248 NTSTATUS status = NT_STATUS_OK;
6249 bool delete_on_fail = False;
6250 enum perm_type ptype;
6251 files_struct *all_fsps = NULL;
6252 bool modify_mtime = true;
6254 SMB_STRUCT_STAT sbuf;
6258 if (total_data < 100) {
6259 return NT_STATUS_INVALID_PARAMETER;
6262 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6263 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6264 size=IVAL(pdata,0); /* first 8 Bytes are size */
6265 #ifdef LARGE_SMB_OFF_T
6266 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6267 #else /* LARGE_SMB_OFF_T */
6268 if (IVAL(pdata,4) != 0) {
6269 /* more than 32 bits? */
6270 return NT_STATUS_INVALID_PARAMETER;
6272 #endif /* LARGE_SMB_OFF_T */
6275 ft.atime = interpret_long_date(pdata+24); /* access_time */
6276 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6277 set_owner = (uid_t)IVAL(pdata,40);
6278 set_grp = (gid_t)IVAL(pdata,48);
6279 raw_unixmode = IVAL(pdata,84);
6281 if (VALID_STAT(smb_fname->st)) {
6282 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6283 ptype = PERM_EXISTING_DIR;
6285 ptype = PERM_EXISTING_FILE;
6288 ptype = PERM_NEW_FILE;
6291 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6293 if (!NT_STATUS_IS_OK(status)) {
6297 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6298 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6299 smb_fname_str_dbg(smb_fname), (double)size,
6300 (unsigned int)set_owner, (unsigned int)set_grp,
6301 (int)raw_unixmode));
6303 sbuf = smb_fname->st;
6305 if (!VALID_STAT(sbuf)) {
6306 struct smb_filename *smb_fname_tmp = NULL;
6308 * The only valid use of this is to create character and block
6309 * devices, and named pipes. This is deprecated (IMHO) and
6310 * a new info level should be used for mknod. JRA.
6313 status = smb_unix_mknod(conn,
6317 if (!NT_STATUS_IS_OK(status)) {
6321 status = copy_smb_filename(talloc_tos(), smb_fname,
6323 if (!NT_STATUS_IS_OK(status)) {
6327 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6328 status = map_nt_error_from_unix(errno);
6329 TALLOC_FREE(smb_fname_tmp);
6330 SMB_VFS_UNLINK(conn, smb_fname);
6334 sbuf = smb_fname_tmp->st;
6335 TALLOC_FREE(smb_fname_tmp);
6337 /* Ensure we don't try and change anything else. */
6338 raw_unixmode = SMB_MODE_NO_CHANGE;
6339 size = get_file_size_stat(&sbuf);
6340 ft.atime = sbuf.st_ex_atime;
6341 ft.mtime = sbuf.st_ex_mtime;
6343 * We continue here as we might want to change the
6346 delete_on_fail = True;
6350 /* Horrible backwards compatibility hack as an old server bug
6351 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6355 size = get_file_size_stat(&sbuf);
6360 * Deal with the UNIX specific mode set.
6363 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6364 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6365 "setting mode 0%o for file %s\n",
6366 (unsigned int)unixmode,
6367 smb_fname_str_dbg(smb_fname)));
6368 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6369 return map_nt_error_from_unix(errno);
6374 * Deal with the UNIX specific uid set.
6377 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6378 (sbuf.st_ex_uid != set_owner)) {
6381 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6382 "changing owner %u for path %s\n",
6383 (unsigned int)set_owner,
6384 smb_fname_str_dbg(smb_fname)));
6386 if (S_ISLNK(sbuf.st_ex_mode)) {
6387 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6388 set_owner, (gid_t)-1);
6390 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6391 set_owner, (gid_t)-1);
6395 status = map_nt_error_from_unix(errno);
6396 if (delete_on_fail) {
6397 SMB_VFS_UNLINK(conn, smb_fname);
6404 * Deal with the UNIX specific gid set.
6407 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6408 (sbuf.st_ex_gid != set_grp)) {
6409 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6410 "changing group %u for file %s\n",
6411 (unsigned int)set_owner,
6412 smb_fname_str_dbg(smb_fname)));
6413 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6415 status = map_nt_error_from_unix(errno);
6416 if (delete_on_fail) {
6417 SMB_VFS_UNLINK(conn, smb_fname);
6423 /* Deal with any size changes. */
6425 status = smb_set_file_size(conn, req,
6430 if (!NT_STATUS_IS_OK(status)) {
6434 /* Deal with any time changes. */
6435 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6436 /* No change, don't cancel anything. */
6440 id = vfs_file_id_from_sbuf(conn, &sbuf);
6441 for(all_fsps = file_find_di_first(id); all_fsps;
6442 all_fsps = file_find_di_next(all_fsps)) {
6444 * We're setting the time explicitly for UNIX.
6445 * Cancel any pending changes over all handles.
6447 all_fsps->update_write_time_on_close = false;
6448 TALLOC_FREE(all_fsps->update_write_time_event);
6452 * Override the "setting_write_time"
6453 * parameter here as it almost does what
6454 * we need. Just remember if we modified
6455 * mtime and send the notify ourselves.
6457 if (null_timespec(ft.mtime)) {
6458 modify_mtime = false;
6461 status = smb_set_file_time(conn,
6467 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6468 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6473 /****************************************************************************
6474 Deal with SMB_SET_FILE_UNIX_INFO2.
6475 ****************************************************************************/
6477 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6478 struct smb_request *req,
6482 const struct smb_filename *smb_fname)
6488 if (total_data < 116) {
6489 return NT_STATUS_INVALID_PARAMETER;
6492 /* Start by setting all the fields that are common between UNIX_BASIC
6495 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6497 if (!NT_STATUS_IS_OK(status)) {
6501 smb_fflags = IVAL(pdata, 108);
6502 smb_fmask = IVAL(pdata, 112);
6504 /* NB: We should only attempt to alter the file flags if the client
6505 * sends a non-zero mask.
6507 if (smb_fmask != 0) {
6508 int stat_fflags = 0;
6510 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6511 smb_fmask, &stat_fflags)) {
6512 /* Client asked to alter a flag we don't understand. */
6513 return NT_STATUS_INVALID_PARAMETER;
6516 if (fsp && fsp->fh->fd != -1) {
6517 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6518 return NT_STATUS_NOT_SUPPORTED;
6520 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6521 stat_fflags) != 0) {
6522 return map_nt_error_from_unix(errno);
6527 /* XXX: need to add support for changing the create_time here. You
6528 * can do this for paths on Darwin with setattrlist(2). The right way
6529 * to hook this up is probably by extending the VFS utimes interface.
6532 return NT_STATUS_OK;
6535 /****************************************************************************
6536 Create a directory with POSIX semantics.
6537 ****************************************************************************/
6539 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6540 struct smb_request *req,
6544 SMB_STRUCT_STAT *psbuf,
6545 int *pdata_return_size)
6547 struct smb_filename *smb_fname;
6548 NTSTATUS status = NT_STATUS_OK;
6549 uint32 raw_unixmode = 0;
6550 uint32 mod_unixmode = 0;
6551 mode_t unixmode = (mode_t)0;
6552 files_struct *fsp = NULL;
6553 uint16 info_level_return = 0;
6555 char *pdata = *ppdata;
6557 if (total_data < 18) {
6558 return NT_STATUS_INVALID_PARAMETER;
6561 raw_unixmode = IVAL(pdata,8);
6562 /* Next 4 bytes are not yet defined. */
6564 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6565 if (!NT_STATUS_IS_OK(status)) {
6569 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6571 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6572 fname, (unsigned int)unixmode ));
6574 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6576 if (!NT_STATUS_IS_OK(status)) {
6580 status = SMB_VFS_CREATE_FILE(
6583 0, /* root_dir_fid */
6584 smb_fname, /* fname */
6585 FILE_READ_ATTRIBUTES, /* access_mask */
6586 FILE_SHARE_NONE, /* share_access */
6587 FILE_CREATE, /* create_disposition*/
6588 FILE_DIRECTORY_FILE, /* create_options */
6589 mod_unixmode, /* file_attributes */
6590 0, /* oplock_request */
6591 0, /* allocation_size */
6597 *psbuf = smb_fname->st;
6598 TALLOC_FREE(smb_fname);
6600 if (NT_STATUS_IS_OK(status)) {
6601 close_file(req, fsp, NORMAL_CLOSE);
6604 info_level_return = SVAL(pdata,16);
6606 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6607 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6608 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6609 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6611 *pdata_return_size = 12;
6614 /* Realloc the data size */
6615 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6616 if (*ppdata == NULL) {
6617 *pdata_return_size = 0;
6618 return NT_STATUS_NO_MEMORY;
6622 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6623 SSVAL(pdata,2,0); /* No fnum. */
6624 SIVAL(pdata,4,info); /* Was directory created. */
6626 switch (info_level_return) {
6627 case SMB_QUERY_FILE_UNIX_BASIC:
6628 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6629 SSVAL(pdata,10,0); /* Padding. */
6630 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6632 case SMB_QUERY_FILE_UNIX_INFO2:
6633 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6634 SSVAL(pdata,10,0); /* Padding. */
6635 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6638 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6639 SSVAL(pdata,10,0); /* Padding. */
6646 /****************************************************************************
6647 Open/Create a file with POSIX semantics.
6648 ****************************************************************************/
6650 static NTSTATUS smb_posix_open(connection_struct *conn,
6651 struct smb_request *req,
6655 SMB_STRUCT_STAT *psbuf,
6656 int *pdata_return_size)
6658 struct smb_filename *smb_fname = NULL;
6659 bool extended_oplock_granted = False;
6660 char *pdata = *ppdata;
6662 uint32 wire_open_mode = 0;
6663 uint32 raw_unixmode = 0;
6664 uint32 mod_unixmode = 0;
6665 uint32 create_disp = 0;
6666 uint32 access_mask = 0;
6667 uint32 create_options = 0;
6668 NTSTATUS status = NT_STATUS_OK;
6669 mode_t unixmode = (mode_t)0;
6670 files_struct *fsp = NULL;
6671 int oplock_request = 0;
6673 uint16 info_level_return = 0;
6675 if (total_data < 18) {
6676 return NT_STATUS_INVALID_PARAMETER;
6679 flags = IVAL(pdata,0);
6680 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6681 if (oplock_request) {
6682 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6685 wire_open_mode = IVAL(pdata,4);
6687 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6688 return smb_posix_mkdir(conn, req,
6696 switch (wire_open_mode & SMB_ACCMODE) {
6698 access_mask = FILE_READ_DATA;
6701 access_mask = FILE_WRITE_DATA;
6704 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6707 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6708 (unsigned int)wire_open_mode ));
6709 return NT_STATUS_INVALID_PARAMETER;
6712 wire_open_mode &= ~SMB_ACCMODE;
6714 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6715 create_disp = FILE_CREATE;
6716 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6717 create_disp = FILE_OVERWRITE_IF;
6718 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6719 create_disp = FILE_OPEN_IF;
6720 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6721 create_disp = FILE_OPEN;
6723 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6724 (unsigned int)wire_open_mode ));
6725 return NT_STATUS_INVALID_PARAMETER;
6728 raw_unixmode = IVAL(pdata,8);
6729 /* Next 4 bytes are not yet defined. */
6731 status = unix_perms_from_wire(conn,
6734 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6737 if (!NT_STATUS_IS_OK(status)) {
6741 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6743 if (wire_open_mode & SMB_O_SYNC) {
6744 create_options |= FILE_WRITE_THROUGH;
6746 if (wire_open_mode & SMB_O_APPEND) {
6747 access_mask |= FILE_APPEND_DATA;
6749 if (wire_open_mode & SMB_O_DIRECT) {
6750 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6753 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6755 (unsigned int)wire_open_mode,
6756 (unsigned int)unixmode ));
6758 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6760 if (!NT_STATUS_IS_OK(status)) {
6764 status = SMB_VFS_CREATE_FILE(
6767 0, /* root_dir_fid */
6768 smb_fname, /* fname */
6769 access_mask, /* access_mask */
6770 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6772 create_disp, /* create_disposition*/
6773 FILE_NON_DIRECTORY_FILE, /* create_options */
6774 mod_unixmode, /* file_attributes */
6775 oplock_request, /* oplock_request */
6776 0, /* allocation_size */
6782 *psbuf = smb_fname->st;
6783 TALLOC_FREE(smb_fname);
6785 if (!NT_STATUS_IS_OK(status)) {
6789 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6790 extended_oplock_granted = True;
6793 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6794 extended_oplock_granted = True;
6797 info_level_return = SVAL(pdata,16);
6799 /* Allocate the correct return size. */
6801 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6802 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6803 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6804 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6806 *pdata_return_size = 12;
6809 /* Realloc the data size */
6810 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6811 if (*ppdata == NULL) {
6812 close_file(req, fsp, ERROR_CLOSE);
6813 *pdata_return_size = 0;
6814 return NT_STATUS_NO_MEMORY;
6818 if (extended_oplock_granted) {
6819 if (flags & REQUEST_BATCH_OPLOCK) {
6820 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6822 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6824 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6825 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6827 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6830 SSVAL(pdata,2,fsp->fnum);
6831 SIVAL(pdata,4,info); /* Was file created etc. */
6833 switch (info_level_return) {
6834 case SMB_QUERY_FILE_UNIX_BASIC:
6835 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6836 SSVAL(pdata,10,0); /* padding. */
6837 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6839 case SMB_QUERY_FILE_UNIX_INFO2:
6840 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6841 SSVAL(pdata,10,0); /* padding. */
6842 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6845 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6846 SSVAL(pdata,10,0); /* padding. */
6849 return NT_STATUS_OK;
6852 /****************************************************************************
6853 Delete a file with POSIX semantics.
6854 ****************************************************************************/
6856 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6857 struct smb_request *req,
6860 struct smb_filename *smb_fname)
6862 NTSTATUS status = NT_STATUS_OK;
6863 files_struct *fsp = NULL;
6867 int create_options = 0;
6869 struct share_mode_lock *lck = NULL;
6871 if (total_data < 2) {
6872 return NT_STATUS_INVALID_PARAMETER;
6875 flags = SVAL(pdata,0);
6877 if (!VALID_STAT(smb_fname->st)) {
6878 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6881 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6882 !VALID_STAT_OF_DIR(smb_fname->st)) {
6883 return NT_STATUS_NOT_A_DIRECTORY;
6886 DEBUG(10,("smb_posix_unlink: %s %s\n",
6887 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6888 smb_fname_str_dbg(smb_fname)));
6890 if (VALID_STAT_OF_DIR(smb_fname->st)) {
6891 create_options |= FILE_DIRECTORY_FILE;
6894 status = SMB_VFS_CREATE_FILE(
6897 0, /* root_dir_fid */
6898 smb_fname, /* fname */
6899 DELETE_ACCESS, /* access_mask */
6900 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6902 FILE_OPEN, /* create_disposition*/
6903 create_options, /* create_options */
6904 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6905 0, /* oplock_request */
6906 0, /* allocation_size */
6912 if (!NT_STATUS_IS_OK(status)) {
6917 * Don't lie to client. If we can't really delete due to
6918 * non-POSIX opens return SHARING_VIOLATION.
6921 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6924 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6925 "lock for file %s\n", fsp->fsp_name));
6926 close_file(req, fsp, NORMAL_CLOSE);
6927 return NT_STATUS_INVALID_PARAMETER;
6931 * See if others still have the file open. If this is the case, then
6932 * don't delete. If all opens are POSIX delete we can set the delete
6933 * on close disposition.
6935 for (i=0; i<lck->num_share_modes; i++) {
6936 struct share_mode_entry *e = &lck->share_modes[i];
6937 if (is_valid_share_mode_entry(e)) {
6938 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6941 /* Fail with sharing violation. */
6942 close_file(req, fsp, NORMAL_CLOSE);
6944 return NT_STATUS_SHARING_VIOLATION;
6949 * Set the delete on close.
6951 status = smb_set_file_disposition_info(conn,
6957 if (!NT_STATUS_IS_OK(status)) {
6958 close_file(req, fsp, NORMAL_CLOSE);
6963 return close_file(req, fsp, NORMAL_CLOSE);
6966 /****************************************************************************
6967 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6968 ****************************************************************************/
6970 static void call_trans2setfilepathinfo(connection_struct *conn,
6971 struct smb_request *req,
6972 unsigned int tran_call,
6973 char **pparams, int total_params,
6974 char **ppdata, int total_data,
6975 unsigned int max_data_bytes)
6977 char *params = *pparams;
6978 char *pdata = *ppdata;
6980 SMB_STRUCT_STAT sbuf;
6982 struct smb_filename *smb_fname = NULL;
6983 files_struct *fsp = NULL;
6984 NTSTATUS status = NT_STATUS_OK;
6985 int data_return_size = 0;
6986 TALLOC_CTX *ctx = talloc_tos();
6989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6993 if (tran_call == TRANSACT2_SETFILEINFO) {
6994 if (total_params < 4) {
6995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6999 fsp = file_fsp(req, SVAL(params,0));
7000 /* Basic check for non-null fsp. */
7001 if (!check_fsp_open(conn, req, fsp)) {
7004 info_level = SVAL(params,2);
7006 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
7008 reply_nterror(req, NT_STATUS_NO_MEMORY);
7012 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
7014 if (!NT_STATUS_IS_OK(status)) {
7015 reply_nterror(req, status);
7019 if(fsp->is_directory || fsp->fh->fd == -1) {
7021 * This is actually a SETFILEINFO on a directory
7022 * handle (returned from an NT SMB). NT5.0 seems
7023 * to do this call. JRA.
7025 if (INFO_LEVEL_IS_UNIX(info_level)) {
7026 /* Always do lstat for UNIX calls. */
7027 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7028 DEBUG(3,("call_trans2setfilepathinfo: "
7029 "SMB_VFS_LSTAT of %s failed "
7031 smb_fname_str_dbg(smb_fname),
7033 reply_nterror(req, map_nt_error_from_unix(errno));
7037 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7038 DEBUG(3,("call_trans2setfilepathinfo: "
7039 "fileinfo of %s failed (%s)\n",
7040 smb_fname_str_dbg(smb_fname),
7042 reply_nterror(req, map_nt_error_from_unix(errno));
7046 } else if (fsp->print_file) {
7048 * Doing a DELETE_ON_CLOSE should cancel a print job.
7050 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7051 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7053 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
7056 send_trans2_replies(conn, req, params, 2,
7061 reply_doserror(req, ERRDOS, ERRbadpath);
7066 * Original code - this is an open file.
7068 if (!check_fsp(conn, req, fsp)) {
7072 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7073 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7074 "of fnum %d failed (%s)\n", fsp->fnum,
7076 reply_nterror(req, map_nt_error_from_unix(errno));
7082 if (total_params < 7) {
7083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7087 info_level = SVAL(params,0);
7088 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
7089 total_params - 6, STR_TERMINATE,
7091 if (!NT_STATUS_IS_OK(status)) {
7092 reply_nterror(req, status);
7096 status = filename_convert(ctx, conn,
7097 req->flags2 & FLAGS2_DFS_PATHNAMES,
7101 if (!NT_STATUS_IS_OK(status)) {
7102 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7103 reply_botherror(req,
7104 NT_STATUS_PATH_NOT_COVERED,
7105 ERRSRV, ERRbadpath);
7108 reply_nterror(req, status);
7112 if (INFO_LEVEL_IS_UNIX(info_level)) {
7114 * For CIFS UNIX extensions the target name may not exist.
7117 /* Always do lstat for UNIX calls. */
7118 SMB_VFS_LSTAT(conn, smb_fname);
7120 } else if (!VALID_STAT(smb_fname->st) &&
7121 SMB_VFS_STAT(conn, smb_fname)) {
7122 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7124 smb_fname_str_dbg(smb_fname),
7126 reply_nterror(req, map_nt_error_from_unix(errno));
7131 /* Set sbuf for use below. */
7132 sbuf = smb_fname->st;
7134 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7135 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7139 if (!CAN_WRITE(conn)) {
7140 /* Allow POSIX opens. The open path will deny
7141 * any non-readonly opens. */
7142 if (info_level != SMB_POSIX_PATH_OPEN) {
7143 reply_doserror(req, ERRSRV, ERRaccess);
7148 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
7149 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
7151 /* Realloc the parameter size */
7152 *pparams = (char *)SMB_REALLOC(*pparams,2);
7153 if (*pparams == NULL) {
7154 reply_nterror(req, NT_STATUS_NO_MEMORY);
7161 switch (info_level) {
7163 case SMB_INFO_STANDARD:
7165 status = smb_set_info_standard(conn,
7173 case SMB_INFO_SET_EA:
7175 status = smb_info_set_ea(conn,
7183 case SMB_SET_FILE_BASIC_INFO:
7184 case SMB_FILE_BASIC_INFORMATION:
7186 status = smb_set_file_basic_info(conn,
7194 case SMB_FILE_ALLOCATION_INFORMATION:
7195 case SMB_SET_FILE_ALLOCATION_INFO:
7197 status = smb_set_file_allocation_info(conn, req,
7205 case SMB_FILE_END_OF_FILE_INFORMATION:
7206 case SMB_SET_FILE_END_OF_FILE_INFO:
7208 status = smb_set_file_end_of_file_info(conn, req,
7216 case SMB_FILE_DISPOSITION_INFORMATION:
7217 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7220 /* JRA - We used to just ignore this on a path ?
7221 * Shouldn't this be invalid level on a pathname
7224 if (tran_call != TRANSACT2_SETFILEINFO) {
7225 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7228 status = smb_set_file_disposition_info(conn,
7236 case SMB_FILE_POSITION_INFORMATION:
7238 status = smb_file_position_information(conn,
7245 /* From tridge Samba4 :
7246 * MODE_INFORMATION in setfileinfo (I have no
7247 * idea what "mode information" on a file is - it takes a value of 0,
7248 * 2, 4 or 6. What could it be?).
7251 case SMB_FILE_MODE_INFORMATION:
7253 status = smb_file_mode_information(conn,
7260 * CIFS UNIX extensions.
7263 case SMB_SET_FILE_UNIX_BASIC:
7265 status = smb_set_file_unix_basic(conn, req,
7273 case SMB_SET_FILE_UNIX_INFO2:
7275 status = smb_set_file_unix_info2(conn, req,
7283 case SMB_SET_FILE_UNIX_LINK:
7285 if (tran_call != TRANSACT2_SETPATHINFO) {
7286 /* We must have a pathname for this. */
7287 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7290 status = smb_set_file_unix_link(conn, req, pdata,
7295 case SMB_SET_FILE_UNIX_HLINK:
7297 if (tran_call != TRANSACT2_SETPATHINFO || smb_fname == NULL) {
7298 /* We must have a pathname for this. */
7299 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7302 status = smb_set_file_unix_hlink(conn, req,
7308 case SMB_FILE_RENAME_INFORMATION:
7310 status = smb_file_rename_information(conn, req,
7316 #if defined(HAVE_POSIX_ACLS)
7317 case SMB_SET_POSIX_ACL:
7319 status = smb_set_posix_acl(conn,
7329 case SMB_SET_POSIX_LOCK:
7331 if (tran_call != TRANSACT2_SETFILEINFO) {
7332 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7335 status = smb_set_posix_lock(conn, req,
7336 pdata, total_data, fsp);
7340 case SMB_POSIX_PATH_OPEN:
7342 if (tran_call != TRANSACT2_SETPATHINFO) {
7343 /* We must have a pathname for this. */
7344 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7348 status = smb_posix_open(conn, req,
7357 case SMB_POSIX_PATH_UNLINK:
7359 if (tran_call != TRANSACT2_SETPATHINFO) {
7360 /* We must have a pathname for this. */
7361 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7365 status = smb_posix_unlink(conn, req,
7373 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7377 if (!NT_STATUS_IS_OK(status)) {
7378 if (open_was_deferred(req->mid)) {
7379 /* We have re-scheduled this call. */
7382 if (blocking_lock_was_deferred(req->mid)) {
7383 /* We have re-scheduled this call. */
7386 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7387 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7388 ERRSRV, ERRbadpath);
7391 if (info_level == SMB_POSIX_PATH_OPEN) {
7392 reply_openerror(req, status);
7396 reply_nterror(req, status);
7401 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7407 /****************************************************************************
7408 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7409 ****************************************************************************/
7411 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7412 char **pparams, int total_params,
7413 char **ppdata, int total_data,
7414 unsigned int max_data_bytes)
7416 struct smb_filename *smb_dname = NULL;
7417 char *params = *pparams;
7418 char *pdata = *ppdata;
7419 char *directory = NULL;
7420 NTSTATUS status = NT_STATUS_OK;
7421 struct ea_list *ea_list = NULL;
7422 TALLOC_CTX *ctx = talloc_tos();
7424 if (!CAN_WRITE(conn)) {
7425 reply_doserror(req, ERRSRV, ERRaccess);
7429 if (total_params < 5) {
7430 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7434 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7435 total_params - 4, STR_TERMINATE,
7437 if (!NT_STATUS_IS_OK(status)) {
7438 reply_nterror(req, status);
7442 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7444 status = filename_convert(ctx,
7446 req->flags2 & FLAGS2_DFS_PATHNAMES,
7451 if (!NT_STATUS_IS_OK(status)) {
7452 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7453 reply_botherror(req,
7454 NT_STATUS_PATH_NOT_COVERED,
7455 ERRSRV, ERRbadpath);
7458 reply_nterror(req, status);
7462 /* Any data in this call is an EA list. */
7463 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7464 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7469 * OS/2 workplace shell seems to send SET_EA requests of "null"
7470 * length (4 bytes containing IVAL 4).
7471 * They seem to have no effect. Bug #3212. JRA.
7474 if (total_data != 4) {
7475 if (total_data < 10) {
7476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7480 if (IVAL(pdata,0) > total_data) {
7481 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7482 IVAL(pdata,0), (unsigned int)total_data));
7483 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7487 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7494 /* If total_data == 4 Windows doesn't care what values
7495 * are placed in that field, it just ignores them.
7496 * The System i QNTC IBM SMB client puts bad values here,
7497 * so ignore them. */
7499 status = create_directory(conn, req, smb_dname);
7501 if (!NT_STATUS_IS_OK(status)) {
7502 reply_nterror(req, status);
7506 /* Try and set any given EA. */
7508 status = set_ea(conn, NULL, smb_dname, ea_list);
7509 if (!NT_STATUS_IS_OK(status)) {
7510 reply_nterror(req, status);
7515 /* Realloc the parameter and data sizes */
7516 *pparams = (char *)SMB_REALLOC(*pparams,2);
7517 if(*pparams == NULL) {
7518 reply_nterror(req, NT_STATUS_NO_MEMORY);
7525 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7528 TALLOC_FREE(smb_dname);
7532 /****************************************************************************
7533 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7534 We don't actually do this - we just send a null response.
7535 ****************************************************************************/
7537 static void call_trans2findnotifyfirst(connection_struct *conn,
7538 struct smb_request *req,
7539 char **pparams, int total_params,
7540 char **ppdata, int total_data,
7541 unsigned int max_data_bytes)
7543 char *params = *pparams;
7546 if (total_params < 6) {
7547 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7551 info_level = SVAL(params,4);
7552 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7554 switch (info_level) {
7559 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7563 /* Realloc the parameter and data sizes */
7564 *pparams = (char *)SMB_REALLOC(*pparams,6);
7565 if (*pparams == NULL) {
7566 reply_nterror(req, NT_STATUS_NO_MEMORY);
7571 SSVAL(params,0,fnf_handle);
7572 SSVAL(params,2,0); /* No changes */
7573 SSVAL(params,4,0); /* No EA errors */
7580 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7585 /****************************************************************************
7586 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7587 changes). Currently this does nothing.
7588 ****************************************************************************/
7590 static void call_trans2findnotifynext(connection_struct *conn,
7591 struct smb_request *req,
7592 char **pparams, int total_params,
7593 char **ppdata, int total_data,
7594 unsigned int max_data_bytes)
7596 char *params = *pparams;
7598 DEBUG(3,("call_trans2findnotifynext\n"));
7600 /* Realloc the parameter and data sizes */
7601 *pparams = (char *)SMB_REALLOC(*pparams,4);
7602 if (*pparams == NULL) {
7603 reply_nterror(req, NT_STATUS_NO_MEMORY);
7608 SSVAL(params,0,0); /* No changes */
7609 SSVAL(params,2,0); /* No EA errors */
7611 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7616 /****************************************************************************
7617 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7618 ****************************************************************************/
7620 static void call_trans2getdfsreferral(connection_struct *conn,
7621 struct smb_request *req,
7622 char **pparams, int total_params,
7623 char **ppdata, int total_data,
7624 unsigned int max_data_bytes)
7626 char *params = *pparams;
7627 char *pathname = NULL;
7629 int max_referral_level;
7630 NTSTATUS status = NT_STATUS_OK;
7631 TALLOC_CTX *ctx = talloc_tos();
7633 DEBUG(10,("call_trans2getdfsreferral\n"));
7635 if (total_params < 3) {
7636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7640 max_referral_level = SVAL(params,0);
7642 if(!lp_host_msdfs()) {
7643 reply_doserror(req, ERRDOS, ERRbadfunc);
7647 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7648 total_params - 2, STR_TERMINATE);
7650 reply_nterror(req, NT_STATUS_NOT_FOUND);
7653 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7654 ppdata,&status)) < 0) {
7655 reply_nterror(req, status);
7659 SSVAL(req->inbuf, smb_flg2,
7660 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7661 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7666 #define LMCAT_SPL 0x53
7667 #define LMFUNC_GETJOBID 0x60
7669 /****************************************************************************
7670 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7671 ****************************************************************************/
7673 static void call_trans2ioctl(connection_struct *conn,
7674 struct smb_request *req,
7675 char **pparams, int total_params,
7676 char **ppdata, int total_data,
7677 unsigned int max_data_bytes)
7679 char *pdata = *ppdata;
7680 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7682 /* check for an invalid fid before proceeding */
7685 reply_doserror(req, ERRDOS, ERRbadfid);
7689 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7690 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7691 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7692 if (*ppdata == NULL) {
7693 reply_nterror(req, NT_STATUS_NO_MEMORY);
7698 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7699 CAN ACCEPT THIS IN UNICODE. JRA. */
7701 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7702 srvstr_push(pdata, req->flags2, pdata + 2,
7703 global_myname(), 15,
7704 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7705 srvstr_push(pdata, req->flags2, pdata+18,
7706 lp_servicename(SNUM(conn)), 13,
7707 STR_ASCII|STR_TERMINATE); /* Service name */
7708 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7713 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7714 reply_doserror(req, ERRSRV, ERRerror);
7717 /****************************************************************************
7718 Reply to a SMBfindclose (stop trans2 directory search).
7719 ****************************************************************************/
7721 void reply_findclose(struct smb_request *req)
7725 START_PROFILE(SMBfindclose);
7728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7729 END_PROFILE(SMBfindclose);
7733 dptr_num = SVALS(req->vwv+0, 0);
7735 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7737 dptr_close(&dptr_num);
7739 reply_outbuf(req, 0, 0);
7741 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7743 END_PROFILE(SMBfindclose);
7747 /****************************************************************************
7748 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7749 ****************************************************************************/
7751 void reply_findnclose(struct smb_request *req)
7755 START_PROFILE(SMBfindnclose);
7758 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7759 END_PROFILE(SMBfindnclose);
7763 dptr_num = SVAL(req->vwv+0, 0);
7765 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7767 /* We never give out valid handles for a
7768 findnotifyfirst - so any dptr_num is ok here.
7771 reply_outbuf(req, 0, 0);
7773 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7775 END_PROFILE(SMBfindnclose);
7779 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7780 struct trans_state *state)
7782 if (Protocol >= PROTOCOL_NT1) {
7783 req->flags2 |= 0x40; /* IS_LONG_NAME */
7784 SSVAL(req->inbuf,smb_flg2,req->flags2);
7787 if (conn->encrypt_level == Required && !req->encrypted) {
7788 if (state->call != TRANSACT2_QFSINFO &&
7789 state->call != TRANSACT2_SETFSINFO) {
7790 DEBUG(0,("handle_trans2: encryption required "
7792 (unsigned int)state->call));
7793 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7798 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7800 /* Now we must call the relevant TRANS2 function */
7801 switch(state->call) {
7802 case TRANSACT2_OPEN:
7804 START_PROFILE(Trans2_open);
7805 call_trans2open(conn, req,
7806 &state->param, state->total_param,
7807 &state->data, state->total_data,
7808 state->max_data_return);
7809 END_PROFILE(Trans2_open);
7813 case TRANSACT2_FINDFIRST:
7815 START_PROFILE(Trans2_findfirst);
7816 call_trans2findfirst(conn, req,
7817 &state->param, state->total_param,
7818 &state->data, state->total_data,
7819 state->max_data_return);
7820 END_PROFILE(Trans2_findfirst);
7824 case TRANSACT2_FINDNEXT:
7826 START_PROFILE(Trans2_findnext);
7827 call_trans2findnext(conn, req,
7828 &state->param, state->total_param,
7829 &state->data, state->total_data,
7830 state->max_data_return);
7831 END_PROFILE(Trans2_findnext);
7835 case TRANSACT2_QFSINFO:
7837 START_PROFILE(Trans2_qfsinfo);
7838 call_trans2qfsinfo(conn, req,
7839 &state->param, state->total_param,
7840 &state->data, state->total_data,
7841 state->max_data_return);
7842 END_PROFILE(Trans2_qfsinfo);
7846 case TRANSACT2_SETFSINFO:
7848 START_PROFILE(Trans2_setfsinfo);
7849 call_trans2setfsinfo(conn, req,
7850 &state->param, state->total_param,
7851 &state->data, state->total_data,
7852 state->max_data_return);
7853 END_PROFILE(Trans2_setfsinfo);
7857 case TRANSACT2_QPATHINFO:
7858 case TRANSACT2_QFILEINFO:
7860 START_PROFILE(Trans2_qpathinfo);
7861 call_trans2qfilepathinfo(conn, req, state->call,
7862 &state->param, state->total_param,
7863 &state->data, state->total_data,
7864 state->max_data_return);
7865 END_PROFILE(Trans2_qpathinfo);
7869 case TRANSACT2_SETPATHINFO:
7870 case TRANSACT2_SETFILEINFO:
7872 START_PROFILE(Trans2_setpathinfo);
7873 call_trans2setfilepathinfo(conn, req, state->call,
7874 &state->param, state->total_param,
7875 &state->data, state->total_data,
7876 state->max_data_return);
7877 END_PROFILE(Trans2_setpathinfo);
7881 case TRANSACT2_FINDNOTIFYFIRST:
7883 START_PROFILE(Trans2_findnotifyfirst);
7884 call_trans2findnotifyfirst(conn, req,
7885 &state->param, state->total_param,
7886 &state->data, state->total_data,
7887 state->max_data_return);
7888 END_PROFILE(Trans2_findnotifyfirst);
7892 case TRANSACT2_FINDNOTIFYNEXT:
7894 START_PROFILE(Trans2_findnotifynext);
7895 call_trans2findnotifynext(conn, req,
7896 &state->param, state->total_param,
7897 &state->data, state->total_data,
7898 state->max_data_return);
7899 END_PROFILE(Trans2_findnotifynext);
7903 case TRANSACT2_MKDIR:
7905 START_PROFILE(Trans2_mkdir);
7906 call_trans2mkdir(conn, req,
7907 &state->param, state->total_param,
7908 &state->data, state->total_data,
7909 state->max_data_return);
7910 END_PROFILE(Trans2_mkdir);
7914 case TRANSACT2_GET_DFS_REFERRAL:
7916 START_PROFILE(Trans2_get_dfs_referral);
7917 call_trans2getdfsreferral(conn, req,
7918 &state->param, state->total_param,
7919 &state->data, state->total_data,
7920 state->max_data_return);
7921 END_PROFILE(Trans2_get_dfs_referral);
7925 case TRANSACT2_IOCTL:
7927 START_PROFILE(Trans2_ioctl);
7928 call_trans2ioctl(conn, req,
7929 &state->param, state->total_param,
7930 &state->data, state->total_data,
7931 state->max_data_return);
7932 END_PROFILE(Trans2_ioctl);
7937 /* Error in request */
7938 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7939 reply_doserror(req, ERRSRV,ERRerror);
7943 /****************************************************************************
7944 Reply to a SMBtrans2.
7945 ****************************************************************************/
7947 void reply_trans2(struct smb_request *req)
7949 connection_struct *conn = req->conn;
7954 unsigned int tran_call;
7955 struct trans_state *state;
7958 START_PROFILE(SMBtrans2);
7960 if (req->wct < 14) {
7961 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7962 END_PROFILE(SMBtrans2);
7966 dsoff = SVAL(req->vwv+12, 0);
7967 dscnt = SVAL(req->vwv+11, 0);
7968 psoff = SVAL(req->vwv+10, 0);
7969 pscnt = SVAL(req->vwv+9, 0);
7970 tran_call = SVAL(req->vwv+14, 0);
7972 result = allow_new_trans(conn->pending_trans, req->mid);
7973 if (!NT_STATUS_IS_OK(result)) {
7974 DEBUG(2, ("Got invalid trans2 request: %s\n",
7975 nt_errstr(result)));
7976 reply_nterror(req, result);
7977 END_PROFILE(SMBtrans2);
7982 switch (tran_call) {
7983 /* List the allowed trans2 calls on IPC$ */
7984 case TRANSACT2_OPEN:
7985 case TRANSACT2_GET_DFS_REFERRAL:
7986 case TRANSACT2_QFILEINFO:
7987 case TRANSACT2_QFSINFO:
7988 case TRANSACT2_SETFSINFO:
7991 reply_doserror(req, ERRSRV, ERRaccess);
7992 END_PROFILE(SMBtrans2);
7997 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7998 DEBUG(0, ("talloc failed\n"));
7999 reply_nterror(req, NT_STATUS_NO_MEMORY);
8000 END_PROFILE(SMBtrans2);
8004 state->cmd = SMBtrans2;
8006 state->mid = req->mid;
8007 state->vuid = req->vuid;
8008 state->setup_count = SVAL(req->vwv+13, 0);
8009 state->setup = NULL;
8010 state->total_param = SVAL(req->vwv+0, 0);
8011 state->param = NULL;
8012 state->total_data = SVAL(req->vwv+1, 0);
8014 state->max_param_return = SVAL(req->vwv+2, 0);
8015 state->max_data_return = SVAL(req->vwv+3, 0);
8016 state->max_setup_return = SVAL(req->vwv+4, 0);
8017 state->close_on_completion = BITSETW(req->vwv+5, 0);
8018 state->one_way = BITSETW(req->vwv+5, 1);
8020 state->call = tran_call;
8022 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8023 is so as a sanity check */
8024 if (state->setup_count != 1) {
8026 * Need to have rc=0 for ioctl to get job id for OS/2.
8027 * Network printing will fail if function is not successful.
8028 * Similar function in reply.c will be used if protocol
8029 * is LANMAN1.0 instead of LM1.2X002.
8030 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8031 * outbuf doesn't have to be set(only job id is used).
8033 if ( (state->setup_count == 4)
8034 && (tran_call == TRANSACT2_IOCTL)
8035 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8036 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8037 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8039 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8040 DEBUG(2,("Transaction is %d\n",tran_call));
8042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8043 END_PROFILE(SMBtrans2);
8048 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8051 if (state->total_data) {
8053 if (trans_oob(state->total_data, 0, dscnt)
8054 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8058 /* Can't use talloc here, the core routines do realloc on the
8059 * params and data. */
8060 state->data = (char *)SMB_MALLOC(state->total_data);
8061 if (state->data == NULL) {
8062 DEBUG(0,("reply_trans2: data malloc fail for %u "
8063 "bytes !\n", (unsigned int)state->total_data));
8065 reply_nterror(req, NT_STATUS_NO_MEMORY);
8066 END_PROFILE(SMBtrans2);
8070 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8073 if (state->total_param) {
8075 if (trans_oob(state->total_param, 0, pscnt)
8076 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8080 /* Can't use talloc here, the core routines do realloc on the
8081 * params and data. */
8082 state->param = (char *)SMB_MALLOC(state->total_param);
8083 if (state->param == NULL) {
8084 DEBUG(0,("reply_trans: param malloc fail for %u "
8085 "bytes !\n", (unsigned int)state->total_param));
8086 SAFE_FREE(state->data);
8088 reply_nterror(req, NT_STATUS_NO_MEMORY);
8089 END_PROFILE(SMBtrans2);
8093 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8096 state->received_data = dscnt;
8097 state->received_param = pscnt;
8099 if ((state->received_param == state->total_param) &&
8100 (state->received_data == state->total_data)) {
8102 handle_trans2(conn, req, state);
8104 SAFE_FREE(state->data);
8105 SAFE_FREE(state->param);
8107 END_PROFILE(SMBtrans2);
8111 DLIST_ADD(conn->pending_trans, state);
8113 /* We need to send an interim response then receive the rest
8114 of the parameter/data bytes */
8115 reply_outbuf(req, 0, 0);
8116 show_msg((char *)req->outbuf);
8117 END_PROFILE(SMBtrans2);
8122 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8123 SAFE_FREE(state->data);
8124 SAFE_FREE(state->param);
8126 END_PROFILE(SMBtrans2);
8127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8131 /****************************************************************************
8132 Reply to a SMBtranss2
8133 ****************************************************************************/
8135 void reply_transs2(struct smb_request *req)
8137 connection_struct *conn = req->conn;
8138 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8139 struct trans_state *state;
8141 START_PROFILE(SMBtranss2);
8143 show_msg((char *)req->inbuf);
8146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8147 END_PROFILE(SMBtranss2);
8151 for (state = conn->pending_trans; state != NULL;
8152 state = state->next) {
8153 if (state->mid == req->mid) {
8158 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8160 END_PROFILE(SMBtranss2);
8164 /* Revise state->total_param and state->total_data in case they have
8165 changed downwards */
8167 if (SVAL(req->vwv+0, 0) < state->total_param)
8168 state->total_param = SVAL(req->vwv+0, 0);
8169 if (SVAL(req->vwv+1, 0) < state->total_data)
8170 state->total_data = SVAL(req->vwv+1, 0);
8172 pcnt = SVAL(req->vwv+2, 0);
8173 poff = SVAL(req->vwv+3, 0);
8174 pdisp = SVAL(req->vwv+4, 0);
8176 dcnt = SVAL(req->vwv+5, 0);
8177 doff = SVAL(req->vwv+6, 0);
8178 ddisp = SVAL(req->vwv+7, 0);
8180 state->received_param += pcnt;
8181 state->received_data += dcnt;
8183 if ((state->received_data > state->total_data) ||
8184 (state->received_param > state->total_param))
8188 if (trans_oob(state->total_param, pdisp, pcnt)
8189 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8192 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8196 if (trans_oob(state->total_data, ddisp, dcnt)
8197 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8200 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8203 if ((state->received_param < state->total_param) ||
8204 (state->received_data < state->total_data)) {
8205 END_PROFILE(SMBtranss2);
8209 handle_trans2(conn, req, state);
8211 DLIST_REMOVE(conn->pending_trans, state);
8212 SAFE_FREE(state->data);
8213 SAFE_FREE(state->param);
8216 END_PROFILE(SMBtranss2);
8221 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8222 DLIST_REMOVE(conn->pending_trans, state);
8223 SAFE_FREE(state->data);
8224 SAFE_FREE(state->param);
8226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8227 END_PROFILE(SMBtranss2);