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(fname, deny_mode, open_ofun,
989 reply_doserror(req, ERRDOS, ERRbadaccess);
993 /* Any data in this call is an EA list. */
994 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
995 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
999 if (total_data != 4) {
1000 if (total_data < 10) {
1001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1005 if (IVAL(pdata,0) > total_data) {
1006 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1007 IVAL(pdata,0), (unsigned int)total_data));
1008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1012 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1018 } else if (IVAL(pdata,0) != 4) {
1019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1023 status = SMB_VFS_CREATE_FILE(
1026 0, /* root_dir_fid */
1027 smb_fname, /* fname */
1028 access_mask, /* access_mask */
1029 share_mode, /* share_access */
1030 create_disposition, /* create_disposition*/
1031 create_options, /* create_options */
1032 open_attr, /* file_attributes */
1033 oplock_request, /* oplock_request */
1034 open_size, /* allocation_size */
1036 ea_list, /* ea_list */
1038 &smb_action); /* psbuf */
1040 if (!NT_STATUS_IS_OK(status)) {
1041 if (open_was_deferred(req->mid)) {
1042 /* We have re-scheduled this call. */
1045 reply_openerror(req, status);
1049 size = get_file_size_stat(&smb_fname->st);
1050 fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st);
1051 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1052 inode = smb_fname->st.st_ex_ino;
1054 close_file(req, fsp, ERROR_CLOSE);
1055 reply_doserror(req, ERRDOS,ERRnoaccess);
1059 /* Realloc the size of parameters and data we will return */
1060 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1061 if(*pparams == NULL ) {
1062 reply_nterror(req, NT_STATUS_NO_MEMORY);
1067 SSVAL(params,0,fsp->fnum);
1068 SSVAL(params,2,fattr);
1069 srv_put_dos_date2(params,4, mtime);
1070 SIVAL(params,8, (uint32)size);
1071 SSVAL(params,12,deny_mode);
1072 SSVAL(params,14,0); /* open_type - file or directory. */
1073 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1075 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1076 smb_action |= EXTENDED_OPLOCK_GRANTED;
1079 SSVAL(params,18,smb_action);
1082 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1084 SIVAL(params,20,inode);
1085 SSVAL(params,24,0); /* Padding. */
1087 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1088 SIVAL(params, 26, ea_size);
1090 SIVAL(params, 26, 0);
1093 /* Send the required number of replies */
1094 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1096 TALLOC_FREE(smb_fname);
1099 /*********************************************************
1100 Routine to check if a given string matches exactly.
1101 as a special case a mask of "." does NOT match. That
1102 is required for correct wildcard semantics
1103 Case can be significant or not.
1104 **********************************************************/
1106 static bool exact_match(connection_struct *conn,
1110 if (mask[0] == '.' && mask[1] == 0)
1112 if (dptr_has_wild(conn->dirptr)) {
1115 if (conn->case_sensitive)
1116 return strcmp(str,mask)==0;
1118 return StrCaseCmp(str,mask) == 0;
1121 /****************************************************************************
1122 Return the filetype for UNIX extensions.
1123 ****************************************************************************/
1125 static uint32 unix_filetype(mode_t mode)
1128 return UNIX_TYPE_FILE;
1129 else if(S_ISDIR(mode))
1130 return UNIX_TYPE_DIR;
1132 else if(S_ISLNK(mode))
1133 return UNIX_TYPE_SYMLINK;
1136 else if(S_ISCHR(mode))
1137 return UNIX_TYPE_CHARDEV;
1140 else if(S_ISBLK(mode))
1141 return UNIX_TYPE_BLKDEV;
1144 else if(S_ISFIFO(mode))
1145 return UNIX_TYPE_FIFO;
1148 else if(S_ISSOCK(mode))
1149 return UNIX_TYPE_SOCKET;
1152 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1153 return UNIX_TYPE_UNKNOWN;
1156 /****************************************************************************
1157 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1158 ****************************************************************************/
1160 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1162 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1163 const SMB_STRUCT_STAT *psbuf,
1165 enum perm_type ptype,
1170 if (perms == SMB_MODE_NO_CHANGE) {
1171 if (!VALID_STAT(*psbuf)) {
1172 return NT_STATUS_INVALID_PARAMETER;
1174 *ret_perms = psbuf->st_ex_mode;
1175 return NT_STATUS_OK;
1179 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1180 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1181 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1182 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1183 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1184 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1185 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1186 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1187 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1189 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1192 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1195 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1200 /* Apply mode mask */
1201 ret &= lp_create_mask(SNUM(conn));
1202 /* Add in force bits */
1203 ret |= lp_force_create_mode(SNUM(conn));
1206 ret &= lp_dir_mask(SNUM(conn));
1207 /* Add in force bits */
1208 ret |= lp_force_dir_mode(SNUM(conn));
1210 case PERM_EXISTING_FILE:
1211 /* Apply mode mask */
1212 ret &= lp_security_mask(SNUM(conn));
1213 /* Add in force bits */
1214 ret |= lp_force_security_mode(SNUM(conn));
1216 case PERM_EXISTING_DIR:
1217 /* Apply mode mask */
1218 ret &= lp_dir_security_mask(SNUM(conn));
1219 /* Add in force bits */
1220 ret |= lp_force_dir_security_mode(SNUM(conn));
1225 return NT_STATUS_OK;
1228 /****************************************************************************
1229 Needed to show the msdfs symlinks as directories. Modifies psbuf
1230 to be a directory if it's a msdfs link.
1231 ****************************************************************************/
1233 static bool check_msdfs_link(connection_struct *conn,
1234 const char *pathname,
1235 SMB_STRUCT_STAT *psbuf)
1237 int saved_errno = errno;
1238 if(lp_host_msdfs() &&
1239 lp_msdfs_root(SNUM(conn)) &&
1240 is_msdfs_link(conn, pathname, psbuf)) {
1242 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1245 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1246 errno = saved_errno;
1249 errno = saved_errno;
1254 /****************************************************************************
1255 Get a level dependent lanman2 dir entry.
1256 ****************************************************************************/
1258 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1259 connection_struct *conn,
1261 const char *path_mask,
1264 int requires_resume_key,
1270 int space_remaining,
1272 bool *got_exact_match,
1273 int *last_entry_off,
1274 struct ea_list *name_list)
1278 SMB_STRUCT_STAT sbuf;
1279 const char *mask = NULL;
1280 char *pathreal = NULL;
1282 char *p, *q, *pdata = *ppdata;
1286 SMB_OFF_T file_size = 0;
1287 uint64_t allocation_size = 0;
1289 struct timespec mdate_ts, adate_ts, create_date_ts;
1290 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1292 char *last_entry_ptr;
1294 uint32 nt_extmode; /* Used for NT connections instead of mode */
1295 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1296 bool check_mangled_names = lp_manglednames(conn->params);
1297 char mangled_name[13]; /* mangled 8.3 name. */
1299 *out_of_space = False;
1300 *got_exact_match = False;
1302 ZERO_STRUCT(mdate_ts);
1303 ZERO_STRUCT(adate_ts);
1304 ZERO_STRUCT(create_date_ts);
1306 if (!conn->dirptr) {
1310 p = strrchr_m(path_mask,'/');
1313 mask = talloc_strdup(ctx,"*.*");
1323 bool ms_dfs_link = False;
1325 /* Needed if we run out of space */
1326 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1327 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1330 * Due to bugs in NT client redirectors we are not using
1331 * resume keys any more - set them to zero.
1332 * Check out the related comments in findfirst/findnext.
1338 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1339 (long)conn->dirptr,curr_dirpos));
1346 * fname may get mangled, dname is never mangled.
1347 * Whenever we're accessing the filesystem we use
1348 * pathreal which is composed from dname.
1354 /* Mangle fname if it's an illegal name. */
1355 if (mangle_must_mangle(dname,conn->params)) {
1356 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1358 continue; /* Error - couldn't mangle. */
1360 fname = talloc_strdup(ctx, mangled_name);
1366 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1367 got_match = mask_match(fname, mask, conn->case_sensitive);
1370 if(!got_match && check_mangled_names &&
1371 !mangle_is_8_3(fname, False, conn->params)) {
1373 * It turns out that NT matches wildcards against
1374 * both long *and* short names. This may explain some
1375 * of the wildcard wierdness from old DOS clients
1376 * that some people have been seeing.... JRA.
1378 /* Force the mangling into 8.3. */
1379 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1381 continue; /* Error - couldn't mangle. */
1384 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1385 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1390 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1392 if (dont_descend && !isdots) {
1399 pathreal = talloc_asprintf(ctx,
1404 pathreal = talloc_asprintf(ctx,
1415 if (INFO_LEVEL_IS_UNIX(info_level)) {
1416 if (vfs_lstat_smb_fname(conn, pathreal,
1418 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1419 pathreal,strerror(errno)));
1420 TALLOC_FREE(pathreal);
1424 } else if (!VALID_STAT(sbuf) &&
1425 vfs_stat_smb_fname(conn, pathreal,
1427 /* Needed to show the msdfs symlinks as
1430 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1432 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1433 pathreal,strerror(errno)));
1434 TALLOC_FREE(pathreal);
1441 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1443 mode = dos_mode(conn,pathreal,&sbuf);
1446 if (!dir_check_ftype(conn,mode,dirtype)) {
1447 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1448 TALLOC_FREE(pathreal);
1453 if (!(mode & aDIR)) {
1454 file_size = get_file_size_stat(&sbuf);
1456 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1458 if (ask_sharemode) {
1459 struct timespec write_time_ts;
1460 struct file_id fileid;
1462 ZERO_STRUCT(write_time_ts);
1463 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1464 get_file_infos(fileid, NULL, &write_time_ts);
1465 if (!null_timespec(write_time_ts)) {
1466 update_stat_ex_mtime(&sbuf, write_time_ts);
1470 mdate_ts = sbuf.st_ex_mtime;
1471 adate_ts = sbuf.st_ex_atime;
1472 create_date_ts = sbuf.st_ex_btime;
1474 if (lp_dos_filetime_resolution(SNUM(conn))) {
1475 dos_filetime_timespec(&create_date_ts);
1476 dos_filetime_timespec(&mdate_ts);
1477 dos_filetime_timespec(&adate_ts);
1480 create_date = convert_timespec_to_time_t(create_date_ts);
1481 mdate = convert_timespec_to_time_t(mdate_ts);
1482 adate = convert_timespec_to_time_t(adate_ts);
1484 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1489 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1499 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1501 switch (info_level) {
1502 case SMB_FIND_INFO_STANDARD:
1503 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1504 if(requires_resume_key) {
1508 srv_put_dos_date2(p,0,create_date);
1509 srv_put_dos_date2(p,4,adate);
1510 srv_put_dos_date2(p,8,mdate);
1511 SIVAL(p,12,(uint32)file_size);
1512 SIVAL(p,16,(uint32)allocation_size);
1516 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1517 p += ucs2_align(base_data, p, 0);
1519 len = srvstr_push(base_data, flags2, p,
1520 fname, PTR_DIFF(end_data, p),
1522 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1524 SCVAL(nameptr, -1, len - 2);
1526 SCVAL(nameptr, -1, 0);
1530 SCVAL(nameptr, -1, len - 1);
1532 SCVAL(nameptr, -1, 0);
1538 case SMB_FIND_EA_SIZE:
1539 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1540 if(requires_resume_key) {
1544 srv_put_dos_date2(p,0,create_date);
1545 srv_put_dos_date2(p,4,adate);
1546 srv_put_dos_date2(p,8,mdate);
1547 SIVAL(p,12,(uint32)file_size);
1548 SIVAL(p,16,(uint32)allocation_size);
1551 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1552 SIVAL(p,22,ea_size); /* Extended attributes */
1556 len = srvstr_push(base_data, flags2,
1557 p, fname, PTR_DIFF(end_data, p),
1558 STR_TERMINATE | STR_NOALIGN);
1559 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1572 SCVAL(nameptr,0,len);
1574 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1577 case SMB_FIND_EA_LIST:
1579 struct ea_list *file_list = NULL;
1582 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1586 if(requires_resume_key) {
1590 srv_put_dos_date2(p,0,create_date);
1591 srv_put_dos_date2(p,4,adate);
1592 srv_put_dos_date2(p,8,mdate);
1593 SIVAL(p,12,(uint32)file_size);
1594 SIVAL(p,16,(uint32)allocation_size);
1596 p += 22; /* p now points to the EA area. */
1598 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1599 name_list = ea_list_union(name_list, file_list, &ea_len);
1601 /* We need to determine if this entry will fit in the space available. */
1602 /* Max string size is 255 bytes. */
1603 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1604 /* Move the dirptr back to prev_dirpos */
1605 dptr_SeekDir(conn->dirptr, prev_dirpos);
1606 *out_of_space = True;
1607 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1608 return False; /* Not finished - just out of space */
1611 /* Push the ea_data followed by the name. */
1612 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1614 len = srvstr_push(base_data, flags2,
1615 p + 1, fname, PTR_DIFF(end_data, p+1),
1616 STR_TERMINATE | STR_NOALIGN);
1617 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1630 SCVAL(nameptr,0,len);
1632 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1636 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1637 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1638 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1640 SIVAL(p,0,reskey); p += 4;
1641 put_long_date_timespec(p,create_date_ts); p += 8;
1642 put_long_date_timespec(p,adate_ts); p += 8;
1643 put_long_date_timespec(p,mdate_ts); p += 8;
1644 put_long_date_timespec(p,mdate_ts); p += 8;
1645 SOFF_T(p,0,file_size); p += 8;
1646 SOFF_T(p,0,allocation_size); p += 8;
1647 SIVAL(p,0,nt_extmode); p += 4;
1648 q = p; p += 4; /* q is placeholder for name length. */
1650 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1651 SIVAL(p,0,ea_size); /* Extended attributes */
1654 /* Clear the short name buffer. This is
1655 * IMPORTANT as not doing so will trigger
1656 * a Win2k client bug. JRA.
1658 if (!was_8_3 && check_mangled_names) {
1659 if (!name_to_8_3(fname,mangled_name,True,
1661 /* Error - mangle failed ! */
1662 memset(mangled_name,'\0',12);
1664 mangled_name[12] = 0;
1665 len = srvstr_push(base_data, flags2,
1666 p+2, mangled_name, 24,
1667 STR_UPPER|STR_UNICODE);
1669 memset(p + 2 + len,'\0',24 - len);
1676 len = srvstr_push(base_data, flags2, p,
1677 fname, PTR_DIFF(end_data, p),
1678 STR_TERMINATE_ASCII);
1681 SIVAL(p,0,0); /* Ensure any padding is null. */
1682 len = PTR_DIFF(p, pdata);
1683 len = (len + 3) & ~3;
1688 case SMB_FIND_FILE_DIRECTORY_INFO:
1689 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1691 SIVAL(p,0,reskey); p += 4;
1692 put_long_date_timespec(p,create_date_ts); p += 8;
1693 put_long_date_timespec(p,adate_ts); p += 8;
1694 put_long_date_timespec(p,mdate_ts); p += 8;
1695 put_long_date_timespec(p,mdate_ts); p += 8;
1696 SOFF_T(p,0,file_size); p += 8;
1697 SOFF_T(p,0,allocation_size); p += 8;
1698 SIVAL(p,0,nt_extmode); p += 4;
1699 len = srvstr_push(base_data, flags2,
1700 p + 4, fname, PTR_DIFF(end_data, p+4),
1701 STR_TERMINATE_ASCII);
1704 SIVAL(p,0,0); /* Ensure any padding is null. */
1705 len = PTR_DIFF(p, pdata);
1706 len = (len + 3) & ~3;
1711 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1712 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1714 SIVAL(p,0,reskey); p += 4;
1715 put_long_date_timespec(p,create_date_ts); p += 8;
1716 put_long_date_timespec(p,adate_ts); p += 8;
1717 put_long_date_timespec(p,mdate_ts); p += 8;
1718 put_long_date_timespec(p,mdate_ts); p += 8;
1719 SOFF_T(p,0,file_size); p += 8;
1720 SOFF_T(p,0,allocation_size); p += 8;
1721 SIVAL(p,0,nt_extmode); p += 4;
1722 q = p; p += 4; /* q is placeholder for name length. */
1724 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1725 SIVAL(p,0,ea_size); /* Extended attributes */
1728 len = srvstr_push(base_data, flags2, p,
1729 fname, PTR_DIFF(end_data, p),
1730 STR_TERMINATE_ASCII);
1734 SIVAL(p,0,0); /* Ensure any padding is null. */
1735 len = PTR_DIFF(p, pdata);
1736 len = (len + 3) & ~3;
1741 case SMB_FIND_FILE_NAMES_INFO:
1742 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1744 SIVAL(p,0,reskey); p += 4;
1746 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1747 acl on a dir (tridge) */
1748 len = srvstr_push(base_data, flags2, p,
1749 fname, PTR_DIFF(end_data, p),
1750 STR_TERMINATE_ASCII);
1753 SIVAL(p,0,0); /* Ensure any padding is null. */
1754 len = PTR_DIFF(p, pdata);
1755 len = (len + 3) & ~3;
1760 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1761 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1763 SIVAL(p,0,reskey); p += 4;
1764 put_long_date_timespec(p,create_date_ts); p += 8;
1765 put_long_date_timespec(p,adate_ts); p += 8;
1766 put_long_date_timespec(p,mdate_ts); p += 8;
1767 put_long_date_timespec(p,mdate_ts); p += 8;
1768 SOFF_T(p,0,file_size); p += 8;
1769 SOFF_T(p,0,allocation_size); p += 8;
1770 SIVAL(p,0,nt_extmode); p += 4;
1771 q = p; p += 4; /* q is placeholder for name length. */
1773 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1774 SIVAL(p,0,ea_size); /* Extended attributes */
1777 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1778 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1779 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1780 len = srvstr_push(base_data, flags2, p,
1781 fname, PTR_DIFF(end_data, p),
1782 STR_TERMINATE_ASCII);
1785 SIVAL(p,0,0); /* Ensure any padding is null. */
1786 len = PTR_DIFF(p, pdata);
1787 len = (len + 3) & ~3;
1792 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1793 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1794 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1796 SIVAL(p,0,reskey); p += 4;
1797 put_long_date_timespec(p,create_date_ts); p += 8;
1798 put_long_date_timespec(p,adate_ts); p += 8;
1799 put_long_date_timespec(p,mdate_ts); p += 8;
1800 put_long_date_timespec(p,mdate_ts); p += 8;
1801 SOFF_T(p,0,file_size); p += 8;
1802 SOFF_T(p,0,allocation_size); p += 8;
1803 SIVAL(p,0,nt_extmode); p += 4;
1804 q = p; p += 4; /* q is placeholder for name length */
1806 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1807 SIVAL(p,0,ea_size); /* Extended attributes */
1810 /* Clear the short name buffer. This is
1811 * IMPORTANT as not doing so will trigger
1812 * a Win2k client bug. JRA.
1814 if (!was_8_3 && check_mangled_names) {
1815 if (!name_to_8_3(fname,mangled_name,True,
1817 /* Error - mangle failed ! */
1818 memset(mangled_name,'\0',12);
1820 mangled_name[12] = 0;
1821 len = srvstr_push(base_data, flags2,
1822 p+2, mangled_name, 24,
1823 STR_UPPER|STR_UNICODE);
1826 memset(p + 2 + len,'\0',24 - len);
1833 SSVAL(p,0,0); p += 2; /* Reserved ? */
1834 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1835 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1836 len = srvstr_push(base_data, flags2, p,
1837 fname, PTR_DIFF(end_data, p),
1838 STR_TERMINATE_ASCII);
1841 SIVAL(p,0,0); /* Ensure any padding is null. */
1842 len = PTR_DIFF(p, pdata);
1843 len = (len + 3) & ~3;
1848 /* CIFS UNIX Extension. */
1850 case SMB_FIND_FILE_UNIX:
1851 case SMB_FIND_FILE_UNIX_INFO2:
1853 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1855 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1857 if (info_level == SMB_FIND_FILE_UNIX) {
1858 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1859 p = store_file_unix_basic(conn, p,
1861 len = srvstr_push(base_data, flags2, p,
1862 fname, PTR_DIFF(end_data, p),
1865 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1866 p = store_file_unix_basic_info2(conn, p,
1870 len = srvstr_push(base_data, flags2, p, fname,
1871 PTR_DIFF(end_data, p), 0);
1872 SIVAL(nameptr, 0, len);
1876 SIVAL(p,0,0); /* Ensure any padding is null. */
1878 len = PTR_DIFF(p, pdata);
1879 len = (len + 3) & ~3;
1880 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1882 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1892 if (PTR_DIFF(p,pdata) > space_remaining) {
1893 /* Move the dirptr back to prev_dirpos */
1894 dptr_SeekDir(conn->dirptr, prev_dirpos);
1895 *out_of_space = True;
1896 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1897 return False; /* Not finished - just out of space */
1900 /* Setup the last entry pointer, as an offset from base_data */
1901 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1902 /* Advance the data pointer to the next slot */
1908 /****************************************************************************
1909 Reply to a TRANS2_FINDFIRST.
1910 ****************************************************************************/
1912 static void call_trans2findfirst(connection_struct *conn,
1913 struct smb_request *req,
1914 char **pparams, int total_params,
1915 char **ppdata, int total_data,
1916 unsigned int max_data_bytes)
1918 /* We must be careful here that we don't return more than the
1919 allowed number of data bytes. If this means returning fewer than
1920 maxentries then so be it. We assume that the redirector has
1921 enough room for the fixed number of parameter bytes it has
1923 struct smb_filename *smb_dname = NULL;
1924 char *params = *pparams;
1925 char *pdata = *ppdata;
1929 uint16 findfirst_flags;
1930 bool close_after_first;
1932 bool requires_resume_key;
1934 char *directory = NULL;
1937 int last_entry_off=0;
1941 bool finished = False;
1942 bool dont_descend = False;
1943 bool out_of_space = False;
1944 int space_remaining;
1945 bool mask_contains_wcard = False;
1946 struct ea_list *ea_list = NULL;
1947 NTSTATUS ntstatus = NT_STATUS_OK;
1948 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1949 TALLOC_CTX *ctx = talloc_tos();
1951 if (total_params < 13) {
1952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1956 dirtype = SVAL(params,0);
1957 maxentries = SVAL(params,2);
1958 findfirst_flags = SVAL(params,4);
1959 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1960 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1961 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1962 info_level = SVAL(params,6);
1964 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1965 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1966 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1967 info_level, max_data_bytes));
1970 /* W2K3 seems to treat zero as 1. */
1974 switch (info_level) {
1975 case SMB_FIND_INFO_STANDARD:
1976 case SMB_FIND_EA_SIZE:
1977 case SMB_FIND_EA_LIST:
1978 case SMB_FIND_FILE_DIRECTORY_INFO:
1979 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1980 case SMB_FIND_FILE_NAMES_INFO:
1981 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1982 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1983 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1985 case SMB_FIND_FILE_UNIX:
1986 case SMB_FIND_FILE_UNIX_INFO2:
1987 /* Always use filesystem for UNIX mtime query. */
1988 ask_sharemode = false;
1989 if (!lp_unix_extensions()) {
1990 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1995 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1999 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2000 params+12, total_params - 12,
2001 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2002 if (!NT_STATUS_IS_OK(ntstatus)) {
2003 reply_nterror(req, ntstatus);
2007 ntstatus = resolve_dfspath_wcard(ctx, conn,
2008 req->flags2 & FLAGS2_DFS_PATHNAMES,
2011 &mask_contains_wcard);
2012 if (!NT_STATUS_IS_OK(ntstatus)) {
2013 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2014 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2015 ERRSRV, ERRbadpath);
2018 reply_nterror(req, ntstatus);
2022 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2023 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2024 if (!NT_STATUS_IS_OK(ntstatus)) {
2025 reply_nterror(req, ntstatus);
2029 mask = smb_dname->original_lcomp;
2031 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2032 TALLOC_FREE(smb_dname);
2033 if (!NT_STATUS_IS_OK(ntstatus)) {
2034 reply_nterror(req, ntstatus);
2038 ntstatus = check_name(conn, directory);
2039 if (!NT_STATUS_IS_OK(ntstatus)) {
2040 reply_nterror(req, ntstatus);
2044 p = strrchr_m(directory,'/');
2046 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2047 if((directory[0] == '.') && (directory[1] == '\0')) {
2048 mask = talloc_strdup(ctx,"*");
2050 reply_nterror(req, NT_STATUS_NO_MEMORY);
2053 mask_contains_wcard = True;
2055 directory = talloc_strdup(talloc_tos(), "./");
2057 reply_nterror(req, NT_STATUS_NO_MEMORY);
2064 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2066 if (info_level == SMB_FIND_EA_LIST) {
2069 if (total_data < 4) {
2070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2074 ea_size = IVAL(pdata,0);
2075 if (ea_size != total_data) {
2076 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2077 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2082 if (!lp_ea_support(SNUM(conn))) {
2083 reply_doserror(req, ERRDOS, ERReasnotsupported);
2087 /* Pull out the list of names. */
2088 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2095 *ppdata = (char *)SMB_REALLOC(
2096 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2097 if(*ppdata == NULL ) {
2098 reply_nterror(req, NT_STATUS_NO_MEMORY);
2102 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2104 /* Realloc the params space */
2105 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2106 if (*pparams == NULL) {
2107 reply_nterror(req, NT_STATUS_NO_MEMORY);
2112 /* Save the wildcard match and attribs we are using on this directory -
2113 needed as lanman2 assumes these are being saved between calls */
2115 ntstatus = dptr_create(conn,
2121 mask_contains_wcard,
2125 if (!NT_STATUS_IS_OK(ntstatus)) {
2126 reply_nterror(req, ntstatus);
2130 dptr_num = dptr_dnum(conn->dirptr);
2131 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2133 /* Initialize per TRANS2_FIND_FIRST operation data */
2134 dptr_init_search_op(conn->dirptr);
2136 /* We don't need to check for VOL here as this is returned by
2137 a different TRANS2 call. */
2139 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2140 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2141 dont_descend = True;
2144 space_remaining = max_data_bytes;
2145 out_of_space = False;
2147 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2148 bool got_exact_match = False;
2150 /* this is a heuristic to avoid seeking the dirptr except when
2151 absolutely necessary. It allows for a filename of about 40 chars */
2152 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2153 out_of_space = True;
2156 finished = !get_lanman2_dir_entry(ctx,
2159 mask,dirtype,info_level,
2160 requires_resume_key,dont_descend,
2163 space_remaining, &out_of_space,
2165 &last_entry_off, ea_list);
2168 if (finished && out_of_space)
2171 if (!finished && !out_of_space)
2175 * As an optimisation if we know we aren't looking
2176 * for a wildcard name (ie. the name matches the wildcard exactly)
2177 * then we can finish on any (first) match.
2178 * This speeds up large directory searches. JRA.
2184 /* Ensure space_remaining never goes -ve. */
2185 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2186 space_remaining = 0;
2187 out_of_space = true;
2189 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2193 /* Check if we can close the dirptr */
2194 if(close_after_first || (finished && close_if_end)) {
2195 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2196 dptr_close(&dptr_num);
2200 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2201 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2202 * the protocol level is less than NT1. Tested with smbclient. JRA.
2203 * This should fix the OS/2 client bug #2335.
2206 if(numentries == 0) {
2207 dptr_close(&dptr_num);
2208 if (Protocol < PROTOCOL_NT1) {
2209 reply_doserror(req, ERRDOS, ERRnofiles);
2212 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2213 ERRDOS, ERRbadfile);
2218 /* At this point pdata points to numentries directory entries. */
2220 /* Set up the return parameter block */
2221 SSVAL(params,0,dptr_num);
2222 SSVAL(params,2,numentries);
2223 SSVAL(params,4,finished);
2224 SSVAL(params,6,0); /* Never an EA error */
2225 SSVAL(params,8,last_entry_off);
2227 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2230 if ((! *directory) && dptr_path(dptr_num)) {
2231 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2233 reply_nterror(req, NT_STATUS_NO_MEMORY);
2237 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2238 smb_fn_name(req->cmd),
2239 mask, directory, dirtype, numentries ) );
2242 * Force a name mangle here to ensure that the
2243 * mask as an 8.3 name is top of the mangled cache.
2244 * The reasons for this are subtle. Don't remove
2245 * this code unless you know what you are doing
2246 * (see PR#13758). JRA.
2249 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2250 char mangled_name[13];
2251 name_to_8_3(mask, mangled_name, True, conn->params);
2257 /****************************************************************************
2258 Reply to a TRANS2_FINDNEXT.
2259 ****************************************************************************/
2261 static void call_trans2findnext(connection_struct *conn,
2262 struct smb_request *req,
2263 char **pparams, int total_params,
2264 char **ppdata, int total_data,
2265 unsigned int max_data_bytes)
2267 /* We must be careful here that we don't return more than the
2268 allowed number of data bytes. If this means returning fewer than
2269 maxentries then so be it. We assume that the redirector has
2270 enough room for the fixed number of parameter bytes it has
2272 char *params = *pparams;
2273 char *pdata = *ppdata;
2279 uint16 findnext_flags;
2280 bool close_after_request;
2282 bool requires_resume_key;
2284 bool mask_contains_wcard = False;
2285 char *resume_name = NULL;
2286 const char *mask = NULL;
2287 const char *directory = NULL;
2291 int i, last_entry_off=0;
2292 bool finished = False;
2293 bool dont_descend = False;
2294 bool out_of_space = False;
2295 int space_remaining;
2296 struct ea_list *ea_list = NULL;
2297 NTSTATUS ntstatus = NT_STATUS_OK;
2298 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2299 TALLOC_CTX *ctx = talloc_tos();
2301 if (total_params < 13) {
2302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2306 dptr_num = SVAL(params,0);
2307 maxentries = SVAL(params,2);
2308 info_level = SVAL(params,4);
2309 resume_key = IVAL(params,6);
2310 findnext_flags = SVAL(params,10);
2311 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2312 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2313 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2314 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2316 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2318 total_params - 12, STR_TERMINATE, &ntstatus,
2319 &mask_contains_wcard);
2320 if (!NT_STATUS_IS_OK(ntstatus)) {
2321 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2322 complain (it thinks we're asking for the directory above the shared
2323 path or an invalid name). Catch this as the resume name is only compared, never used in
2324 a file access. JRA. */
2325 srvstr_pull_talloc(ctx, params, req->flags2,
2326 &resume_name, params+12,
2330 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2331 reply_nterror(req, ntstatus);
2336 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2337 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2338 resume_key = %d resume name = %s continue=%d level = %d\n",
2339 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2340 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2343 /* W2K3 seems to treat zero as 1. */
2347 switch (info_level) {
2348 case SMB_FIND_INFO_STANDARD:
2349 case SMB_FIND_EA_SIZE:
2350 case SMB_FIND_EA_LIST:
2351 case SMB_FIND_FILE_DIRECTORY_INFO:
2352 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2353 case SMB_FIND_FILE_NAMES_INFO:
2354 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2355 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2356 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2358 case SMB_FIND_FILE_UNIX:
2359 case SMB_FIND_FILE_UNIX_INFO2:
2360 /* Always use filesystem for UNIX mtime query. */
2361 ask_sharemode = false;
2362 if (!lp_unix_extensions()) {
2363 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2368 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2372 if (info_level == SMB_FIND_EA_LIST) {
2375 if (total_data < 4) {
2376 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2380 ea_size = IVAL(pdata,0);
2381 if (ea_size != total_data) {
2382 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2383 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2384 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2388 if (!lp_ea_support(SNUM(conn))) {
2389 reply_doserror(req, ERRDOS, ERReasnotsupported);
2393 /* Pull out the list of names. */
2394 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2401 *ppdata = (char *)SMB_REALLOC(
2402 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2403 if(*ppdata == NULL) {
2404 reply_nterror(req, NT_STATUS_NO_MEMORY);
2409 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2411 /* Realloc the params space */
2412 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2413 if(*pparams == NULL ) {
2414 reply_nterror(req, NT_STATUS_NO_MEMORY);
2420 /* Check that the dptr is valid */
2421 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2422 reply_doserror(req, ERRDOS, ERRnofiles);
2426 string_set(&conn->dirpath,dptr_path(dptr_num));
2428 /* Get the wildcard mask from the dptr */
2429 if((p = dptr_wcard(dptr_num))== NULL) {
2430 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2431 reply_doserror(req, ERRDOS, ERRnofiles);
2436 directory = conn->dirpath;
2438 /* Get the attr mask from the dptr */
2439 dirtype = dptr_attr(dptr_num);
2441 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2442 dptr_num, mask, dirtype,
2444 dptr_TellDir(conn->dirptr)));
2446 /* Initialize per TRANS2_FIND_NEXT operation data */
2447 dptr_init_search_op(conn->dirptr);
2449 /* We don't need to check for VOL here as this is returned by
2450 a different TRANS2 call. */
2452 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2453 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2454 dont_descend = True;
2457 space_remaining = max_data_bytes;
2458 out_of_space = False;
2461 * Seek to the correct position. We no longer use the resume key but
2462 * depend on the last file name instead.
2465 if(*resume_name && !continue_bit) {
2468 long current_pos = 0;
2470 * Remember, name_to_8_3 is called by
2471 * get_lanman2_dir_entry(), so the resume name
2472 * could be mangled. Ensure we check the unmangled name.
2475 if (mangle_is_mangled(resume_name, conn->params)) {
2476 char *new_resume_name = NULL;
2477 mangle_lookup_name_from_8_3(ctx,
2481 if (new_resume_name) {
2482 resume_name = new_resume_name;
2487 * Fix for NT redirector problem triggered by resume key indexes
2488 * changing between directory scans. We now return a resume key of 0
2489 * and instead look for the filename to continue from (also given
2490 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2491 * findfirst/findnext (as is usual) then the directory pointer
2492 * should already be at the correct place.
2495 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2496 } /* end if resume_name && !continue_bit */
2498 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2499 bool got_exact_match = False;
2501 /* this is a heuristic to avoid seeking the dirptr except when
2502 absolutely necessary. It allows for a filename of about 40 chars */
2503 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2504 out_of_space = True;
2507 finished = !get_lanman2_dir_entry(ctx,
2510 mask,dirtype,info_level,
2511 requires_resume_key,dont_descend,
2514 space_remaining, &out_of_space,
2516 &last_entry_off, ea_list);
2519 if (finished && out_of_space)
2522 if (!finished && !out_of_space)
2526 * As an optimisation if we know we aren't looking
2527 * for a wildcard name (ie. the name matches the wildcard exactly)
2528 * then we can finish on any (first) match.
2529 * This speeds up large directory searches. JRA.
2535 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2538 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2539 smb_fn_name(req->cmd),
2540 mask, directory, dirtype, numentries ) );
2542 /* Check if we can close the dirptr */
2543 if(close_after_request || (finished && close_if_end)) {
2544 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2545 dptr_close(&dptr_num); /* This frees up the saved mask */
2548 /* Set up the return parameter block */
2549 SSVAL(params,0,numentries);
2550 SSVAL(params,2,finished);
2551 SSVAL(params,4,0); /* Never an EA error */
2552 SSVAL(params,6,last_entry_off);
2554 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2560 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2562 E_md4hash(lp_servicename(SNUM(conn)),objid);
2566 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2568 SMB_ASSERT(extended_info != NULL);
2570 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2571 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2572 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2573 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2574 #ifdef SAMBA_VERSION_REVISION
2575 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2577 extended_info->samba_subversion = 0;
2578 #ifdef SAMBA_VERSION_RC_RELEASE
2579 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2581 #ifdef SAMBA_VERSION_PRE_RELEASE
2582 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2585 #ifdef SAMBA_VERSION_VENDOR_PATCH
2586 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2588 extended_info->samba_gitcommitdate = 0;
2589 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2590 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2593 memset(extended_info->samba_version_string, 0,
2594 sizeof(extended_info->samba_version_string));
2596 snprintf (extended_info->samba_version_string,
2597 sizeof(extended_info->samba_version_string),
2598 "%s", samba_version_string());
2601 /****************************************************************************
2602 Reply to a TRANS2_QFSINFO (query filesystem info).
2603 ****************************************************************************/
2605 static void call_trans2qfsinfo(connection_struct *conn,
2606 struct smb_request *req,
2607 char **pparams, int total_params,
2608 char **ppdata, int total_data,
2609 unsigned int max_data_bytes)
2611 char *pdata, *end_data;
2612 char *params = *pparams;
2616 const char *vname = volume_label(SNUM(conn));
2617 int snum = SNUM(conn);
2618 char *fstype = lp_fstype(SNUM(conn));
2619 uint32 additional_flags = 0;
2621 if (total_params < 2) {
2622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2626 info_level = SVAL(params,0);
2629 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2630 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2631 "info level (0x%x) on IPC$.\n",
2632 (unsigned int)info_level));
2633 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2638 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2639 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2640 DEBUG(0,("call_trans2qfsinfo: encryption required "
2641 "and info level 0x%x sent.\n",
2642 (unsigned int)info_level));
2643 exit_server_cleanly("encryption required "
2649 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2651 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
2652 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2653 reply_doserror(req, ERRSRV, ERRinvdevice);
2657 *ppdata = (char *)SMB_REALLOC(
2658 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2659 if (*ppdata == NULL ) {
2660 reply_nterror(req, NT_STATUS_NO_MEMORY);
2665 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2666 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2668 switch (info_level) {
2669 case SMB_INFO_ALLOCATION:
2671 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2673 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2674 reply_unixerror(req, ERRHRD, ERRgeneral);
2678 block_size = lp_block_size(snum);
2679 if (bsize < block_size) {
2680 uint64_t factor = block_size/bsize;
2685 if (bsize > block_size) {
2686 uint64_t factor = bsize/block_size;
2691 bytes_per_sector = 512;
2692 sectors_per_unit = bsize/bytes_per_sector;
2694 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2695 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2696 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2698 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2699 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2700 SIVAL(pdata,l1_cUnit,dsize);
2701 SIVAL(pdata,l1_cUnitAvail,dfree);
2702 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2706 case SMB_INFO_VOLUME:
2707 /* Return volume name */
2709 * Add volume serial number - hash of a combination of
2710 * the called hostname and the service name.
2712 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2714 * Win2k3 and previous mess this up by sending a name length
2715 * one byte short. I believe only older clients (OS/2 Win9x) use
2716 * this call so try fixing this by adding a terminating null to
2717 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2721 pdata+l2_vol_szVolLabel, vname,
2722 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2723 STR_NOALIGN|STR_TERMINATE);
2724 SCVAL(pdata,l2_vol_cch,len);
2725 data_len = l2_vol_szVolLabel + len;
2726 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2727 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2731 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2732 case SMB_FS_ATTRIBUTE_INFORMATION:
2734 additional_flags = 0;
2735 #if defined(HAVE_SYS_QUOTAS)
2736 additional_flags |= FILE_VOLUME_QUOTAS;
2739 if(lp_nt_acl_support(SNUM(conn))) {
2740 additional_flags |= FILE_PERSISTENT_ACLS;
2743 /* Capabilities are filled in at connection time through STATVFS call */
2744 additional_flags |= conn->fs_capabilities;
2746 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2747 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2748 additional_flags); /* FS ATTRIBUTES */
2750 SIVAL(pdata,4,255); /* Max filename component length */
2751 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2752 and will think we can't do long filenames */
2753 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2754 PTR_DIFF(end_data, pdata+12),
2757 data_len = 12 + len;
2760 case SMB_QUERY_FS_LABEL_INFO:
2761 case SMB_FS_LABEL_INFORMATION:
2762 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2763 PTR_DIFF(end_data, pdata+4), 0);
2768 case SMB_QUERY_FS_VOLUME_INFO:
2769 case SMB_FS_VOLUME_INFORMATION:
2772 * Add volume serial number - hash of a combination of
2773 * the called hostname and the service name.
2775 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2776 (str_checksum(get_local_machine_name())<<16));
2778 /* Max label len is 32 characters. */
2779 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2780 PTR_DIFF(end_data, pdata+18),
2782 SIVAL(pdata,12,len);
2785 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2786 (int)strlen(vname),vname, lp_servicename(snum)));
2789 case SMB_QUERY_FS_SIZE_INFO:
2790 case SMB_FS_SIZE_INFORMATION:
2792 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2794 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2795 reply_unixerror(req, ERRHRD, ERRgeneral);
2798 block_size = lp_block_size(snum);
2799 if (bsize < block_size) {
2800 uint64_t factor = block_size/bsize;
2805 if (bsize > block_size) {
2806 uint64_t factor = bsize/block_size;
2811 bytes_per_sector = 512;
2812 sectors_per_unit = bsize/bytes_per_sector;
2813 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2814 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2815 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2816 SBIG_UINT(pdata,0,dsize);
2817 SBIG_UINT(pdata,8,dfree);
2818 SIVAL(pdata,16,sectors_per_unit);
2819 SIVAL(pdata,20,bytes_per_sector);
2823 case SMB_FS_FULL_SIZE_INFORMATION:
2825 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2827 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2828 reply_unixerror(req, ERRHRD, ERRgeneral);
2831 block_size = lp_block_size(snum);
2832 if (bsize < block_size) {
2833 uint64_t factor = block_size/bsize;
2838 if (bsize > block_size) {
2839 uint64_t factor = bsize/block_size;
2844 bytes_per_sector = 512;
2845 sectors_per_unit = bsize/bytes_per_sector;
2846 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2847 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2848 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2849 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2850 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2851 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2852 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2853 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2857 case SMB_QUERY_FS_DEVICE_INFO:
2858 case SMB_FS_DEVICE_INFORMATION:
2860 SIVAL(pdata,0,0); /* dev type */
2861 SIVAL(pdata,4,0); /* characteristics */
2864 #ifdef HAVE_SYS_QUOTAS
2865 case SMB_FS_QUOTA_INFORMATION:
2867 * what we have to send --metze:
2869 * Unknown1: 24 NULL bytes
2870 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2871 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2872 * Quota Flags: 2 byte :
2873 * Unknown3: 6 NULL bytes
2877 * details for Quota Flags:
2879 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2880 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2881 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2882 * 0x0001 Enable Quotas: enable quota for this fs
2886 /* we need to fake up a fsp here,
2887 * because its not send in this call
2890 SMB_NTQUOTA_STRUCT quotas;
2893 ZERO_STRUCT(quotas);
2899 if (conn->server_info->utok.uid != 0) {
2900 DEBUG(0,("set_user_quota: access_denied "
2901 "service [%s] user [%s]\n",
2902 lp_servicename(SNUM(conn)),
2903 conn->server_info->unix_name));
2904 reply_doserror(req, ERRDOS, ERRnoaccess);
2908 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2909 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2910 reply_doserror(req, ERRSRV, ERRerror);
2916 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2918 /* Unknown1 24 NULL bytes*/
2919 SBIG_UINT(pdata,0,(uint64_t)0);
2920 SBIG_UINT(pdata,8,(uint64_t)0);
2921 SBIG_UINT(pdata,16,(uint64_t)0);
2923 /* Default Soft Quota 8 bytes */
2924 SBIG_UINT(pdata,24,quotas.softlim);
2926 /* Default Hard Quota 8 bytes */
2927 SBIG_UINT(pdata,32,quotas.hardlim);
2929 /* Quota flag 2 bytes */
2930 SSVAL(pdata,40,quotas.qflags);
2932 /* Unknown3 6 NULL bytes */
2938 #endif /* HAVE_SYS_QUOTAS */
2939 case SMB_FS_OBJECTID_INFORMATION:
2941 unsigned char objid[16];
2942 struct smb_extended_info extended_info;
2943 memcpy(pdata,create_volume_objectid(conn, objid),16);
2944 samba_extended_info_version (&extended_info);
2945 SIVAL(pdata,16,extended_info.samba_magic);
2946 SIVAL(pdata,20,extended_info.samba_version);
2947 SIVAL(pdata,24,extended_info.samba_subversion);
2948 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2949 memcpy(pdata+36,extended_info.samba_version_string,28);
2955 * Query the version and capabilities of the CIFS UNIX extensions
2959 case SMB_QUERY_CIFS_UNIX_INFO:
2961 bool large_write = lp_min_receive_file_size() &&
2962 !srv_is_signing_active(smbd_server_conn);
2963 bool large_read = !srv_is_signing_active(smbd_server_conn);
2964 int encrypt_caps = 0;
2966 if (!lp_unix_extensions()) {
2967 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2971 switch (conn->encrypt_level) {
2977 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2980 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2981 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2982 large_write = false;
2988 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2989 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2991 /* We have POSIX ACLs, pathname, encryption,
2992 * large read/write, and locking capability. */
2994 SBIG_UINT(pdata,4,((uint64_t)(
2995 CIFS_UNIX_POSIX_ACLS_CAP|
2996 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2997 CIFS_UNIX_FCNTL_LOCKS_CAP|
2998 CIFS_UNIX_EXTATTR_CAP|
2999 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3001 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3003 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3007 case SMB_QUERY_POSIX_FS_INFO:
3010 vfs_statvfs_struct svfs;
3012 if (!lp_unix_extensions()) {
3013 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3017 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3021 SIVAL(pdata,0,svfs.OptimalTransferSize);
3022 SIVAL(pdata,4,svfs.BlockSize);
3023 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3024 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3025 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3026 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3027 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3028 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3029 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3031 } else if (rc == EOPNOTSUPP) {
3032 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3034 #endif /* EOPNOTSUPP */
3036 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3037 reply_doserror(req, ERRSRV, ERRerror);
3043 case SMB_QUERY_POSIX_WHOAMI:
3049 if (!lp_unix_extensions()) {
3050 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3054 if (max_data_bytes < 40) {
3055 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3059 /* We ARE guest if global_sid_Builtin_Guests is
3060 * in our list of SIDs.
3062 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3063 conn->server_info->ptok)) {
3064 flags |= SMB_WHOAMI_GUEST;
3067 /* We are NOT guest if global_sid_Authenticated_Users
3068 * is in our list of SIDs.
3070 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3071 conn->server_info->ptok)) {
3072 flags &= ~SMB_WHOAMI_GUEST;
3075 /* NOTE: 8 bytes for UID/GID, irrespective of native
3076 * platform size. This matches
3077 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3079 data_len = 4 /* flags */
3086 + 4 /* pad/reserved */
3087 + (conn->server_info->utok.ngroups * 8)
3089 + (conn->server_info->ptok->num_sids *
3093 SIVAL(pdata, 0, flags);
3094 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3096 (uint64_t)conn->server_info->utok.uid);
3097 SBIG_UINT(pdata, 16,
3098 (uint64_t)conn->server_info->utok.gid);
3101 if (data_len >= max_data_bytes) {
3102 /* Potential overflow, skip the GIDs and SIDs. */
3104 SIVAL(pdata, 24, 0); /* num_groups */
3105 SIVAL(pdata, 28, 0); /* num_sids */
3106 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3107 SIVAL(pdata, 36, 0); /* reserved */
3113 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3114 SIVAL(pdata, 28, conn->server_info->num_sids);
3116 /* We walk the SID list twice, but this call is fairly
3117 * infrequent, and I don't expect that it's performance
3118 * sensitive -- jpeach
3120 for (i = 0, sid_bytes = 0;
3121 i < conn->server_info->ptok->num_sids; ++i) {
3122 sid_bytes += ndr_size_dom_sid(
3123 &conn->server_info->ptok->user_sids[i],
3128 /* SID list byte count */
3129 SIVAL(pdata, 32, sid_bytes);
3131 /* 4 bytes pad/reserved - must be zero */
3132 SIVAL(pdata, 36, 0);
3136 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3137 SBIG_UINT(pdata, data_len,
3138 (uint64_t)conn->server_info->utok.groups[i]);
3144 i < conn->server_info->ptok->num_sids; ++i) {
3145 int sid_len = ndr_size_dom_sid(
3146 &conn->server_info->ptok->user_sids[i],
3150 sid_linearize(pdata + data_len, sid_len,
3151 &conn->server_info->ptok->user_sids[i]);
3152 data_len += sid_len;
3158 case SMB_MAC_QUERY_FS_INFO:
3160 * Thursby MAC extension... ONLY on NTFS filesystems
3161 * once we do streams then we don't need this
3163 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3165 SIVAL(pdata,84,0x100); /* Don't support mac... */
3170 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3175 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3178 DEBUG( 4, ( "%s info_level = %d\n",
3179 smb_fn_name(req->cmd), info_level) );
3184 /****************************************************************************
3185 Reply to a TRANS2_SETFSINFO (set filesystem info).
3186 ****************************************************************************/
3188 static void call_trans2setfsinfo(connection_struct *conn,
3189 struct smb_request *req,
3190 char **pparams, int total_params,
3191 char **ppdata, int total_data,
3192 unsigned int max_data_bytes)
3194 char *pdata = *ppdata;
3195 char *params = *pparams;
3198 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3201 if (total_params < 4) {
3202 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3204 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3208 info_level = SVAL(params,2);
3211 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3212 info_level != SMB_SET_CIFS_UNIX_INFO) {
3213 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3214 "info level (0x%x) on IPC$.\n",
3215 (unsigned int)info_level));
3216 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3221 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3222 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3223 DEBUG(0,("call_trans2setfsinfo: encryption required "
3224 "and info level 0x%x sent.\n",
3225 (unsigned int)info_level));
3226 exit_server_cleanly("encryption required "
3232 switch(info_level) {
3233 case SMB_SET_CIFS_UNIX_INFO:
3235 uint16 client_unix_major;
3236 uint16 client_unix_minor;
3237 uint32 client_unix_cap_low;
3238 uint32 client_unix_cap_high;
3240 if (!lp_unix_extensions()) {
3242 NT_STATUS_INVALID_LEVEL);
3246 /* There should be 12 bytes of capabilities set. */
3247 if (total_data < 8) {
3250 NT_STATUS_INVALID_PARAMETER);
3253 client_unix_major = SVAL(pdata,0);
3254 client_unix_minor = SVAL(pdata,2);
3255 client_unix_cap_low = IVAL(pdata,4);
3256 client_unix_cap_high = IVAL(pdata,8);
3257 /* Just print these values for now. */
3258 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3259 cap_low = 0x%x, cap_high = 0x%x\n",
3260 (unsigned int)client_unix_major,
3261 (unsigned int)client_unix_minor,
3262 (unsigned int)client_unix_cap_low,
3263 (unsigned int)client_unix_cap_high ));
3265 /* Here is where we must switch to posix pathname processing... */
3266 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3267 lp_set_posix_pathnames();
3268 mangle_change_to_posix();
3271 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3272 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3273 /* Client that knows how to do posix locks,
3274 * but not posix open/mkdir operations. Set a
3275 * default type for read/write checks. */
3277 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3283 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3286 size_t param_len = 0;
3287 size_t data_len = total_data;
3289 if (!lp_unix_extensions()) {
3292 NT_STATUS_INVALID_LEVEL);
3296 if (lp_smb_encrypt(SNUM(conn)) == false) {
3299 NT_STATUS_NOT_SUPPORTED);
3303 DEBUG( 4,("call_trans2setfsinfo: "
3304 "request transport encryption.\n"));
3306 status = srv_request_encryption_setup(conn,
3307 (unsigned char **)ppdata,
3309 (unsigned char **)pparams,
3312 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3313 !NT_STATUS_IS_OK(status)) {
3314 reply_nterror(req, status);
3318 send_trans2_replies(conn, req,
3325 if (NT_STATUS_IS_OK(status)) {
3326 /* Server-side transport
3327 * encryption is now *on*. */
3328 status = srv_encryption_start(conn);
3329 if (!NT_STATUS_IS_OK(status)) {
3330 exit_server_cleanly(
3331 "Failure in setting "
3332 "up encrypted transport");
3338 case SMB_FS_QUOTA_INFORMATION:
3340 files_struct *fsp = NULL;
3341 SMB_NTQUOTA_STRUCT quotas;
3343 ZERO_STRUCT(quotas);
3346 if ((conn->server_info->utok.uid != 0)
3347 ||!CAN_WRITE(conn)) {
3348 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3349 lp_servicename(SNUM(conn)),
3350 conn->server_info->unix_name));
3351 reply_doserror(req, ERRSRV, ERRaccess);
3355 /* note: normaly there're 48 bytes,
3356 * but we didn't use the last 6 bytes for now
3359 fsp = file_fsp(req, SVAL(params,0));
3361 if (!check_fsp_ntquota_handle(conn, req,
3363 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3365 req, NT_STATUS_INVALID_HANDLE);
3369 if (total_data < 42) {
3370 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3374 NT_STATUS_INVALID_PARAMETER);
3378 /* unknown_1 24 NULL bytes in pdata*/
3380 /* the soft quotas 8 bytes (uint64_t)*/
3381 quotas.softlim = (uint64_t)IVAL(pdata,24);
3382 #ifdef LARGE_SMB_OFF_T
3383 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3384 #else /* LARGE_SMB_OFF_T */
3385 if ((IVAL(pdata,28) != 0)&&
3386 ((quotas.softlim != 0xFFFFFFFF)||
3387 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3388 /* more than 32 bits? */
3391 NT_STATUS_INVALID_PARAMETER);
3394 #endif /* LARGE_SMB_OFF_T */
3396 /* the hard quotas 8 bytes (uint64_t)*/
3397 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3398 #ifdef LARGE_SMB_OFF_T
3399 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3400 #else /* LARGE_SMB_OFF_T */
3401 if ((IVAL(pdata,36) != 0)&&
3402 ((quotas.hardlim != 0xFFFFFFFF)||
3403 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3404 /* more than 32 bits? */
3407 NT_STATUS_INVALID_PARAMETER);
3410 #endif /* LARGE_SMB_OFF_T */
3412 /* quota_flags 2 bytes **/
3413 quotas.qflags = SVAL(pdata,40);
3415 /* unknown_2 6 NULL bytes follow*/
3417 /* now set the quotas */
3418 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3419 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3420 reply_doserror(req, ERRSRV, ERRerror);
3427 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3429 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3435 * sending this reply works fine,
3436 * but I'm not sure it's the same
3437 * like windows do...
3440 reply_outbuf(req, 10, 0);
3443 #if defined(HAVE_POSIX_ACLS)
3444 /****************************************************************************
3445 Utility function to count the number of entries in a POSIX acl.
3446 ****************************************************************************/
3448 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3450 unsigned int ace_count = 0;
3451 int entry_id = SMB_ACL_FIRST_ENTRY;
3452 SMB_ACL_ENTRY_T entry;
3454 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3456 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3457 entry_id = SMB_ACL_NEXT_ENTRY;
3464 /****************************************************************************
3465 Utility function to marshall a POSIX acl into wire format.
3466 ****************************************************************************/
3468 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3470 int entry_id = SMB_ACL_FIRST_ENTRY;
3471 SMB_ACL_ENTRY_T entry;
3473 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3474 SMB_ACL_TAG_T tagtype;
3475 SMB_ACL_PERMSET_T permset;
3476 unsigned char perms = 0;
3477 unsigned int own_grp;
3480 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3481 entry_id = SMB_ACL_NEXT_ENTRY;
3484 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3485 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3489 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3490 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3494 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3495 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3496 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3498 SCVAL(pdata,1,perms);
3501 case SMB_ACL_USER_OBJ:
3502 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3503 own_grp = (unsigned int)pst->st_ex_uid;
3504 SIVAL(pdata,2,own_grp);
3509 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3511 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3514 own_grp = (unsigned int)*puid;
3515 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3516 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3517 SIVAL(pdata,2,own_grp);
3521 case SMB_ACL_GROUP_OBJ:
3522 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3523 own_grp = (unsigned int)pst->st_ex_gid;
3524 SIVAL(pdata,2,own_grp);
3529 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3531 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3534 own_grp = (unsigned int)*pgid;
3535 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3536 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3537 SIVAL(pdata,2,own_grp);
3542 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3543 SIVAL(pdata,2,0xFFFFFFFF);
3544 SIVAL(pdata,6,0xFFFFFFFF);
3547 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3548 SIVAL(pdata,2,0xFFFFFFFF);
3549 SIVAL(pdata,6,0xFFFFFFFF);
3552 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3555 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3562 /****************************************************************************
3563 Store the FILE_UNIX_BASIC info.
3564 ****************************************************************************/
3566 static char *store_file_unix_basic(connection_struct *conn,
3569 const SMB_STRUCT_STAT *psbuf)
3571 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3572 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3574 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3577 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3580 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3581 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3582 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3585 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3589 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3593 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3596 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3600 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3604 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3607 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3611 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3618 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3619 * the chflags(2) (or equivalent) flags.
3621 * XXX: this really should be behind the VFS interface. To do this, we would
3622 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3623 * Each VFS module could then implement its own mapping as appropriate for the
3624 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3626 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3630 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3634 { UF_IMMUTABLE, EXT_IMMUTABLE },
3638 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3642 { UF_HIDDEN, EXT_HIDDEN },
3645 /* Do not remove. We need to guarantee that this array has at least one
3646 * entry to build on HP-UX.
3652 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3653 uint32 *smb_fflags, uint32 *smb_fmask)
3657 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3658 *smb_fmask |= info2_flags_map[i].smb_fflag;
3659 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3660 *smb_fflags |= info2_flags_map[i].smb_fflag;
3665 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3666 const uint32 smb_fflags,
3667 const uint32 smb_fmask,
3670 uint32 max_fmask = 0;
3673 *stat_fflags = psbuf->st_ex_flags;
3675 /* For each flags requested in smb_fmask, check the state of the
3676 * corresponding flag in smb_fflags and set or clear the matching
3680 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3681 max_fmask |= info2_flags_map[i].smb_fflag;
3682 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3683 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3684 *stat_fflags |= info2_flags_map[i].stat_fflag;
3686 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3691 /* If smb_fmask is asking to set any bits that are not supported by
3692 * our flag mappings, we should fail.
3694 if ((smb_fmask & max_fmask) != smb_fmask) {
3702 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3703 * of file flags and birth (create) time.
3705 static char *store_file_unix_basic_info2(connection_struct *conn,
3708 const SMB_STRUCT_STAT *psbuf)
3710 uint32 file_flags = 0;
3711 uint32 flags_mask = 0;
3713 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3715 /* Create (birth) time 64 bit */
3716 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3719 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3720 SIVAL(pdata, 0, file_flags); /* flags */
3721 SIVAL(pdata, 4, flags_mask); /* mask */
3727 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3728 const struct stream_struct *streams,
3730 unsigned int max_data_bytes,
3731 unsigned int *data_size)
3734 unsigned int ofs = 0;
3736 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3737 unsigned int next_offset;
3739 smb_ucs2_t *namebuf;
3741 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3742 streams[i].name, &namelen) ||
3745 return NT_STATUS_INVALID_PARAMETER;
3749 * name_buf is now null-terminated, we need to marshall as not
3755 SIVAL(data, ofs+4, namelen);
3756 SOFF_T(data, ofs+8, streams[i].size);
3757 SOFF_T(data, ofs+16, streams[i].alloc_size);
3758 memcpy(data+ofs+24, namebuf, namelen);
3759 TALLOC_FREE(namebuf);
3761 next_offset = ofs + 24 + namelen;
3763 if (i == num_streams-1) {
3764 SIVAL(data, ofs, 0);
3767 unsigned int align = ndr_align_size(next_offset, 8);
3769 memset(data+next_offset, 0, align);
3770 next_offset += align;
3772 SIVAL(data, ofs, next_offset - ofs);
3781 return NT_STATUS_OK;
3784 /****************************************************************************
3785 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3786 ****************************************************************************/
3788 static void call_trans2qpipeinfo(connection_struct *conn,
3789 struct smb_request *req,
3790 unsigned int tran_call,
3791 char **pparams, int total_params,
3792 char **ppdata, int total_data,
3793 unsigned int max_data_bytes)
3795 char *params = *pparams;
3796 char *pdata = *ppdata;
3797 unsigned int data_size = 0;
3798 unsigned int param_size = 2;
3803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3807 if (total_params < 4) {
3808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3812 fsp = file_fsp(req, SVAL(params,0));
3813 if (!fsp_is_np(fsp)) {
3814 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3818 info_level = SVAL(params,2);
3820 *pparams = (char *)SMB_REALLOC(*pparams,2);
3821 if (*pparams == NULL) {
3822 reply_nterror(req, NT_STATUS_NO_MEMORY);
3827 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3828 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3829 if (*ppdata == NULL ) {
3830 reply_nterror(req, NT_STATUS_NO_MEMORY);
3835 switch (info_level) {
3836 case SMB_FILE_STANDARD_INFORMATION:
3838 SOFF_T(pdata,0,4096LL);
3845 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3849 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3855 /****************************************************************************
3856 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3857 file name or file id).
3858 ****************************************************************************/
3860 static void call_trans2qfilepathinfo(connection_struct *conn,
3861 struct smb_request *req,
3862 unsigned int tran_call,
3863 char **pparams, int total_params,
3864 char **ppdata, int total_data,
3865 unsigned int max_data_bytes)
3867 char *params = *pparams;
3868 char *pdata = *ppdata;
3869 char *dstart, *dend;
3873 SMB_OFF_T file_size=0;
3874 uint64_t allocation_size=0;
3875 unsigned int data_size = 0;
3876 unsigned int param_size = 2;
3877 SMB_STRUCT_STAT sbuf;
3878 char *dos_fname = NULL;
3880 struct smb_filename *smb_fname = NULL;
3885 bool delete_pending = False;
3887 time_t create_time, mtime, atime;
3888 struct timespec create_time_ts, mtime_ts, atime_ts;
3889 struct timespec write_time_ts;
3890 files_struct *fsp = NULL;
3891 struct file_id fileid;
3892 struct ea_list *ea_list = NULL;
3893 char *lock_data = NULL;
3894 bool ms_dfs_link = false;
3895 TALLOC_CTX *ctx = talloc_tos();
3896 NTSTATUS status = NT_STATUS_OK;
3899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3903 ZERO_STRUCT(write_time_ts);
3905 if (tran_call == TRANSACT2_QFILEINFO) {
3906 if (total_params < 4) {
3907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3912 call_trans2qpipeinfo(conn, req, tran_call,
3913 pparams, total_params,
3919 fsp = file_fsp(req, SVAL(params,0));
3920 info_level = SVAL(params,2);
3922 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3924 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3925 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3929 /* Initial check for valid fsp ptr. */
3930 if (!check_fsp_open(conn, req, fsp)) {
3934 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3936 reply_nterror(req, NT_STATUS_NO_MEMORY);
3940 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
3942 if (!NT_STATUS_IS_OK(status)) {
3943 reply_nterror(req, status);
3947 if(fsp->fake_file_handle) {
3949 * This is actually for the QUOTA_FAKE_FILE --metze
3952 /* We know this name is ok, it's already passed the checks. */
3954 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3956 * This is actually a QFILEINFO on a directory
3957 * handle (returned from an NT SMB). NT5.0 seems
3958 * to do this call. JRA.
3961 if (INFO_LEVEL_IS_UNIX(info_level)) {
3962 /* Always do lstat for UNIX calls. */
3963 if (SMB_VFS_LSTAT(conn, smb_fname)) {
3964 DEBUG(3,("call_trans2qfilepathinfo: "
3965 "SMB_VFS_LSTAT of %s failed "
3967 smb_fname_str_dbg(smb_fname),
3969 reply_unixerror(req,ERRDOS,ERRbadpath);
3972 } else if (SMB_VFS_STAT(conn, smb_fname)) {
3973 DEBUG(3,("call_trans2qfilepathinfo: "
3974 "SMB_VFS_STAT of %s failed (%s)\n",
3975 smb_fname_str_dbg(smb_fname),
3977 reply_unixerror(req, ERRDOS, ERRbadpath);
3981 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
3982 get_file_infos(fileid, &delete_pending, &write_time_ts);
3985 * Original code - this is an open file.
3987 if (!check_fsp(conn, req, fsp)) {
3991 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
3992 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
3993 fsp->fnum, strerror(errno)));
3994 reply_unixerror(req, ERRDOS, ERRbadfid);
3997 pos = fsp->fh->position_information;
3998 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
3999 get_file_infos(fileid, &delete_pending, &write_time_ts);
4004 if (total_params < 7) {
4005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4009 info_level = SVAL(params,0);
4011 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4013 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4014 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4018 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
4020 STR_TERMINATE, &status);
4021 if (!NT_STATUS_IS_OK(status)) {
4022 reply_nterror(req, status);
4026 status = filename_convert(ctx,
4028 req->flags2 & FLAGS2_DFS_PATHNAMES,
4032 if (!NT_STATUS_IS_OK(status)) {
4033 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4034 reply_botherror(req,
4035 NT_STATUS_PATH_NOT_COVERED,
4036 ERRSRV, ERRbadpath);
4039 reply_nterror(req, status);
4043 /* If this is a stream, check if there is a delete_pending. */
4044 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4045 && is_ntfs_stream_smb_fname(smb_fname)) {
4046 struct smb_filename *smb_fname_base = NULL;
4048 /* Create an smb_filename with stream_name == NULL. */
4050 create_synthetic_smb_fname(talloc_tos(),
4051 smb_fname->base_name,
4054 if (!NT_STATUS_IS_OK(status)) {
4055 reply_nterror(req, status);
4059 if (INFO_LEVEL_IS_UNIX(info_level)) {
4060 /* Always do lstat for UNIX calls. */
4061 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4062 DEBUG(3,("call_trans2qfilepathinfo: "
4063 "SMB_VFS_LSTAT of %s failed "
4065 smb_fname_str_dbg(smb_fname_base),
4067 TALLOC_FREE(smb_fname_base);
4068 reply_unixerror(req,ERRDOS,ERRbadpath);
4072 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4073 DEBUG(3,("call_trans2qfilepathinfo: "
4074 "fileinfo of %s failed "
4076 smb_fname_str_dbg(smb_fname_base),
4078 TALLOC_FREE(smb_fname_base);
4079 reply_unixerror(req,ERRDOS,ERRbadpath);
4084 fileid = vfs_file_id_from_sbuf(conn,
4085 &smb_fname_base->st);
4086 TALLOC_FREE(smb_fname_base);
4087 get_file_infos(fileid, &delete_pending, NULL);
4088 if (delete_pending) {
4089 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4094 if (INFO_LEVEL_IS_UNIX(info_level)) {
4095 /* Always do lstat for UNIX calls. */
4096 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4097 DEBUG(3,("call_trans2qfilepathinfo: "
4098 "SMB_VFS_LSTAT of %s failed (%s)\n",
4099 smb_fname_str_dbg(smb_fname),
4101 reply_unixerror(req, ERRDOS, ERRbadpath);
4105 } else if (!VALID_STAT(smb_fname->st) &&
4106 SMB_VFS_STAT(conn, smb_fname) &&
4107 (info_level != SMB_INFO_IS_NAME_VALID)) {
4108 ms_dfs_link = check_msdfs_link(conn, fname,
4112 DEBUG(3,("call_trans2qfilepathinfo: "
4113 "SMB_VFS_STAT of %s failed (%s)\n",
4114 smb_fname_str_dbg(smb_fname),
4116 reply_unixerror(req, ERRDOS, ERRbadpath);
4121 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4122 get_file_infos(fileid, &delete_pending, &write_time_ts);
4123 if (delete_pending) {
4124 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4129 /* Set sbuf for use below. */
4130 sbuf = smb_fname->st;
4132 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4133 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4137 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4138 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4140 p = strrchr_m(fname,'/');
4147 mode = dos_mode_msdfs(conn,fname,&sbuf);
4149 mode = dos_mode(conn,fname,&sbuf);
4152 mode = FILE_ATTRIBUTE_NORMAL;
4154 nlink = sbuf.st_ex_nlink;
4156 if (nlink && (mode&aDIR)) {
4160 if ((nlink > 0) && delete_pending) {
4164 fullpathname = fname;
4166 file_size = get_file_size_stat(&sbuf);
4168 /* Pull out any data sent here before we realloc. */
4169 switch (info_level) {
4170 case SMB_INFO_QUERY_EAS_FROM_LIST:
4172 /* Pull any EA list from the data portion. */
4175 if (total_data < 4) {
4177 req, NT_STATUS_INVALID_PARAMETER);
4180 ea_size = IVAL(pdata,0);
4182 if (total_data > 0 && ea_size != total_data) {
4183 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4184 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4186 req, NT_STATUS_INVALID_PARAMETER);
4190 if (!lp_ea_support(SNUM(conn))) {
4191 reply_doserror(req, ERRDOS,
4192 ERReasnotsupported);
4196 /* Pull out the list of names. */
4197 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4200 req, NT_STATUS_INVALID_PARAMETER);
4206 case SMB_QUERY_POSIX_LOCK:
4208 if (fsp == NULL || fsp->fh->fd == -1) {
4209 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4213 if (total_data != POSIX_LOCK_DATA_SIZE) {
4215 req, NT_STATUS_INVALID_PARAMETER);
4219 /* Copy the lock range data. */
4220 lock_data = (char *)TALLOC_MEMDUP(
4221 ctx, pdata, total_data);
4223 reply_nterror(req, NT_STATUS_NO_MEMORY);
4231 *pparams = (char *)SMB_REALLOC(*pparams,2);
4232 if (*pparams == NULL) {
4233 reply_nterror(req, NT_STATUS_NO_MEMORY);
4238 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4239 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4240 if (*ppdata == NULL ) {
4241 reply_nterror(req, NT_STATUS_NO_MEMORY);
4246 dend = dstart + data_size - 1;
4248 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4251 /* Do we have this path open ? */
4253 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4254 fsp1 = file_find_di_first(fileid);
4255 if (fsp1 && fsp1->initial_allocation_size) {
4256 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4260 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4261 update_stat_ex_mtime(&sbuf, write_time_ts);
4264 create_time_ts = sbuf.st_ex_btime;
4265 mtime_ts = sbuf.st_ex_mtime;
4266 atime_ts = sbuf.st_ex_atime;
4268 if (lp_dos_filetime_resolution(SNUM(conn))) {
4269 dos_filetime_timespec(&create_time_ts);
4270 dos_filetime_timespec(&mtime_ts);
4271 dos_filetime_timespec(&atime_ts);
4274 create_time = convert_timespec_to_time_t(create_time_ts);
4275 mtime = convert_timespec_to_time_t(mtime_ts);
4276 atime = convert_timespec_to_time_t(atime_ts);
4278 /* NT expects the name to be in an exact form of the *full*
4279 filename. See the trans2 torture test */
4280 if (ISDOT(base_name)) {
4281 dos_fname = talloc_strdup(ctx, "\\");
4283 reply_nterror(req, NT_STATUS_NO_MEMORY);
4287 dos_fname = talloc_asprintf(ctx,
4291 reply_nterror(req, NT_STATUS_NO_MEMORY);
4294 string_replace(dos_fname, '/', '\\');
4297 switch (info_level) {
4298 case SMB_INFO_STANDARD:
4299 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4301 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4302 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4303 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4304 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4305 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4306 SSVAL(pdata,l1_attrFile,mode);
4309 case SMB_INFO_QUERY_EA_SIZE:
4311 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4312 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4314 srv_put_dos_date2(pdata,0,create_time);
4315 srv_put_dos_date2(pdata,4,atime);
4316 srv_put_dos_date2(pdata,8,mtime); /* write time */
4317 SIVAL(pdata,12,(uint32)file_size);
4318 SIVAL(pdata,16,(uint32)allocation_size);
4319 SSVAL(pdata,20,mode);
4320 SIVAL(pdata,22,ea_size);
4324 case SMB_INFO_IS_NAME_VALID:
4325 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4326 if (tran_call == TRANSACT2_QFILEINFO) {
4327 /* os/2 needs this ? really ?*/
4328 reply_doserror(req, ERRDOS, ERRbadfunc);
4335 case SMB_INFO_QUERY_EAS_FROM_LIST:
4337 size_t total_ea_len = 0;
4338 struct ea_list *ea_file_list = NULL;
4340 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4342 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4343 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4345 if (!ea_list || (total_ea_len > data_size)) {
4347 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4351 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4355 case SMB_INFO_QUERY_ALL_EAS:
4357 /* We have data_size bytes to put EA's into. */
4358 size_t total_ea_len = 0;
4360 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4362 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4363 if (!ea_list || (total_ea_len > data_size)) {
4365 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4369 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4373 case SMB_FILE_BASIC_INFORMATION:
4374 case SMB_QUERY_FILE_BASIC_INFO:
4376 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4377 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4378 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4380 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4384 put_long_date_timespec(pdata,create_time_ts);
4385 put_long_date_timespec(pdata+8,atime_ts);
4386 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4387 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4388 SIVAL(pdata,32,mode);
4390 DEBUG(5,("SMB_QFBI - "));
4391 DEBUG(5,("create: %s ", ctime(&create_time)));
4392 DEBUG(5,("access: %s ", ctime(&atime)));
4393 DEBUG(5,("write: %s ", ctime(&mtime)));
4394 DEBUG(5,("change: %s ", ctime(&mtime)));
4395 DEBUG(5,("mode: %x\n", mode));
4398 case SMB_FILE_STANDARD_INFORMATION:
4399 case SMB_QUERY_FILE_STANDARD_INFO:
4401 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4403 SOFF_T(pdata,0,allocation_size);
4404 SOFF_T(pdata,8,file_size);
4405 SIVAL(pdata,16,nlink);
4406 SCVAL(pdata,20,delete_pending?1:0);
4407 SCVAL(pdata,21,(mode&aDIR)?1:0);
4408 SSVAL(pdata,22,0); /* Padding. */
4411 case SMB_FILE_EA_INFORMATION:
4412 case SMB_QUERY_FILE_EA_INFO:
4414 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4415 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4417 SIVAL(pdata,0,ea_size);
4421 /* Get the 8.3 name - used if NT SMB was negotiated. */
4422 case SMB_QUERY_FILE_ALT_NAME_INFO:
4423 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4425 char mangled_name[13];
4426 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4427 if (!name_to_8_3(base_name,mangled_name,
4428 True,conn->params)) {
4431 NT_STATUS_NO_MEMORY);
4433 len = srvstr_push(dstart, req->flags2,
4434 pdata+4, mangled_name,
4435 PTR_DIFF(dend, pdata+4),
4437 data_size = 4 + len;
4442 case SMB_QUERY_FILE_NAME_INFO:
4444 this must be *exactly* right for ACLs on mapped drives to work
4446 len = srvstr_push(dstart, req->flags2,
4448 PTR_DIFF(dend, pdata+4),
4450 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4451 data_size = 4 + len;
4455 case SMB_FILE_ALLOCATION_INFORMATION:
4456 case SMB_QUERY_FILE_ALLOCATION_INFO:
4457 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4459 SOFF_T(pdata,0,allocation_size);
4462 case SMB_FILE_END_OF_FILE_INFORMATION:
4463 case SMB_QUERY_FILE_END_OF_FILEINFO:
4464 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4466 SOFF_T(pdata,0,file_size);
4469 case SMB_QUERY_FILE_ALL_INFO:
4470 case SMB_FILE_ALL_INFORMATION:
4472 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4473 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4474 put_long_date_timespec(pdata,create_time_ts);
4475 put_long_date_timespec(pdata+8,atime_ts);
4476 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4477 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4478 SIVAL(pdata,32,mode);
4479 SIVAL(pdata,36,0); /* padding. */
4481 SOFF_T(pdata,0,allocation_size);
4482 SOFF_T(pdata,8,file_size);
4483 SIVAL(pdata,16,nlink);
4484 SCVAL(pdata,20,delete_pending);
4485 SCVAL(pdata,21,(mode&aDIR)?1:0);
4488 SIVAL(pdata,0,ea_size);
4489 pdata += 4; /* EA info */
4490 len = srvstr_push(dstart, req->flags2,
4492 PTR_DIFF(dend, pdata+4),
4496 data_size = PTR_DIFF(pdata,(*ppdata));
4499 case SMB_FILE_INTERNAL_INFORMATION:
4500 /* This should be an index number - looks like
4503 I think this causes us to fail the IFSKIT
4504 BasicFileInformationTest. -tpot */
4506 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4507 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4508 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4512 case SMB_FILE_ACCESS_INFORMATION:
4513 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4515 SIVAL(pdata,0,fsp->access_mask);
4517 /* GENERIC_EXECUTE mapping from Windows */
4518 SIVAL(pdata,0,0x12019F);
4523 case SMB_FILE_NAME_INFORMATION:
4524 /* Pathname with leading '\'. */
4527 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4528 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4529 SIVAL(pdata,0,byte_len);
4530 data_size = 4 + byte_len;
4534 case SMB_FILE_DISPOSITION_INFORMATION:
4535 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4537 SCVAL(pdata,0,delete_pending);
4540 case SMB_FILE_POSITION_INFORMATION:
4541 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4543 SOFF_T(pdata,0,pos);
4546 case SMB_FILE_MODE_INFORMATION:
4547 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4548 SIVAL(pdata,0,mode);
4552 case SMB_FILE_ALIGNMENT_INFORMATION:
4553 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4554 SIVAL(pdata,0,0); /* No alignment needed. */
4559 * NT4 server just returns "invalid query" to this - if we try
4560 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4563 /* The first statement above is false - verified using Thursby
4564 * client against NT4 -- gcolley.
4566 case SMB_QUERY_FILE_STREAM_INFO:
4567 case SMB_FILE_STREAM_INFORMATION: {
4568 unsigned int num_streams;
4569 struct stream_struct *streams;
4571 DEBUG(10,("call_trans2qfilepathinfo: "
4572 "SMB_FILE_STREAM_INFORMATION\n"));
4574 status = SMB_VFS_STREAMINFO(
4575 conn, fsp, fname, talloc_tos(),
4576 &num_streams, &streams);
4578 if (!NT_STATUS_IS_OK(status)) {
4579 DEBUG(10, ("could not get stream info: %s\n",
4580 nt_errstr(status)));
4581 reply_nterror(req, status);
4585 status = marshall_stream_info(num_streams, streams,
4586 pdata, max_data_bytes,
4589 if (!NT_STATUS_IS_OK(status)) {
4590 DEBUG(10, ("marshall_stream_info failed: %s\n",
4591 nt_errstr(status)));
4592 reply_nterror(req, status);
4596 TALLOC_FREE(streams);
4600 case SMB_QUERY_COMPRESSION_INFO:
4601 case SMB_FILE_COMPRESSION_INFORMATION:
4602 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4603 SOFF_T(pdata,0,file_size);
4604 SIVAL(pdata,8,0); /* ??? */
4605 SIVAL(pdata,12,0); /* ??? */
4609 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4610 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4611 put_long_date_timespec(pdata,create_time_ts);
4612 put_long_date_timespec(pdata+8,atime_ts);
4613 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4614 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4615 SOFF_T(pdata,32,allocation_size);
4616 SOFF_T(pdata,40,file_size);
4617 SIVAL(pdata,48,mode);
4618 SIVAL(pdata,52,0); /* ??? */
4622 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4623 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4624 SIVAL(pdata,0,mode);
4630 * CIFS UNIX Extensions.
4633 case SMB_QUERY_FILE_UNIX_BASIC:
4635 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4636 data_size = PTR_DIFF(pdata,(*ppdata));
4640 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4642 for (i=0; i<100; i++)
4643 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4649 case SMB_QUERY_FILE_UNIX_INFO2:
4651 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4652 data_size = PTR_DIFF(pdata,(*ppdata));
4656 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4658 for (i=0; i<100; i++)
4659 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4665 case SMB_QUERY_FILE_UNIX_LINK:
4667 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4670 reply_nterror(req, NT_STATUS_NO_MEMORY);
4674 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4676 if(!S_ISLNK(sbuf.st_ex_mode)) {
4677 reply_unixerror(req, ERRSRV,
4682 reply_unixerror(req, ERRDOS, ERRbadlink);
4685 len = SMB_VFS_READLINK(conn,fullpathname,
4688 reply_unixerror(req, ERRDOS,
4693 len = srvstr_push(dstart, req->flags2,
4695 PTR_DIFF(dend, pdata),
4698 data_size = PTR_DIFF(pdata,(*ppdata));
4703 #if defined(HAVE_POSIX_ACLS)
4704 case SMB_QUERY_POSIX_ACL:
4706 SMB_ACL_T file_acl = NULL;
4707 SMB_ACL_T def_acl = NULL;
4708 uint16 num_file_acls = 0;
4709 uint16 num_def_acls = 0;
4711 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4712 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4714 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4717 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4718 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4722 NT_STATUS_NOT_IMPLEMENTED);
4726 if (S_ISDIR(sbuf.st_ex_mode)) {
4727 if (fsp && fsp->is_directory) {
4728 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4730 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4732 def_acl = free_empty_sys_acl(conn, def_acl);
4735 num_file_acls = count_acl_entries(conn, file_acl);
4736 num_def_acls = count_acl_entries(conn, def_acl);
4738 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4739 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4741 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4742 SMB_POSIX_ACL_HEADER_SIZE) ));
4744 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4747 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4751 NT_STATUS_BUFFER_TOO_SMALL);
4755 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4756 SSVAL(pdata,2,num_file_acls);
4757 SSVAL(pdata,4,num_def_acls);
4758 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4760 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4763 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4766 req, NT_STATUS_INTERNAL_ERROR);
4769 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4771 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4774 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4778 NT_STATUS_INTERNAL_ERROR);
4783 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4786 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4788 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4794 case SMB_QUERY_POSIX_LOCK:
4799 enum brl_type lock_type;
4801 if (total_data != POSIX_LOCK_DATA_SIZE) {
4803 req, NT_STATUS_INVALID_PARAMETER);
4807 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4808 case POSIX_LOCK_TYPE_READ:
4809 lock_type = READ_LOCK;
4811 case POSIX_LOCK_TYPE_WRITE:
4812 lock_type = WRITE_LOCK;
4814 case POSIX_LOCK_TYPE_UNLOCK:
4816 /* There's no point in asking for an unlock... */
4819 NT_STATUS_INVALID_PARAMETER);
4823 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4824 #if defined(HAVE_LONGLONG)
4825 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4826 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4827 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4828 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4829 #else /* HAVE_LONGLONG */
4830 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4831 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4832 #endif /* HAVE_LONGLONG */
4834 status = query_lock(fsp,
4841 if (ERROR_WAS_LOCK_DENIED(status)) {
4842 /* Here we need to report who has it locked... */
4843 data_size = POSIX_LOCK_DATA_SIZE;
4845 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4846 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4847 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4848 #if defined(HAVE_LONGLONG)
4849 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4850 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4851 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4852 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4853 #else /* HAVE_LONGLONG */
4854 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4855 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4856 #endif /* HAVE_LONGLONG */
4858 } else if (NT_STATUS_IS_OK(status)) {
4859 /* For success we just return a copy of what we sent
4860 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4861 data_size = POSIX_LOCK_DATA_SIZE;
4862 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4863 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4865 reply_nterror(req, status);
4872 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4876 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4882 /****************************************************************************
4883 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4885 ****************************************************************************/
4887 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4888 connection_struct *conn,
4889 const struct smb_filename *smb_fname_old,
4890 const struct smb_filename *smb_fname_new)
4892 char *oldname = NULL;
4893 char *newname = NULL;
4894 NTSTATUS status = NT_STATUS_OK;
4896 /* source must already exist. */
4897 if (!VALID_STAT(smb_fname_old->st)) {
4898 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4901 /* Disallow if newname already exists. */
4902 if (VALID_STAT(smb_fname_new->st)) {
4903 return NT_STATUS_OBJECT_NAME_COLLISION;
4906 /* No links from a directory. */
4907 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
4908 return NT_STATUS_FILE_IS_A_DIRECTORY;
4911 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
4912 if (!NT_STATUS_IS_OK(status)) {
4915 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
4916 if (!NT_STATUS_IS_OK(status)) {
4920 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4922 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4923 status = map_nt_error_from_unix(errno);
4924 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4925 nt_errstr(status), newname, oldname));
4928 TALLOC_FREE(newname);
4929 TALLOC_FREE(oldname);
4933 /****************************************************************************
4934 Deal with setting the time from any of the setfilepathinfo functions.
4935 ****************************************************************************/
4937 NTSTATUS smb_set_file_time(connection_struct *conn,
4939 const struct smb_filename *smb_fname,
4940 struct smb_file_time *ft,
4941 bool setting_write_time)
4943 struct smb_filename *smb_fname_base = NULL;
4945 FILE_NOTIFY_CHANGE_LAST_ACCESS
4946 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4949 if (!VALID_STAT(smb_fname->st)) {
4950 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4953 /* get some defaults (no modifications) if any info is zero or -1. */
4954 if (null_timespec(ft->atime)) {
4955 ft->atime= smb_fname->st.st_ex_atime;
4956 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4959 if (null_timespec(ft->mtime)) {
4960 ft->mtime = smb_fname->st.st_ex_mtime;
4961 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4964 if (!setting_write_time) {
4965 /* ft->mtime comes from change time, not write time. */
4966 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4969 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4970 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4971 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4972 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4973 if (!null_timespec(ft->create_time)) {
4974 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4975 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4979 * Try and set the times of this file if
4980 * they are different from the current values.
4984 struct timespec mts = smb_fname->st.st_ex_mtime;
4985 struct timespec ats = smb_fname->st.st_ex_atime;
4986 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4987 (timespec_compare(&ft->mtime, &mts) == 0)) {
4988 return NT_STATUS_OK;
4992 if (setting_write_time) {
4994 * This was a Windows setfileinfo on an open file.
4995 * NT does this a lot. We also need to
4996 * set the time here, as it can be read by
4997 * FindFirst/FindNext and with the patch for bug #2045
4998 * in smbd/fileio.c it ensures that this timestamp is
4999 * kept sticky even after a write. We save the request
5000 * away and will set it on file close and after a write. JRA.
5003 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5004 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5007 if (fsp->base_fsp) {
5008 set_sticky_write_time_fsp(fsp->base_fsp,
5011 set_sticky_write_time_fsp(fsp, ft->mtime);
5014 set_sticky_write_time_path(
5015 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5020 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5022 /* Always call ntimes on the base, even if a stream was passed in. */
5023 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5024 NULL, &smb_fname->st,
5026 if (!NT_STATUS_IS_OK(status)) {
5030 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5031 TALLOC_FREE(smb_fname_base);
5032 return map_nt_error_from_unix(errno);
5034 TALLOC_FREE(smb_fname_base);
5036 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5037 smb_fname->base_name);
5038 return NT_STATUS_OK;
5041 /****************************************************************************
5042 Deal with setting the dosmode from any of the setfilepathinfo functions.
5043 ****************************************************************************/
5045 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5046 const struct smb_filename *smb_fname,
5049 struct smb_filename *smb_fname_base = NULL;
5052 if (!VALID_STAT(smb_fname->st)) {
5053 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5056 /* Always operate on the base_name, even if a stream was passed in. */
5057 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5058 NULL, &smb_fname->st,
5060 if (!NT_STATUS_IS_OK(status)) {
5065 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5072 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5074 /* check the mode isn't different, before changing it */
5075 if ((dosmode != 0) && (dosmode != dos_mode(conn,
5076 smb_fname_base->base_name,
5077 &smb_fname_base->st))) {
5078 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5079 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5080 (unsigned int)dosmode));
5082 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5084 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5086 smb_fname_str_dbg(smb_fname_base),
5088 status = map_nt_error_from_unix(errno);
5092 status = NT_STATUS_OK;
5094 TALLOC_FREE(smb_fname_base);
5098 /****************************************************************************
5099 Deal with setting the size from any of the setfilepathinfo functions.
5100 ****************************************************************************/
5102 static NTSTATUS smb_set_file_size(connection_struct *conn,
5103 struct smb_request *req,
5105 const struct smb_filename *smb_fname,
5106 const SMB_STRUCT_STAT *psbuf,
5109 NTSTATUS status = NT_STATUS_OK;
5110 struct smb_filename *smb_fname_tmp = NULL;
5111 files_struct *new_fsp = NULL;
5113 if (!VALID_STAT(*psbuf)) {
5114 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5117 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5119 if (size == get_file_size_stat(psbuf)) {
5120 return NT_STATUS_OK;
5123 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5124 smb_fname_str_dbg(smb_fname), (double)size));
5126 if (fsp && fsp->fh->fd != -1) {
5127 /* Handle based call. */
5128 if (vfs_set_filelen(fsp, size) == -1) {
5129 return map_nt_error_from_unix(errno);
5131 trigger_write_time_update_immediate(fsp);
5132 return NT_STATUS_OK;
5135 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5136 if (!NT_STATUS_IS_OK(status)) {
5140 smb_fname_tmp->st = *psbuf;
5142 status = SMB_VFS_CREATE_FILE(
5145 0, /* root_dir_fid */
5146 smb_fname_tmp, /* fname */
5147 FILE_WRITE_ATTRIBUTES, /* access_mask */
5148 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5150 FILE_OPEN, /* create_disposition*/
5151 0, /* create_options */
5152 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5153 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5154 0, /* allocation_size */
5157 &new_fsp, /* result */
5160 TALLOC_FREE(smb_fname_tmp);
5162 if (!NT_STATUS_IS_OK(status)) {
5163 /* NB. We check for open_was_deferred in the caller. */
5167 if (vfs_set_filelen(new_fsp, size) == -1) {
5168 status = map_nt_error_from_unix(errno);
5169 close_file(req, new_fsp,NORMAL_CLOSE);
5173 trigger_write_time_update_immediate(new_fsp);
5174 close_file(req, new_fsp,NORMAL_CLOSE);
5175 return NT_STATUS_OK;
5178 /****************************************************************************
5179 Deal with SMB_INFO_SET_EA.
5180 ****************************************************************************/
5182 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5186 const struct smb_filename *smb_fname)
5188 struct ea_list *ea_list = NULL;
5189 TALLOC_CTX *ctx = NULL;
5190 NTSTATUS status = NT_STATUS_OK;
5192 if (total_data < 10) {
5194 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5195 length. They seem to have no effect. Bug #3212. JRA */
5197 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5198 /* We're done. We only get EA info in this call. */
5199 return NT_STATUS_OK;
5202 return NT_STATUS_INVALID_PARAMETER;
5205 if (IVAL(pdata,0) > total_data) {
5206 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5207 IVAL(pdata,0), (unsigned int)total_data));
5208 return NT_STATUS_INVALID_PARAMETER;
5212 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5214 return NT_STATUS_INVALID_PARAMETER;
5216 status = set_ea(conn, fsp, smb_fname, ea_list);
5221 /****************************************************************************
5222 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5223 ****************************************************************************/
5225 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5230 SMB_STRUCT_STAT *psbuf)
5232 NTSTATUS status = NT_STATUS_OK;
5233 bool delete_on_close;
5236 if (total_data < 1) {
5237 return NT_STATUS_INVALID_PARAMETER;
5241 return NT_STATUS_INVALID_HANDLE;
5244 delete_on_close = (CVAL(pdata,0) ? True : False);
5245 dosmode = dos_mode(conn, fname, psbuf);
5247 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5248 "delete_on_close = %u\n",
5250 (unsigned int)dosmode,
5251 (unsigned int)delete_on_close ));
5253 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5255 if (!NT_STATUS_IS_OK(status)) {
5259 /* The set is across all open files on this dev/inode pair. */
5260 if (!set_delete_on_close(fsp, delete_on_close,
5261 &conn->server_info->utok)) {
5262 return NT_STATUS_ACCESS_DENIED;
5264 return NT_STATUS_OK;
5267 /****************************************************************************
5268 Deal with SMB_FILE_POSITION_INFORMATION.
5269 ****************************************************************************/
5271 static NTSTATUS smb_file_position_information(connection_struct *conn,
5276 uint64_t position_information;
5278 if (total_data < 8) {
5279 return NT_STATUS_INVALID_PARAMETER;
5283 /* Ignore on pathname based set. */
5284 return NT_STATUS_OK;
5287 position_information = (uint64_t)IVAL(pdata,0);
5288 #ifdef LARGE_SMB_OFF_T
5289 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5290 #else /* LARGE_SMB_OFF_T */
5291 if (IVAL(pdata,4) != 0) {
5292 /* more than 32 bits? */
5293 return NT_STATUS_INVALID_PARAMETER;
5295 #endif /* LARGE_SMB_OFF_T */
5297 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5298 fsp->fsp_name, (double)position_information ));
5299 fsp->fh->position_information = position_information;
5300 return NT_STATUS_OK;
5303 /****************************************************************************
5304 Deal with SMB_FILE_MODE_INFORMATION.
5305 ****************************************************************************/
5307 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5313 if (total_data < 4) {
5314 return NT_STATUS_INVALID_PARAMETER;
5316 mode = IVAL(pdata,0);
5317 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5318 return NT_STATUS_INVALID_PARAMETER;
5320 return NT_STATUS_OK;
5323 /****************************************************************************
5324 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5325 ****************************************************************************/
5327 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5328 struct smb_request *req,
5333 char *link_target = NULL;
5334 const char *newname = fname;
5335 NTSTATUS status = NT_STATUS_OK;
5336 TALLOC_CTX *ctx = talloc_tos();
5338 /* Set a symbolic link. */
5339 /* Don't allow this if follow links is false. */
5341 if (total_data == 0) {
5342 return NT_STATUS_INVALID_PARAMETER;
5345 if (!lp_symlinks(SNUM(conn))) {
5346 return NT_STATUS_ACCESS_DENIED;
5349 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5350 total_data, STR_TERMINATE);
5353 return NT_STATUS_INVALID_PARAMETER;
5356 /* !widelinks forces the target path to be within the share. */
5357 /* This means we can interpret the target as a pathname. */
5358 if (!lp_widelinks(SNUM(conn))) {
5359 char *rel_name = NULL;
5360 char *last_dirp = NULL;
5362 if (*link_target == '/') {
5363 /* No absolute paths allowed. */
5364 return NT_STATUS_ACCESS_DENIED;
5366 rel_name = talloc_strdup(ctx,newname);
5368 return NT_STATUS_NO_MEMORY;
5370 last_dirp = strrchr_m(rel_name, '/');
5372 last_dirp[1] = '\0';
5374 rel_name = talloc_strdup(ctx,"./");
5376 return NT_STATUS_NO_MEMORY;
5379 rel_name = talloc_asprintf_append(rel_name,
5383 return NT_STATUS_NO_MEMORY;
5386 status = check_name(conn, rel_name);
5387 if (!NT_STATUS_IS_OK(status)) {
5392 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5393 newname, link_target ));
5395 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5396 return map_nt_error_from_unix(errno);
5399 return NT_STATUS_OK;
5402 /****************************************************************************
5403 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5404 ****************************************************************************/
5406 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5407 struct smb_request *req,
5408 const char *pdata, int total_data,
5409 const struct smb_filename *smb_fname_new)
5411 char *oldname = NULL;
5412 struct smb_filename *smb_fname_old = NULL;
5413 TALLOC_CTX *ctx = talloc_tos();
5414 NTSTATUS status = NT_STATUS_OK;
5416 /* Set a hard link. */
5417 if (total_data == 0) {
5418 return NT_STATUS_INVALID_PARAMETER;
5421 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5422 total_data, STR_TERMINATE, &status);
5423 if (!NT_STATUS_IS_OK(status)) {
5427 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5428 smb_fname_str_dbg(smb_fname_new), oldname));
5430 status = filename_convert(ctx,
5432 req->flags2 & FLAGS2_DFS_PATHNAMES,
5436 if (!NT_STATUS_IS_OK(status)) {
5440 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5443 /****************************************************************************
5444 Deal with SMB_FILE_RENAME_INFORMATION.
5445 ****************************************************************************/
5447 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5448 struct smb_request *req,
5457 char *newname = NULL;
5458 char *base_name = NULL;
5459 struct smb_filename *smb_fname = NULL;
5460 bool dest_has_wcard = False;
5461 NTSTATUS status = NT_STATUS_OK;
5463 TALLOC_CTX *ctx = talloc_tos();
5465 if (total_data < 13) {
5466 return NT_STATUS_INVALID_PARAMETER;
5469 overwrite = (CVAL(pdata,0) ? True : False);
5470 root_fid = IVAL(pdata,4);
5471 len = IVAL(pdata,8);
5473 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5474 return NT_STATUS_INVALID_PARAMETER;
5477 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5480 if (!NT_STATUS_IS_OK(status)) {
5484 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5487 status = resolve_dfspath_wcard(ctx, conn,
5488 req->flags2 & FLAGS2_DFS_PATHNAMES,
5492 if (!NT_STATUS_IS_OK(status)) {
5496 /* Check the new name has no '/' characters. */
5497 if (strchr_m(newname, '/')) {
5498 return NT_STATUS_NOT_SUPPORTED;
5501 if (fsp && fsp->base_fsp) {
5502 /* newname must be a stream name. */
5503 if (newname[0] != ':') {
5504 return NT_STATUS_NOT_SUPPORTED;
5507 /* Create an smb_fname to call rename_internals_fsp() with. */
5508 status = create_synthetic_smb_fname(talloc_tos(),
5509 fsp->base_fsp->fsp_name,
5510 newname, NULL, &smb_fname);
5511 if (!NT_STATUS_IS_OK(status)) {
5516 * Set the original last component, since
5517 * rename_internals_fsp() requires it.
5519 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5520 if (smb_fname->original_lcomp == NULL) {
5521 status = NT_STATUS_NO_MEMORY;
5525 /* Create a char * to call rename_internals() with. */
5526 base_name = talloc_asprintf(ctx, "%s%s",
5527 fsp->base_fsp->fsp_name,
5530 status = NT_STATUS_NO_MEMORY;
5534 /* newname must *not* be a stream name. */
5535 if (is_ntfs_stream_name(newname)) {
5536 return NT_STATUS_NOT_SUPPORTED;
5539 /* Create the base directory. */
5540 base_name = talloc_strdup(ctx, fname);
5542 return NT_STATUS_NO_MEMORY;
5544 p = strrchr_m(base_name, '/');
5548 base_name = talloc_strdup(ctx, "./");
5550 return NT_STATUS_NO_MEMORY;
5553 /* Append the new name. */
5554 base_name = talloc_asprintf_append(base_name,
5558 return NT_STATUS_NO_MEMORY;
5561 status = unix_convert(ctx, conn, base_name, &smb_fname,
5564 /* If an error we expect this to be
5565 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5567 if (!NT_STATUS_IS_OK(status)) {
5568 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5572 /* Create an smb_fname to call rename_internals_fsp() */
5573 status = create_synthetic_smb_fname(talloc_tos(),
5576 if (!NT_STATUS_IS_OK(status)) {
5584 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5585 fsp->fnum, fsp->fsp_name, base_name ));
5586 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5589 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5590 fname, base_name ));
5591 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5592 overwrite, False, dest_has_wcard,
5593 FILE_WRITE_ATTRIBUTES);
5596 TALLOC_FREE(smb_fname);
5600 /****************************************************************************
5601 Deal with SMB_SET_POSIX_ACL.
5602 ****************************************************************************/
5604 #if defined(HAVE_POSIX_ACLS)
5605 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5610 SMB_STRUCT_STAT *psbuf)
5612 uint16 posix_acl_version;
5613 uint16 num_file_acls;
5614 uint16 num_def_acls;
5615 bool valid_file_acls = True;
5616 bool valid_def_acls = True;
5618 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5619 return NT_STATUS_INVALID_PARAMETER;
5621 posix_acl_version = SVAL(pdata,0);
5622 num_file_acls = SVAL(pdata,2);
5623 num_def_acls = SVAL(pdata,4);
5625 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5626 valid_file_acls = False;
5630 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5631 valid_def_acls = False;
5635 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5636 return NT_STATUS_INVALID_PARAMETER;
5639 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5640 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5641 return NT_STATUS_INVALID_PARAMETER;
5644 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5645 fname ? fname : fsp->fsp_name,
5646 (unsigned int)num_file_acls,
5647 (unsigned int)num_def_acls));
5649 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5650 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5651 return map_nt_error_from_unix(errno);
5654 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5655 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5656 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5657 return map_nt_error_from_unix(errno);
5659 return NT_STATUS_OK;
5663 /****************************************************************************
5664 Deal with SMB_SET_POSIX_LOCK.
5665 ****************************************************************************/
5667 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5668 struct smb_request *req,
5676 bool blocking_lock = False;
5677 enum brl_type lock_type;
5679 NTSTATUS status = NT_STATUS_OK;
5681 if (fsp == NULL || fsp->fh->fd == -1) {
5682 return NT_STATUS_INVALID_HANDLE;
5685 if (total_data != POSIX_LOCK_DATA_SIZE) {
5686 return NT_STATUS_INVALID_PARAMETER;
5689 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5690 case POSIX_LOCK_TYPE_READ:
5691 lock_type = READ_LOCK;
5693 case POSIX_LOCK_TYPE_WRITE:
5694 /* Return the right POSIX-mappable error code for files opened read-only. */
5695 if (!fsp->can_write) {
5696 return NT_STATUS_INVALID_HANDLE;
5698 lock_type = WRITE_LOCK;
5700 case POSIX_LOCK_TYPE_UNLOCK:
5701 lock_type = UNLOCK_LOCK;
5704 return NT_STATUS_INVALID_PARAMETER;
5707 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5708 blocking_lock = False;
5709 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5710 blocking_lock = True;
5712 return NT_STATUS_INVALID_PARAMETER;
5715 if (!lp_blocking_locks(SNUM(conn))) {
5716 blocking_lock = False;
5719 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5720 #if defined(HAVE_LONGLONG)
5721 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5722 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5723 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5724 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5725 #else /* HAVE_LONGLONG */
5726 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5727 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5728 #endif /* HAVE_LONGLONG */
5730 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5731 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5733 (unsigned int)lock_type,
5734 (unsigned int)lock_pid,
5738 if (lock_type == UNLOCK_LOCK) {
5739 status = do_unlock(smbd_messaging_context(),
5746 uint32 block_smbpid;
5748 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5760 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5762 * A blocking lock was requested. Package up
5763 * this smb into a queued request and push it
5764 * onto the blocking lock queue.
5766 if(push_blocking_lock_request(br_lck,
5769 -1, /* infinite timeout. */
5777 TALLOC_FREE(br_lck);
5781 TALLOC_FREE(br_lck);
5787 /****************************************************************************
5788 Deal with SMB_INFO_STANDARD.
5789 ****************************************************************************/
5791 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5795 const struct smb_filename *smb_fname)
5797 struct smb_file_time ft;
5800 if (total_data < 12) {
5801 return NT_STATUS_INVALID_PARAMETER;
5805 ft.create_time = interpret_long_date(pdata);
5808 ft.atime = interpret_long_date(pdata + 8);
5811 ft.mtime = interpret_long_date(pdata + 16);
5813 DEBUG(10,("smb_set_info_standard: file %s\n",
5814 smb_fname_str_dbg(smb_fname)));
5816 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5819 /****************************************************************************
5820 Deal with SMB_SET_FILE_BASIC_INFO.
5821 ****************************************************************************/
5823 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5827 const struct smb_filename *smb_fname)
5829 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5830 struct timespec write_time;
5831 struct timespec changed_time;
5832 struct smb_file_time ft;
5834 NTSTATUS status = NT_STATUS_OK;
5835 bool setting_write_time = true;
5839 if (total_data < 36) {
5840 return NT_STATUS_INVALID_PARAMETER;
5843 /* Set the attributes */
5844 dosmode = IVAL(pdata,32);
5845 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
5846 if (!NT_STATUS_IS_OK(status)) {
5851 ft.atime = interpret_long_date(pdata+8);
5853 write_time = interpret_long_date(pdata+16);
5854 changed_time = interpret_long_date(pdata+24);
5857 ft.mtime = timespec_min(&write_time, &changed_time);
5860 ft.create_time = interpret_long_date(pdata);
5862 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5863 !null_timespec(write_time)) {
5864 ft.mtime = write_time;
5867 /* Prefer a defined time to an undefined one. */
5868 if (null_timespec(ft.mtime)) {
5869 if (null_timespec(write_time)) {
5870 ft.mtime = changed_time;
5871 setting_write_time = false;
5873 ft.mtime = write_time;
5877 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
5878 smb_fname_str_dbg(smb_fname)));
5880 return smb_set_file_time(conn, fsp, smb_fname, &ft,
5881 setting_write_time);
5884 /****************************************************************************
5885 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5886 ****************************************************************************/
5888 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5889 struct smb_request *req,
5894 SMB_STRUCT_STAT *psbuf)
5896 struct smb_filename *smb_fname = NULL;
5897 uint64_t allocation_size = 0;
5898 NTSTATUS status = NT_STATUS_OK;
5899 files_struct *new_fsp = NULL;
5901 if (!VALID_STAT(*psbuf)) {
5902 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5905 if (total_data < 8) {
5906 return NT_STATUS_INVALID_PARAMETER;
5909 allocation_size = (uint64_t)IVAL(pdata,0);
5910 #ifdef LARGE_SMB_OFF_T
5911 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5912 #else /* LARGE_SMB_OFF_T */
5913 if (IVAL(pdata,4) != 0) {
5914 /* more than 32 bits? */
5915 return NT_STATUS_INVALID_PARAMETER;
5917 #endif /* LARGE_SMB_OFF_T */
5919 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5920 fname, (double)allocation_size ));
5922 if (allocation_size) {
5923 allocation_size = smb_roundup(conn, allocation_size);
5926 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5927 fname, (double)allocation_size ));
5929 if (fsp && fsp->fh->fd != -1) {
5930 /* Open file handle. */
5931 /* Only change if needed. */
5932 if (allocation_size != get_file_size_stat(psbuf)) {
5933 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5934 return map_nt_error_from_unix(errno);
5937 /* But always update the time. */
5939 * This is equivalent to a write. Ensure it's seen immediately
5940 * if there are no pending writes.
5942 trigger_write_time_update_immediate(fsp);
5943 return NT_STATUS_OK;
5946 /* Pathname or stat or directory file. */
5948 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5950 if (!NT_STATUS_IS_OK(status)) {
5954 status = SMB_VFS_CREATE_FILE(
5957 0, /* root_dir_fid */
5958 smb_fname, /* fname */
5959 FILE_WRITE_DATA, /* access_mask */
5960 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5962 FILE_OPEN, /* create_disposition*/
5963 0, /* create_options */
5964 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5965 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5966 0, /* allocation_size */
5969 &new_fsp, /* result */
5972 *psbuf = smb_fname->st;
5973 TALLOC_FREE(smb_fname);
5975 if (!NT_STATUS_IS_OK(status)) {
5976 /* NB. We check for open_was_deferred in the caller. */
5980 /* Only change if needed. */
5981 if (allocation_size != get_file_size_stat(psbuf)) {
5982 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5983 status = map_nt_error_from_unix(errno);
5984 close_file(req, new_fsp, NORMAL_CLOSE);
5989 /* Changing the allocation size should set the last mod time. */
5991 * This is equivalent to a write. Ensure it's seen immediately
5992 * if there are no pending writes.
5994 trigger_write_time_update_immediate(new_fsp);
5996 close_file(req, new_fsp, NORMAL_CLOSE);
5997 return NT_STATUS_OK;
6000 /****************************************************************************
6001 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6002 ****************************************************************************/
6004 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6005 struct smb_request *req,
6009 const struct smb_filename *smb_fname)
6013 if (total_data < 8) {
6014 return NT_STATUS_INVALID_PARAMETER;
6017 size = IVAL(pdata,0);
6018 #ifdef LARGE_SMB_OFF_T
6019 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6020 #else /* LARGE_SMB_OFF_T */
6021 if (IVAL(pdata,4) != 0) {
6022 /* more than 32 bits? */
6023 return NT_STATUS_INVALID_PARAMETER;
6025 #endif /* LARGE_SMB_OFF_T */
6026 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6027 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6030 return smb_set_file_size(conn, req,
6037 /****************************************************************************
6038 Allow a UNIX info mknod.
6039 ****************************************************************************/
6041 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6044 const struct smb_filename *smb_fname)
6046 uint32 file_type = IVAL(pdata,56);
6047 #if defined(HAVE_MAKEDEV)
6048 uint32 dev_major = IVAL(pdata,60);
6049 uint32 dev_minor = IVAL(pdata,68);
6051 SMB_DEV_T dev = (SMB_DEV_T)0;
6052 uint32 raw_unixmode = IVAL(pdata,84);
6056 if (total_data < 100) {
6057 return NT_STATUS_INVALID_PARAMETER;
6060 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6061 PERM_NEW_FILE, &unixmode);
6062 if (!NT_STATUS_IS_OK(status)) {
6066 #if defined(HAVE_MAKEDEV)
6067 dev = makedev(dev_major, dev_minor);
6070 switch (file_type) {
6071 #if defined(S_IFIFO)
6072 case UNIX_TYPE_FIFO:
6073 unixmode |= S_IFIFO;
6076 #if defined(S_IFSOCK)
6077 case UNIX_TYPE_SOCKET:
6078 unixmode |= S_IFSOCK;
6081 #if defined(S_IFCHR)
6082 case UNIX_TYPE_CHARDEV:
6083 unixmode |= S_IFCHR;
6086 #if defined(S_IFBLK)
6087 case UNIX_TYPE_BLKDEV:
6088 unixmode |= S_IFBLK;
6092 return NT_STATUS_INVALID_PARAMETER;
6095 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6096 "%.0f mode 0%o for file %s\n", (double)dev,
6097 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6099 /* Ok - do the mknod. */
6100 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6101 return map_nt_error_from_unix(errno);
6104 /* If any of the other "set" calls fail we
6105 * don't want to end up with a half-constructed mknod.
6108 if (lp_inherit_perms(SNUM(conn))) {
6110 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6112 return NT_STATUS_NO_MEMORY;
6114 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6116 TALLOC_FREE(parent);
6119 return NT_STATUS_OK;
6122 /****************************************************************************
6123 Deal with SMB_SET_FILE_UNIX_BASIC.
6124 ****************************************************************************/
6126 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6127 struct smb_request *req,
6131 const struct smb_filename *smb_fname)
6133 struct smb_file_time ft;
6134 uint32 raw_unixmode;
6137 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6138 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6139 NTSTATUS status = NT_STATUS_OK;
6140 bool delete_on_fail = False;
6141 enum perm_type ptype;
6142 files_struct *all_fsps = NULL;
6143 bool modify_mtime = true;
6145 SMB_STRUCT_STAT sbuf;
6149 if (total_data < 100) {
6150 return NT_STATUS_INVALID_PARAMETER;
6153 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6154 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6155 size=IVAL(pdata,0); /* first 8 Bytes are size */
6156 #ifdef LARGE_SMB_OFF_T
6157 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6158 #else /* LARGE_SMB_OFF_T */
6159 if (IVAL(pdata,4) != 0) {
6160 /* more than 32 bits? */
6161 return NT_STATUS_INVALID_PARAMETER;
6163 #endif /* LARGE_SMB_OFF_T */
6166 ft.atime = interpret_long_date(pdata+24); /* access_time */
6167 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6168 set_owner = (uid_t)IVAL(pdata,40);
6169 set_grp = (gid_t)IVAL(pdata,48);
6170 raw_unixmode = IVAL(pdata,84);
6172 if (VALID_STAT(smb_fname->st)) {
6173 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6174 ptype = PERM_EXISTING_DIR;
6176 ptype = PERM_EXISTING_FILE;
6179 ptype = PERM_NEW_FILE;
6182 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6184 if (!NT_STATUS_IS_OK(status)) {
6188 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6189 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6190 smb_fname_str_dbg(smb_fname), (double)size,
6191 (unsigned int)set_owner, (unsigned int)set_grp,
6192 (int)raw_unixmode));
6194 sbuf = smb_fname->st;
6196 if (!VALID_STAT(sbuf)) {
6197 struct smb_filename *smb_fname_tmp = NULL;
6199 * The only valid use of this is to create character and block
6200 * devices, and named pipes. This is deprecated (IMHO) and
6201 * a new info level should be used for mknod. JRA.
6204 status = smb_unix_mknod(conn,
6208 if (!NT_STATUS_IS_OK(status)) {
6212 status = copy_smb_filename(talloc_tos(), smb_fname,
6214 if (!NT_STATUS_IS_OK(status)) {
6218 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6219 status = map_nt_error_from_unix(errno);
6220 TALLOC_FREE(smb_fname_tmp);
6221 SMB_VFS_UNLINK(conn, smb_fname);
6225 sbuf = smb_fname_tmp->st;
6226 TALLOC_FREE(smb_fname_tmp);
6228 /* Ensure we don't try and change anything else. */
6229 raw_unixmode = SMB_MODE_NO_CHANGE;
6230 size = get_file_size_stat(&sbuf);
6231 ft.atime = sbuf.st_ex_atime;
6232 ft.mtime = sbuf.st_ex_mtime;
6234 * We continue here as we might want to change the
6237 delete_on_fail = True;
6241 /* Horrible backwards compatibility hack as an old server bug
6242 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6246 size = get_file_size_stat(&sbuf);
6251 * Deal with the UNIX specific mode set.
6254 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6255 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6256 "setting mode 0%o for file %s\n",
6257 (unsigned int)unixmode,
6258 smb_fname_str_dbg(smb_fname)));
6259 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6260 return map_nt_error_from_unix(errno);
6265 * Deal with the UNIX specific uid set.
6268 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6269 (sbuf.st_ex_uid != set_owner)) {
6272 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6273 "changing owner %u for path %s\n",
6274 (unsigned int)set_owner,
6275 smb_fname_str_dbg(smb_fname)));
6277 if (S_ISLNK(sbuf.st_ex_mode)) {
6278 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6279 set_owner, (gid_t)-1);
6281 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6282 set_owner, (gid_t)-1);
6286 status = map_nt_error_from_unix(errno);
6287 if (delete_on_fail) {
6288 SMB_VFS_UNLINK(conn, smb_fname);
6295 * Deal with the UNIX specific gid set.
6298 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6299 (sbuf.st_ex_gid != set_grp)) {
6300 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6301 "changing group %u for file %s\n",
6302 (unsigned int)set_owner,
6303 smb_fname_str_dbg(smb_fname)));
6304 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6306 status = map_nt_error_from_unix(errno);
6307 if (delete_on_fail) {
6308 SMB_VFS_UNLINK(conn, smb_fname);
6314 /* Deal with any size changes. */
6316 status = smb_set_file_size(conn, req,
6321 if (!NT_STATUS_IS_OK(status)) {
6325 /* Deal with any time changes. */
6326 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6327 /* No change, don't cancel anything. */
6331 id = vfs_file_id_from_sbuf(conn, &sbuf);
6332 for(all_fsps = file_find_di_first(id); all_fsps;
6333 all_fsps = file_find_di_next(all_fsps)) {
6335 * We're setting the time explicitly for UNIX.
6336 * Cancel any pending changes over all handles.
6338 all_fsps->update_write_time_on_close = false;
6339 TALLOC_FREE(all_fsps->update_write_time_event);
6343 * Override the "setting_write_time"
6344 * parameter here as it almost does what
6345 * we need. Just remember if we modified
6346 * mtime and send the notify ourselves.
6348 if (null_timespec(ft.mtime)) {
6349 modify_mtime = false;
6352 status = smb_set_file_time(conn,
6358 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6359 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6364 /****************************************************************************
6365 Deal with SMB_SET_FILE_UNIX_INFO2.
6366 ****************************************************************************/
6368 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6369 struct smb_request *req,
6373 const struct smb_filename *smb_fname)
6379 if (total_data < 116) {
6380 return NT_STATUS_INVALID_PARAMETER;
6383 /* Start by setting all the fields that are common between UNIX_BASIC
6386 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6388 if (!NT_STATUS_IS_OK(status)) {
6392 smb_fflags = IVAL(pdata, 108);
6393 smb_fmask = IVAL(pdata, 112);
6395 /* NB: We should only attempt to alter the file flags if the client
6396 * sends a non-zero mask.
6398 if (smb_fmask != 0) {
6399 int stat_fflags = 0;
6401 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6402 smb_fmask, &stat_fflags)) {
6403 /* Client asked to alter a flag we don't understand. */
6404 return NT_STATUS_INVALID_PARAMETER;
6407 if (fsp && fsp->fh->fd != -1) {
6408 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6409 return NT_STATUS_NOT_SUPPORTED;
6411 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6412 stat_fflags) != 0) {
6413 return map_nt_error_from_unix(errno);
6418 /* XXX: need to add support for changing the create_time here. You
6419 * can do this for paths on Darwin with setattrlist(2). The right way
6420 * to hook this up is probably by extending the VFS utimes interface.
6423 return NT_STATUS_OK;
6426 /****************************************************************************
6427 Create a directory with POSIX semantics.
6428 ****************************************************************************/
6430 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6431 struct smb_request *req,
6435 SMB_STRUCT_STAT *psbuf,
6436 int *pdata_return_size)
6438 struct smb_filename *smb_fname;
6439 NTSTATUS status = NT_STATUS_OK;
6440 uint32 raw_unixmode = 0;
6441 uint32 mod_unixmode = 0;
6442 mode_t unixmode = (mode_t)0;
6443 files_struct *fsp = NULL;
6444 uint16 info_level_return = 0;
6446 char *pdata = *ppdata;
6448 if (total_data < 18) {
6449 return NT_STATUS_INVALID_PARAMETER;
6452 raw_unixmode = IVAL(pdata,8);
6453 /* Next 4 bytes are not yet defined. */
6455 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6456 if (!NT_STATUS_IS_OK(status)) {
6460 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6462 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6463 fname, (unsigned int)unixmode ));
6465 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6467 if (!NT_STATUS_IS_OK(status)) {
6471 status = SMB_VFS_CREATE_FILE(
6474 0, /* root_dir_fid */
6475 smb_fname, /* fname */
6476 FILE_READ_ATTRIBUTES, /* access_mask */
6477 FILE_SHARE_NONE, /* share_access */
6478 FILE_CREATE, /* create_disposition*/
6479 FILE_DIRECTORY_FILE, /* create_options */
6480 mod_unixmode, /* file_attributes */
6481 0, /* oplock_request */
6482 0, /* allocation_size */
6488 *psbuf = smb_fname->st;
6489 TALLOC_FREE(smb_fname);
6491 if (NT_STATUS_IS_OK(status)) {
6492 close_file(req, fsp, NORMAL_CLOSE);
6495 info_level_return = SVAL(pdata,16);
6497 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6498 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6499 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6500 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6502 *pdata_return_size = 12;
6505 /* Realloc the data size */
6506 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6507 if (*ppdata == NULL) {
6508 *pdata_return_size = 0;
6509 return NT_STATUS_NO_MEMORY;
6513 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6514 SSVAL(pdata,2,0); /* No fnum. */
6515 SIVAL(pdata,4,info); /* Was directory created. */
6517 switch (info_level_return) {
6518 case SMB_QUERY_FILE_UNIX_BASIC:
6519 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6520 SSVAL(pdata,10,0); /* Padding. */
6521 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6523 case SMB_QUERY_FILE_UNIX_INFO2:
6524 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6525 SSVAL(pdata,10,0); /* Padding. */
6526 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6529 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6530 SSVAL(pdata,10,0); /* Padding. */
6537 /****************************************************************************
6538 Open/Create a file with POSIX semantics.
6539 ****************************************************************************/
6541 static NTSTATUS smb_posix_open(connection_struct *conn,
6542 struct smb_request *req,
6546 SMB_STRUCT_STAT *psbuf,
6547 int *pdata_return_size)
6549 struct smb_filename *smb_fname = NULL;
6550 bool extended_oplock_granted = False;
6551 char *pdata = *ppdata;
6553 uint32 wire_open_mode = 0;
6554 uint32 raw_unixmode = 0;
6555 uint32 mod_unixmode = 0;
6556 uint32 create_disp = 0;
6557 uint32 access_mask = 0;
6558 uint32 create_options = 0;
6559 NTSTATUS status = NT_STATUS_OK;
6560 mode_t unixmode = (mode_t)0;
6561 files_struct *fsp = NULL;
6562 int oplock_request = 0;
6564 uint16 info_level_return = 0;
6566 if (total_data < 18) {
6567 return NT_STATUS_INVALID_PARAMETER;
6570 flags = IVAL(pdata,0);
6571 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6572 if (oplock_request) {
6573 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6576 wire_open_mode = IVAL(pdata,4);
6578 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6579 return smb_posix_mkdir(conn, req,
6587 switch (wire_open_mode & SMB_ACCMODE) {
6589 access_mask = FILE_READ_DATA;
6592 access_mask = FILE_WRITE_DATA;
6595 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6598 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6599 (unsigned int)wire_open_mode ));
6600 return NT_STATUS_INVALID_PARAMETER;
6603 wire_open_mode &= ~SMB_ACCMODE;
6605 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6606 create_disp = FILE_CREATE;
6607 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6608 create_disp = FILE_OVERWRITE_IF;
6609 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6610 create_disp = FILE_OPEN_IF;
6611 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6612 create_disp = FILE_OPEN;
6614 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6615 (unsigned int)wire_open_mode ));
6616 return NT_STATUS_INVALID_PARAMETER;
6619 raw_unixmode = IVAL(pdata,8);
6620 /* Next 4 bytes are not yet defined. */
6622 status = unix_perms_from_wire(conn,
6625 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6628 if (!NT_STATUS_IS_OK(status)) {
6632 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6634 if (wire_open_mode & SMB_O_SYNC) {
6635 create_options |= FILE_WRITE_THROUGH;
6637 if (wire_open_mode & SMB_O_APPEND) {
6638 access_mask |= FILE_APPEND_DATA;
6640 if (wire_open_mode & SMB_O_DIRECT) {
6641 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6644 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6646 (unsigned int)wire_open_mode,
6647 (unsigned int)unixmode ));
6649 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6651 if (!NT_STATUS_IS_OK(status)) {
6655 status = SMB_VFS_CREATE_FILE(
6658 0, /* root_dir_fid */
6659 smb_fname, /* fname */
6660 access_mask, /* access_mask */
6661 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6663 create_disp, /* create_disposition*/
6664 FILE_NON_DIRECTORY_FILE, /* create_options */
6665 mod_unixmode, /* file_attributes */
6666 oplock_request, /* oplock_request */
6667 0, /* allocation_size */
6673 *psbuf = smb_fname->st;
6674 TALLOC_FREE(smb_fname);
6676 if (!NT_STATUS_IS_OK(status)) {
6680 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6681 extended_oplock_granted = True;
6684 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6685 extended_oplock_granted = True;
6688 info_level_return = SVAL(pdata,16);
6690 /* Allocate the correct return size. */
6692 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6693 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6694 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6695 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6697 *pdata_return_size = 12;
6700 /* Realloc the data size */
6701 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6702 if (*ppdata == NULL) {
6703 close_file(req, fsp, ERROR_CLOSE);
6704 *pdata_return_size = 0;
6705 return NT_STATUS_NO_MEMORY;
6709 if (extended_oplock_granted) {
6710 if (flags & REQUEST_BATCH_OPLOCK) {
6711 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6713 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6715 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6716 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6718 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6721 SSVAL(pdata,2,fsp->fnum);
6722 SIVAL(pdata,4,info); /* Was file created etc. */
6724 switch (info_level_return) {
6725 case SMB_QUERY_FILE_UNIX_BASIC:
6726 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6727 SSVAL(pdata,10,0); /* padding. */
6728 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6730 case SMB_QUERY_FILE_UNIX_INFO2:
6731 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6732 SSVAL(pdata,10,0); /* padding. */
6733 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6736 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6737 SSVAL(pdata,10,0); /* padding. */
6740 return NT_STATUS_OK;
6743 /****************************************************************************
6744 Delete a file with POSIX semantics.
6745 ****************************************************************************/
6747 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6748 struct smb_request *req,
6752 SMB_STRUCT_STAT *psbuf)
6754 struct smb_filename *smb_fname = NULL;
6755 NTSTATUS status = NT_STATUS_OK;
6756 files_struct *fsp = NULL;
6760 int create_options = 0;
6762 struct share_mode_lock *lck = NULL;
6764 if (total_data < 2) {
6765 return NT_STATUS_INVALID_PARAMETER;
6768 flags = SVAL(pdata,0);
6770 if (!VALID_STAT(*psbuf)) {
6771 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6774 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6775 !VALID_STAT_OF_DIR(*psbuf)) {
6776 return NT_STATUS_NOT_A_DIRECTORY;
6779 DEBUG(10,("smb_posix_unlink: %s %s\n",
6780 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6783 if (VALID_STAT_OF_DIR(*psbuf)) {
6784 create_options |= FILE_DIRECTORY_FILE;
6787 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6789 if (!NT_STATUS_IS_OK(status)) {
6793 status = SMB_VFS_CREATE_FILE(
6796 0, /* root_dir_fid */
6797 smb_fname, /* fname */
6798 DELETE_ACCESS, /* access_mask */
6799 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6801 FILE_OPEN, /* create_disposition*/
6802 create_options, /* create_options */
6803 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6804 0, /* oplock_request */
6805 0, /* allocation_size */
6811 *psbuf = smb_fname->st;
6812 TALLOC_FREE(smb_fname);
6814 if (!NT_STATUS_IS_OK(status)) {
6819 * Don't lie to client. If we can't really delete due to
6820 * non-POSIX opens return SHARING_VIOLATION.
6823 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6826 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6827 "lock for file %s\n", fsp->fsp_name));
6828 close_file(req, fsp, NORMAL_CLOSE);
6829 return NT_STATUS_INVALID_PARAMETER;
6833 * See if others still have the file open. If this is the case, then
6834 * don't delete. If all opens are POSIX delete we can set the delete
6835 * on close disposition.
6837 for (i=0; i<lck->num_share_modes; i++) {
6838 struct share_mode_entry *e = &lck->share_modes[i];
6839 if (is_valid_share_mode_entry(e)) {
6840 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6843 /* Fail with sharing violation. */
6844 close_file(req, fsp, NORMAL_CLOSE);
6846 return NT_STATUS_SHARING_VIOLATION;
6851 * Set the delete on close.
6853 status = smb_set_file_disposition_info(conn,
6860 if (!NT_STATUS_IS_OK(status)) {
6861 close_file(req, fsp, NORMAL_CLOSE);
6866 return close_file(req, fsp, NORMAL_CLOSE);
6869 /****************************************************************************
6870 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6871 ****************************************************************************/
6873 static void call_trans2setfilepathinfo(connection_struct *conn,
6874 struct smb_request *req,
6875 unsigned int tran_call,
6876 char **pparams, int total_params,
6877 char **ppdata, int total_data,
6878 unsigned int max_data_bytes)
6880 char *params = *pparams;
6881 char *pdata = *ppdata;
6883 SMB_STRUCT_STAT sbuf;
6885 struct smb_filename *smb_fname = NULL;
6886 files_struct *fsp = NULL;
6887 NTSTATUS status = NT_STATUS_OK;
6888 int data_return_size = 0;
6889 TALLOC_CTX *ctx = talloc_tos();
6892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6896 if (tran_call == TRANSACT2_SETFILEINFO) {
6897 if (total_params < 4) {
6898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6902 fsp = file_fsp(req, SVAL(params,0));
6903 /* Basic check for non-null fsp. */
6904 if (!check_fsp_open(conn, req, fsp)) {
6907 info_level = SVAL(params,2);
6909 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6911 reply_nterror(req, NT_STATUS_NO_MEMORY);
6915 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
6917 if (!NT_STATUS_IS_OK(status)) {
6918 reply_nterror(req, status);
6922 if(fsp->is_directory || fsp->fh->fd == -1) {
6924 * This is actually a SETFILEINFO on a directory
6925 * handle (returned from an NT SMB). NT5.0 seems
6926 * to do this call. JRA.
6928 if (INFO_LEVEL_IS_UNIX(info_level)) {
6929 /* Always do lstat for UNIX calls. */
6930 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6931 DEBUG(3,("call_trans2setfilepathinfo: "
6932 "SMB_VFS_LSTAT of %s failed "
6934 smb_fname_str_dbg(smb_fname),
6936 reply_unixerror(req,ERRDOS,ERRbadpath);
6940 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6941 DEBUG(3,("call_trans2setfilepathinfo: "
6942 "fileinfo of %s failed (%s)\n",
6943 smb_fname_str_dbg(smb_fname),
6945 reply_unixerror(req,ERRDOS,ERRbadpath);
6949 } else if (fsp->print_file) {
6951 * Doing a DELETE_ON_CLOSE should cancel a print job.
6953 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6954 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6956 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6959 send_trans2_replies(conn, req, params, 2,
6964 reply_unixerror(req, ERRDOS, ERRbadpath);
6969 * Original code - this is an open file.
6971 if (!check_fsp(conn, req, fsp)) {
6975 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6976 DEBUG(3,("call_trans2setfilepathinfo: fstat "
6977 "of fnum %d failed (%s)\n", fsp->fnum,
6979 reply_unixerror(req, ERRDOS, ERRbadfid);
6985 if (total_params < 7) {
6986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6990 info_level = SVAL(params,0);
6991 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6992 total_params - 6, STR_TERMINATE,
6994 if (!NT_STATUS_IS_OK(status)) {
6995 reply_nterror(req, status);
6999 status = filename_convert(ctx, conn,
7000 req->flags2 & FLAGS2_DFS_PATHNAMES,
7004 if (!NT_STATUS_IS_OK(status)) {
7005 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7006 reply_botherror(req,
7007 NT_STATUS_PATH_NOT_COVERED,
7008 ERRSRV, ERRbadpath);
7011 reply_nterror(req, status);
7015 if (INFO_LEVEL_IS_UNIX(info_level)) {
7017 * For CIFS UNIX extensions the target name may not exist.
7020 /* Always do lstat for UNIX calls. */
7021 SMB_VFS_LSTAT(conn, smb_fname);
7023 } else if (!VALID_STAT(smb_fname->st) &&
7024 SMB_VFS_STAT(conn, smb_fname)) {
7025 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7027 smb_fname_str_dbg(smb_fname),
7029 reply_unixerror(req, ERRDOS, ERRbadpath);
7034 /* Set sbuf for use below. */
7035 sbuf = smb_fname->st;
7037 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7038 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7042 if (!CAN_WRITE(conn)) {
7043 /* Allow POSIX opens. The open path will deny
7044 * any non-readonly opens. */
7045 if (info_level != SMB_POSIX_PATH_OPEN) {
7046 reply_doserror(req, ERRSRV, ERRaccess);
7051 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
7052 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
7054 /* Realloc the parameter size */
7055 *pparams = (char *)SMB_REALLOC(*pparams,2);
7056 if (*pparams == NULL) {
7057 reply_nterror(req, NT_STATUS_NO_MEMORY);
7064 switch (info_level) {
7066 case SMB_INFO_STANDARD:
7068 status = smb_set_info_standard(conn,
7076 case SMB_INFO_SET_EA:
7078 status = smb_info_set_ea(conn,
7086 case SMB_SET_FILE_BASIC_INFO:
7087 case SMB_FILE_BASIC_INFORMATION:
7089 status = smb_set_file_basic_info(conn,
7097 case SMB_FILE_ALLOCATION_INFORMATION:
7098 case SMB_SET_FILE_ALLOCATION_INFO:
7100 status = smb_set_file_allocation_info(conn, req,
7109 case SMB_FILE_END_OF_FILE_INFORMATION:
7110 case SMB_SET_FILE_END_OF_FILE_INFO:
7112 status = smb_set_file_end_of_file_info(conn, req,
7120 case SMB_FILE_DISPOSITION_INFORMATION:
7121 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7124 /* JRA - We used to just ignore this on a path ?
7125 * Shouldn't this be invalid level on a pathname
7128 if (tran_call != TRANSACT2_SETFILEINFO) {
7129 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7132 status = smb_set_file_disposition_info(conn,
7141 case SMB_FILE_POSITION_INFORMATION:
7143 status = smb_file_position_information(conn,
7150 /* From tridge Samba4 :
7151 * MODE_INFORMATION in setfileinfo (I have no
7152 * idea what "mode information" on a file is - it takes a value of 0,
7153 * 2, 4 or 6. What could it be?).
7156 case SMB_FILE_MODE_INFORMATION:
7158 status = smb_file_mode_information(conn,
7165 * CIFS UNIX extensions.
7168 case SMB_SET_FILE_UNIX_BASIC:
7170 status = smb_set_file_unix_basic(conn, req,
7178 case SMB_SET_FILE_UNIX_INFO2:
7180 status = smb_set_file_unix_info2(conn, req,
7188 case SMB_SET_FILE_UNIX_LINK:
7190 if (tran_call != TRANSACT2_SETPATHINFO) {
7191 /* We must have a pathname for this. */
7192 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7195 status = smb_set_file_unix_link(conn, req, pdata,
7200 case SMB_SET_FILE_UNIX_HLINK:
7202 if (tran_call != TRANSACT2_SETPATHINFO || smb_fname == NULL) {
7203 /* We must have a pathname for this. */
7204 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7207 status = smb_set_file_unix_hlink(conn, req,
7213 case SMB_FILE_RENAME_INFORMATION:
7215 status = smb_file_rename_information(conn, req,
7221 #if defined(HAVE_POSIX_ACLS)
7222 case SMB_SET_POSIX_ACL:
7224 status = smb_set_posix_acl(conn,
7234 case SMB_SET_POSIX_LOCK:
7236 if (tran_call != TRANSACT2_SETFILEINFO) {
7237 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7240 status = smb_set_posix_lock(conn, req,
7241 pdata, total_data, fsp);
7245 case SMB_POSIX_PATH_OPEN:
7247 if (tran_call != TRANSACT2_SETPATHINFO) {
7248 /* We must have a pathname for this. */
7249 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7253 status = smb_posix_open(conn, req,
7262 case SMB_POSIX_PATH_UNLINK:
7264 if (tran_call != TRANSACT2_SETPATHINFO) {
7265 /* We must have a pathname for this. */
7266 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7270 status = smb_posix_unlink(conn, req,
7279 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7283 if (!NT_STATUS_IS_OK(status)) {
7284 if (open_was_deferred(req->mid)) {
7285 /* We have re-scheduled this call. */
7288 if (blocking_lock_was_deferred(req->mid)) {
7289 /* We have re-scheduled this call. */
7292 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7293 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7294 ERRSRV, ERRbadpath);
7297 if (info_level == SMB_POSIX_PATH_OPEN) {
7298 reply_openerror(req, status);
7302 reply_nterror(req, status);
7307 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7313 /****************************************************************************
7314 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7315 ****************************************************************************/
7317 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7318 char **pparams, int total_params,
7319 char **ppdata, int total_data,
7320 unsigned int max_data_bytes)
7322 struct smb_filename *smb_dname = NULL;
7323 char *params = *pparams;
7324 char *pdata = *ppdata;
7325 char *directory = NULL;
7326 NTSTATUS status = NT_STATUS_OK;
7327 struct ea_list *ea_list = NULL;
7328 TALLOC_CTX *ctx = talloc_tos();
7330 if (!CAN_WRITE(conn)) {
7331 reply_doserror(req, ERRSRV, ERRaccess);
7335 if (total_params < 5) {
7336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7340 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7341 total_params - 4, STR_TERMINATE,
7343 if (!NT_STATUS_IS_OK(status)) {
7344 reply_nterror(req, status);
7348 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7350 status = filename_convert(ctx,
7352 req->flags2 & FLAGS2_DFS_PATHNAMES,
7357 if (!NT_STATUS_IS_OK(status)) {
7358 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7359 reply_botherror(req,
7360 NT_STATUS_PATH_NOT_COVERED,
7361 ERRSRV, ERRbadpath);
7364 reply_nterror(req, status);
7368 /* Any data in this call is an EA list. */
7369 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7370 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7375 * OS/2 workplace shell seems to send SET_EA requests of "null"
7376 * length (4 bytes containing IVAL 4).
7377 * They seem to have no effect. Bug #3212. JRA.
7380 if (total_data != 4) {
7381 if (total_data < 10) {
7382 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7386 if (IVAL(pdata,0) > total_data) {
7387 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7388 IVAL(pdata,0), (unsigned int)total_data));
7389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7393 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7400 /* If total_data == 4 Windows doesn't care what values
7401 * are placed in that field, it just ignores them.
7402 * The System i QNTC IBM SMB client puts bad values here,
7403 * so ignore them. */
7405 status = create_directory(conn, req, smb_dname);
7407 if (!NT_STATUS_IS_OK(status)) {
7408 reply_nterror(req, status);
7412 /* Try and set any given EA. */
7414 status = set_ea(conn, NULL, smb_dname, ea_list);
7415 if (!NT_STATUS_IS_OK(status)) {
7416 reply_nterror(req, status);
7421 /* Realloc the parameter and data sizes */
7422 *pparams = (char *)SMB_REALLOC(*pparams,2);
7423 if(*pparams == NULL) {
7424 reply_nterror(req, NT_STATUS_NO_MEMORY);
7431 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7434 TALLOC_FREE(smb_dname);
7438 /****************************************************************************
7439 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7440 We don't actually do this - we just send a null response.
7441 ****************************************************************************/
7443 static void call_trans2findnotifyfirst(connection_struct *conn,
7444 struct smb_request *req,
7445 char **pparams, int total_params,
7446 char **ppdata, int total_data,
7447 unsigned int max_data_bytes)
7449 char *params = *pparams;
7452 if (total_params < 6) {
7453 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7457 info_level = SVAL(params,4);
7458 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7460 switch (info_level) {
7465 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7469 /* Realloc the parameter and data sizes */
7470 *pparams = (char *)SMB_REALLOC(*pparams,6);
7471 if (*pparams == NULL) {
7472 reply_nterror(req, NT_STATUS_NO_MEMORY);
7477 SSVAL(params,0,fnf_handle);
7478 SSVAL(params,2,0); /* No changes */
7479 SSVAL(params,4,0); /* No EA errors */
7486 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7491 /****************************************************************************
7492 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7493 changes). Currently this does nothing.
7494 ****************************************************************************/
7496 static void call_trans2findnotifynext(connection_struct *conn,
7497 struct smb_request *req,
7498 char **pparams, int total_params,
7499 char **ppdata, int total_data,
7500 unsigned int max_data_bytes)
7502 char *params = *pparams;
7504 DEBUG(3,("call_trans2findnotifynext\n"));
7506 /* Realloc the parameter and data sizes */
7507 *pparams = (char *)SMB_REALLOC(*pparams,4);
7508 if (*pparams == NULL) {
7509 reply_nterror(req, NT_STATUS_NO_MEMORY);
7514 SSVAL(params,0,0); /* No changes */
7515 SSVAL(params,2,0); /* No EA errors */
7517 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7522 /****************************************************************************
7523 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7524 ****************************************************************************/
7526 static void call_trans2getdfsreferral(connection_struct *conn,
7527 struct smb_request *req,
7528 char **pparams, int total_params,
7529 char **ppdata, int total_data,
7530 unsigned int max_data_bytes)
7532 char *params = *pparams;
7533 char *pathname = NULL;
7535 int max_referral_level;
7536 NTSTATUS status = NT_STATUS_OK;
7537 TALLOC_CTX *ctx = talloc_tos();
7539 DEBUG(10,("call_trans2getdfsreferral\n"));
7541 if (total_params < 3) {
7542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7546 max_referral_level = SVAL(params,0);
7548 if(!lp_host_msdfs()) {
7549 reply_doserror(req, ERRDOS, ERRbadfunc);
7553 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7554 total_params - 2, STR_TERMINATE);
7556 reply_nterror(req, NT_STATUS_NOT_FOUND);
7559 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7560 ppdata,&status)) < 0) {
7561 reply_nterror(req, status);
7565 SSVAL(req->inbuf, smb_flg2,
7566 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7567 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7572 #define LMCAT_SPL 0x53
7573 #define LMFUNC_GETJOBID 0x60
7575 /****************************************************************************
7576 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7577 ****************************************************************************/
7579 static void call_trans2ioctl(connection_struct *conn,
7580 struct smb_request *req,
7581 char **pparams, int total_params,
7582 char **ppdata, int total_data,
7583 unsigned int max_data_bytes)
7585 char *pdata = *ppdata;
7586 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7588 /* check for an invalid fid before proceeding */
7591 reply_doserror(req, ERRDOS, ERRbadfid);
7595 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7596 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7597 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7598 if (*ppdata == NULL) {
7599 reply_nterror(req, NT_STATUS_NO_MEMORY);
7604 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7605 CAN ACCEPT THIS IN UNICODE. JRA. */
7607 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7608 srvstr_push(pdata, req->flags2, pdata + 2,
7609 global_myname(), 15,
7610 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7611 srvstr_push(pdata, req->flags2, pdata+18,
7612 lp_servicename(SNUM(conn)), 13,
7613 STR_ASCII|STR_TERMINATE); /* Service name */
7614 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7619 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7620 reply_doserror(req, ERRSRV, ERRerror);
7623 /****************************************************************************
7624 Reply to a SMBfindclose (stop trans2 directory search).
7625 ****************************************************************************/
7627 void reply_findclose(struct smb_request *req)
7631 START_PROFILE(SMBfindclose);
7634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7635 END_PROFILE(SMBfindclose);
7639 dptr_num = SVALS(req->vwv+0, 0);
7641 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7643 dptr_close(&dptr_num);
7645 reply_outbuf(req, 0, 0);
7647 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7649 END_PROFILE(SMBfindclose);
7653 /****************************************************************************
7654 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7655 ****************************************************************************/
7657 void reply_findnclose(struct smb_request *req)
7661 START_PROFILE(SMBfindnclose);
7664 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7665 END_PROFILE(SMBfindnclose);
7669 dptr_num = SVAL(req->vwv+0, 0);
7671 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7673 /* We never give out valid handles for a
7674 findnotifyfirst - so any dptr_num is ok here.
7677 reply_outbuf(req, 0, 0);
7679 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7681 END_PROFILE(SMBfindnclose);
7685 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7686 struct trans_state *state)
7688 if (Protocol >= PROTOCOL_NT1) {
7689 req->flags2 |= 0x40; /* IS_LONG_NAME */
7690 SSVAL(req->inbuf,smb_flg2,req->flags2);
7693 if (conn->encrypt_level == Required && !req->encrypted) {
7694 if (state->call != TRANSACT2_QFSINFO &&
7695 state->call != TRANSACT2_SETFSINFO) {
7696 DEBUG(0,("handle_trans2: encryption required "
7698 (unsigned int)state->call));
7699 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7704 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7706 /* Now we must call the relevant TRANS2 function */
7707 switch(state->call) {
7708 case TRANSACT2_OPEN:
7710 START_PROFILE(Trans2_open);
7711 call_trans2open(conn, req,
7712 &state->param, state->total_param,
7713 &state->data, state->total_data,
7714 state->max_data_return);
7715 END_PROFILE(Trans2_open);
7719 case TRANSACT2_FINDFIRST:
7721 START_PROFILE(Trans2_findfirst);
7722 call_trans2findfirst(conn, req,
7723 &state->param, state->total_param,
7724 &state->data, state->total_data,
7725 state->max_data_return);
7726 END_PROFILE(Trans2_findfirst);
7730 case TRANSACT2_FINDNEXT:
7732 START_PROFILE(Trans2_findnext);
7733 call_trans2findnext(conn, req,
7734 &state->param, state->total_param,
7735 &state->data, state->total_data,
7736 state->max_data_return);
7737 END_PROFILE(Trans2_findnext);
7741 case TRANSACT2_QFSINFO:
7743 START_PROFILE(Trans2_qfsinfo);
7744 call_trans2qfsinfo(conn, req,
7745 &state->param, state->total_param,
7746 &state->data, state->total_data,
7747 state->max_data_return);
7748 END_PROFILE(Trans2_qfsinfo);
7752 case TRANSACT2_SETFSINFO:
7754 START_PROFILE(Trans2_setfsinfo);
7755 call_trans2setfsinfo(conn, req,
7756 &state->param, state->total_param,
7757 &state->data, state->total_data,
7758 state->max_data_return);
7759 END_PROFILE(Trans2_setfsinfo);
7763 case TRANSACT2_QPATHINFO:
7764 case TRANSACT2_QFILEINFO:
7766 START_PROFILE(Trans2_qpathinfo);
7767 call_trans2qfilepathinfo(conn, req, state->call,
7768 &state->param, state->total_param,
7769 &state->data, state->total_data,
7770 state->max_data_return);
7771 END_PROFILE(Trans2_qpathinfo);
7775 case TRANSACT2_SETPATHINFO:
7776 case TRANSACT2_SETFILEINFO:
7778 START_PROFILE(Trans2_setpathinfo);
7779 call_trans2setfilepathinfo(conn, req, state->call,
7780 &state->param, state->total_param,
7781 &state->data, state->total_data,
7782 state->max_data_return);
7783 END_PROFILE(Trans2_setpathinfo);
7787 case TRANSACT2_FINDNOTIFYFIRST:
7789 START_PROFILE(Trans2_findnotifyfirst);
7790 call_trans2findnotifyfirst(conn, req,
7791 &state->param, state->total_param,
7792 &state->data, state->total_data,
7793 state->max_data_return);
7794 END_PROFILE(Trans2_findnotifyfirst);
7798 case TRANSACT2_FINDNOTIFYNEXT:
7800 START_PROFILE(Trans2_findnotifynext);
7801 call_trans2findnotifynext(conn, req,
7802 &state->param, state->total_param,
7803 &state->data, state->total_data,
7804 state->max_data_return);
7805 END_PROFILE(Trans2_findnotifynext);
7809 case TRANSACT2_MKDIR:
7811 START_PROFILE(Trans2_mkdir);
7812 call_trans2mkdir(conn, req,
7813 &state->param, state->total_param,
7814 &state->data, state->total_data,
7815 state->max_data_return);
7816 END_PROFILE(Trans2_mkdir);
7820 case TRANSACT2_GET_DFS_REFERRAL:
7822 START_PROFILE(Trans2_get_dfs_referral);
7823 call_trans2getdfsreferral(conn, req,
7824 &state->param, state->total_param,
7825 &state->data, state->total_data,
7826 state->max_data_return);
7827 END_PROFILE(Trans2_get_dfs_referral);
7831 case TRANSACT2_IOCTL:
7833 START_PROFILE(Trans2_ioctl);
7834 call_trans2ioctl(conn, req,
7835 &state->param, state->total_param,
7836 &state->data, state->total_data,
7837 state->max_data_return);
7838 END_PROFILE(Trans2_ioctl);
7843 /* Error in request */
7844 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7845 reply_doserror(req, ERRSRV,ERRerror);
7849 /****************************************************************************
7850 Reply to a SMBtrans2.
7851 ****************************************************************************/
7853 void reply_trans2(struct smb_request *req)
7855 connection_struct *conn = req->conn;
7860 unsigned int tran_call;
7861 struct trans_state *state;
7864 START_PROFILE(SMBtrans2);
7866 if (req->wct < 14) {
7867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7868 END_PROFILE(SMBtrans2);
7872 dsoff = SVAL(req->vwv+12, 0);
7873 dscnt = SVAL(req->vwv+11, 0);
7874 psoff = SVAL(req->vwv+10, 0);
7875 pscnt = SVAL(req->vwv+9, 0);
7876 tran_call = SVAL(req->vwv+14, 0);
7878 result = allow_new_trans(conn->pending_trans, req->mid);
7879 if (!NT_STATUS_IS_OK(result)) {
7880 DEBUG(2, ("Got invalid trans2 request: %s\n",
7881 nt_errstr(result)));
7882 reply_nterror(req, result);
7883 END_PROFILE(SMBtrans2);
7888 switch (tran_call) {
7889 /* List the allowed trans2 calls on IPC$ */
7890 case TRANSACT2_OPEN:
7891 case TRANSACT2_GET_DFS_REFERRAL:
7892 case TRANSACT2_QFILEINFO:
7893 case TRANSACT2_QFSINFO:
7894 case TRANSACT2_SETFSINFO:
7897 reply_doserror(req, ERRSRV, ERRaccess);
7898 END_PROFILE(SMBtrans2);
7903 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7904 DEBUG(0, ("talloc failed\n"));
7905 reply_nterror(req, NT_STATUS_NO_MEMORY);
7906 END_PROFILE(SMBtrans2);
7910 state->cmd = SMBtrans2;
7912 state->mid = req->mid;
7913 state->vuid = req->vuid;
7914 state->setup_count = SVAL(req->vwv+13, 0);
7915 state->setup = NULL;
7916 state->total_param = SVAL(req->vwv+0, 0);
7917 state->param = NULL;
7918 state->total_data = SVAL(req->vwv+1, 0);
7920 state->max_param_return = SVAL(req->vwv+2, 0);
7921 state->max_data_return = SVAL(req->vwv+3, 0);
7922 state->max_setup_return = SVAL(req->vwv+4, 0);
7923 state->close_on_completion = BITSETW(req->vwv+5, 0);
7924 state->one_way = BITSETW(req->vwv+5, 1);
7926 state->call = tran_call;
7928 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7929 is so as a sanity check */
7930 if (state->setup_count != 1) {
7932 * Need to have rc=0 for ioctl to get job id for OS/2.
7933 * Network printing will fail if function is not successful.
7934 * Similar function in reply.c will be used if protocol
7935 * is LANMAN1.0 instead of LM1.2X002.
7936 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7937 * outbuf doesn't have to be set(only job id is used).
7939 if ( (state->setup_count == 4)
7940 && (tran_call == TRANSACT2_IOCTL)
7941 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7942 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7943 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7945 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7946 DEBUG(2,("Transaction is %d\n",tran_call));
7948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7949 END_PROFILE(SMBtrans2);
7954 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7957 if (state->total_data) {
7959 if (trans_oob(state->total_data, 0, dscnt)
7960 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7964 /* Can't use talloc here, the core routines do realloc on the
7965 * params and data. */
7966 state->data = (char *)SMB_MALLOC(state->total_data);
7967 if (state->data == NULL) {
7968 DEBUG(0,("reply_trans2: data malloc fail for %u "
7969 "bytes !\n", (unsigned int)state->total_data));
7971 reply_nterror(req, NT_STATUS_NO_MEMORY);
7972 END_PROFILE(SMBtrans2);
7976 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7979 if (state->total_param) {
7981 if (trans_oob(state->total_param, 0, pscnt)
7982 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7986 /* Can't use talloc here, the core routines do realloc on the
7987 * params and data. */
7988 state->param = (char *)SMB_MALLOC(state->total_param);
7989 if (state->param == NULL) {
7990 DEBUG(0,("reply_trans: param malloc fail for %u "
7991 "bytes !\n", (unsigned int)state->total_param));
7992 SAFE_FREE(state->data);
7994 reply_nterror(req, NT_STATUS_NO_MEMORY);
7995 END_PROFILE(SMBtrans2);
7999 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8002 state->received_data = dscnt;
8003 state->received_param = pscnt;
8005 if ((state->received_param == state->total_param) &&
8006 (state->received_data == state->total_data)) {
8008 handle_trans2(conn, req, state);
8010 SAFE_FREE(state->data);
8011 SAFE_FREE(state->param);
8013 END_PROFILE(SMBtrans2);
8017 DLIST_ADD(conn->pending_trans, state);
8019 /* We need to send an interim response then receive the rest
8020 of the parameter/data bytes */
8021 reply_outbuf(req, 0, 0);
8022 show_msg((char *)req->outbuf);
8023 END_PROFILE(SMBtrans2);
8028 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8029 SAFE_FREE(state->data);
8030 SAFE_FREE(state->param);
8032 END_PROFILE(SMBtrans2);
8033 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8037 /****************************************************************************
8038 Reply to a SMBtranss2
8039 ****************************************************************************/
8041 void reply_transs2(struct smb_request *req)
8043 connection_struct *conn = req->conn;
8044 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8045 struct trans_state *state;
8047 START_PROFILE(SMBtranss2);
8049 show_msg((char *)req->inbuf);
8052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8053 END_PROFILE(SMBtranss2);
8057 for (state = conn->pending_trans; state != NULL;
8058 state = state->next) {
8059 if (state->mid == req->mid) {
8064 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8065 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8066 END_PROFILE(SMBtranss2);
8070 /* Revise state->total_param and state->total_data in case they have
8071 changed downwards */
8073 if (SVAL(req->vwv+0, 0) < state->total_param)
8074 state->total_param = SVAL(req->vwv+0, 0);
8075 if (SVAL(req->vwv+1, 0) < state->total_data)
8076 state->total_data = SVAL(req->vwv+1, 0);
8078 pcnt = SVAL(req->vwv+2, 0);
8079 poff = SVAL(req->vwv+3, 0);
8080 pdisp = SVAL(req->vwv+4, 0);
8082 dcnt = SVAL(req->vwv+5, 0);
8083 doff = SVAL(req->vwv+6, 0);
8084 ddisp = SVAL(req->vwv+7, 0);
8086 state->received_param += pcnt;
8087 state->received_data += dcnt;
8089 if ((state->received_data > state->total_data) ||
8090 (state->received_param > state->total_param))
8094 if (trans_oob(state->total_param, pdisp, pcnt)
8095 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8098 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8102 if (trans_oob(state->total_data, ddisp, dcnt)
8103 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8106 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8109 if ((state->received_param < state->total_param) ||
8110 (state->received_data < state->total_data)) {
8111 END_PROFILE(SMBtranss2);
8115 handle_trans2(conn, req, state);
8117 DLIST_REMOVE(conn->pending_trans, state);
8118 SAFE_FREE(state->data);
8119 SAFE_FREE(state->param);
8122 END_PROFILE(SMBtranss2);
8127 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8128 DLIST_REMOVE(conn->pending_trans, state);
8129 SAFE_FREE(state->data);
8130 SAFE_FREE(state->param);
8132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8133 END_PROFILE(SMBtranss2);