2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
247 *pnum_names = num_names;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list *ea_list_head = NULL;
266 if (!lp_ea_support(SNUM(conn))) {
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
285 listp = TALLOC_P(mem_ctx, struct ea_list);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
346 if (ea_list->ea.value.length > 65535) {
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
372 size_t total_ea_len = 0;
373 TALLOC_CTX *mem_ctx = NULL;
375 if (!lp_ea_support(SNUM(conn))) {
378 mem_ctx = talloc_tos();
379 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
383 /****************************************************************************
384 Ensure the EA name is case insensitive by matching any existing EA name.
385 ****************************************************************************/
387 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
390 TALLOC_CTX *mem_ctx = talloc_tos();
391 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
393 for (; ea_list; ea_list = ea_list->next) {
394 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
395 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
396 &unix_ea_name[5], ea_list->ea.name));
397 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
403 /****************************************************************************
404 Set or delete an extended attribute.
405 ****************************************************************************/
407 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
408 const struct smb_filename *smb_fname, struct ea_list *ea_list)
413 if (!lp_ea_support(SNUM(conn))) {
414 return NT_STATUS_EAS_NOT_SUPPORTED;
417 status = get_full_smb_filename(talloc_tos(), smb_fname,
419 if (!NT_STATUS_IS_OK(status)) {
423 for (;ea_list; ea_list = ea_list->next) {
425 fstring unix_ea_name;
427 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
428 fstrcat(unix_ea_name, ea_list->ea.name);
430 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
432 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
434 if (samba_private_attr_name(unix_ea_name)) {
435 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
436 return NT_STATUS_ACCESS_DENIED;
439 if (ea_list->ea.value.length == 0) {
440 /* Remove the attribute. */
441 if (fsp && (fsp->fh->fd != -1)) {
442 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
443 unix_ea_name, fsp->fsp_name));
444 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
446 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
447 unix_ea_name, fname));
448 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
451 /* Removing a non existent attribute always succeeds. */
452 if (ret == -1 && errno == ENOATTR) {
453 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
459 if (fsp && (fsp->fh->fd != -1)) {
460 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
461 unix_ea_name, fsp->fsp_name));
462 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
463 ea_list->ea.value.data, ea_list->ea.value.length, 0);
465 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
466 unix_ea_name, fname));
467 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
468 ea_list->ea.value.data, ea_list->ea.value.length, 0);
474 if (errno == ENOTSUP) {
475 return NT_STATUS_EAS_NOT_SUPPORTED;
478 return map_nt_error_from_unix(errno);
484 /****************************************************************************
485 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
486 ****************************************************************************/
488 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
490 struct ea_list *ea_list_head = NULL;
491 size_t converted_size, offset = 0;
493 while (offset + 2 < data_size) {
494 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
495 unsigned int namelen = CVAL(pdata,offset);
497 offset++; /* Go past the namelen byte. */
499 /* integer wrap paranioa. */
500 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
501 (offset > data_size) || (namelen > data_size) ||
502 (offset + namelen >= data_size)) {
505 /* Ensure the name is null terminated. */
506 if (pdata[offset + namelen] != '\0') {
509 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
511 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
512 "failed: %s", strerror(errno)));
518 offset += (namelen + 1); /* Go past the name + terminating zero. */
519 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
520 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
526 /****************************************************************************
527 Read one EA list entry from the buffer.
528 ****************************************************************************/
530 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
532 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
534 unsigned int namelen;
535 size_t converted_size;
545 eal->ea.flags = CVAL(pdata,0);
546 namelen = CVAL(pdata,1);
547 val_len = SVAL(pdata,2);
549 if (4 + namelen + 1 + val_len > data_size) {
553 /* Ensure the name is null terminated. */
554 if (pdata[namelen + 4] != '\0') {
557 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
558 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
565 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
566 if (!eal->ea.value.data) {
570 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
572 /* Ensure we're null terminated just in case we print the value. */
573 eal->ea.value.data[val_len] = '\0';
574 /* But don't count the null. */
575 eal->ea.value.length--;
578 *pbytes_used = 4 + namelen + 1 + val_len;
581 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
582 dump_data(10, eal->ea.value.data, eal->ea.value.length);
587 /****************************************************************************
588 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
589 ****************************************************************************/
591 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
593 struct ea_list *ea_list_head = NULL;
595 size_t bytes_used = 0;
597 while (offset < data_size) {
598 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
604 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
605 offset += bytes_used;
611 /****************************************************************************
612 Count the total EA size needed.
613 ****************************************************************************/
615 static size_t ea_list_size(struct ea_list *ealist)
618 struct ea_list *listp;
621 for (listp = ealist; listp; listp = listp->next) {
622 push_ascii_fstring(dos_ea_name, listp->ea.name);
623 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
625 /* Add on 4 for total length. */
633 /****************************************************************************
634 Return a union of EA's from a file list and a list of names.
635 The TALLOC context for the two lists *MUST* be identical as we steal
636 memory from one list to add to another. JRA.
637 ****************************************************************************/
639 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
641 struct ea_list *nlistp, *flistp;
643 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
644 for (flistp = file_list; flistp; flistp = flistp->next) {
645 if (strequal(nlistp->ea.name, flistp->ea.name)) {
651 /* Copy the data from this entry. */
652 nlistp->ea.flags = flistp->ea.flags;
653 nlistp->ea.value = flistp->ea.value;
656 nlistp->ea.flags = 0;
657 ZERO_STRUCT(nlistp->ea.value);
661 *total_ea_len = ea_list_size(name_list);
665 /****************************************************************************
666 Send the required number of replies back.
667 We assume all fields other than the data fields are
668 set correctly for the type of call.
669 HACK ! Always assumes smb_setup field is zero.
670 ****************************************************************************/
672 void send_trans2_replies(connection_struct *conn,
673 struct smb_request *req,
680 /* As we are using a protocol > LANMAN1 then the max_send
681 variable must have been set in the sessetupX call.
682 This takes precedence over the max_xmit field in the
683 global struct. These different max_xmit variables should
684 be merged as this is now too confusing */
686 int data_to_send = datasize;
687 int params_to_send = paramsize;
689 const char *pp = params;
690 const char *pd = pdata;
691 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
692 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
693 int data_alignment_offset = 0;
694 bool overflow = False;
695 struct smbd_server_connection *sconn = smbd_server_conn;
696 int max_send = sconn->smb1.sessions.max_send;
698 /* Modify the data_to_send and datasize and set the error if
699 we're trying to send more than max_data_bytes. We still send
700 the part of the packet(s) that fit. Strange, but needed
703 if (max_data_bytes > 0 && datasize > max_data_bytes) {
704 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
705 max_data_bytes, datasize ));
706 datasize = data_to_send = max_data_bytes;
710 /* If there genuinely are no parameters or data to send just send the empty packet */
712 if(params_to_send == 0 && data_to_send == 0) {
713 reply_outbuf(req, 10, 0);
714 show_msg((char *)req->outbuf);
715 if (!srv_send_smb(smbd_server_fd(),
718 IS_CONN_ENCRYPTED(conn),
720 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
722 TALLOC_FREE(req->outbuf);
726 /* When sending params and data ensure that both are nicely aligned */
727 /* Only do this alignment when there is also data to send - else
728 can cause NT redirector problems. */
730 if (((params_to_send % 4) != 0) && (data_to_send != 0))
731 data_alignment_offset = 4 - (params_to_send % 4);
733 /* Space is bufsize minus Netbios over TCP header minus SMB header */
734 /* The alignment_offset is to align the param bytes on an even byte
735 boundary. NT 4.0 Beta needs this to work correctly. */
737 useable_space = max_send - (smb_size
740 + data_alignment_offset);
742 if (useable_space < 0) {
743 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
744 "= %d!!!", useable_space));
745 exit_server_cleanly("send_trans2_replies: Not enough space");
748 while (params_to_send || data_to_send) {
749 /* Calculate whether we will totally or partially fill this packet */
751 total_sent_thistime = params_to_send + data_to_send;
753 /* We can never send more than useable_space */
755 * Note that 'useable_space' does not include the alignment offsets,
756 * but we must include the alignment offsets in the calculation of
757 * the length of the data we send over the wire, as the alignment offsets
758 * are sent here. Fix from Marc_Jacobsen@hp.com.
761 total_sent_thistime = MIN(total_sent_thistime, useable_space);
763 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
764 + data_alignment_offset);
767 * We might have SMBtrans2s in req which was transferred to
768 * the outbuf, fix that.
770 SCVAL(req->outbuf, smb_com, SMBtrans2);
772 /* Set total params and data to be sent */
773 SSVAL(req->outbuf,smb_tprcnt,paramsize);
774 SSVAL(req->outbuf,smb_tdrcnt,datasize);
776 /* Calculate how many parameters and data we can fit into
777 * this packet. Parameters get precedence
780 params_sent_thistime = MIN(params_to_send,useable_space);
781 data_sent_thistime = useable_space - params_sent_thistime;
782 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
784 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
786 /* smb_proff is the offset from the start of the SMB header to the
787 parameter bytes, however the first 4 bytes of outbuf are
788 the Netbios over TCP header. Thus use smb_base() to subtract
789 them from the calculation */
791 SSVAL(req->outbuf,smb_proff,
792 ((smb_buf(req->outbuf)+alignment_offset)
793 - smb_base(req->outbuf)));
795 if(params_sent_thistime == 0)
796 SSVAL(req->outbuf,smb_prdisp,0);
798 /* Absolute displacement of param bytes sent in this packet */
799 SSVAL(req->outbuf,smb_prdisp,pp - params);
801 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
802 if(data_sent_thistime == 0) {
803 SSVAL(req->outbuf,smb_droff,0);
804 SSVAL(req->outbuf,smb_drdisp, 0);
806 /* The offset of the data bytes is the offset of the
807 parameter bytes plus the number of parameters being sent this time */
808 SSVAL(req->outbuf, smb_droff,
809 ((smb_buf(req->outbuf)+alignment_offset)
810 - smb_base(req->outbuf))
811 + params_sent_thistime + data_alignment_offset);
812 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
815 /* Initialize the padding for alignment */
817 if (alignment_offset != 0) {
818 memset(smb_buf(req->outbuf), 0, alignment_offset);
821 /* Copy the param bytes into the packet */
823 if(params_sent_thistime) {
824 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
825 params_sent_thistime);
828 /* Copy in the data bytes */
829 if(data_sent_thistime) {
830 if (data_alignment_offset != 0) {
831 memset((smb_buf(req->outbuf)+alignment_offset+
832 params_sent_thistime), 0,
833 data_alignment_offset);
835 memcpy(smb_buf(req->outbuf)+alignment_offset
836 +params_sent_thistime+data_alignment_offset,
837 pd,data_sent_thistime);
840 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
841 params_sent_thistime, data_sent_thistime, useable_space));
842 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
843 params_to_send, data_to_send, paramsize, datasize));
846 error_packet_set((char *)req->outbuf,
847 ERRDOS,ERRbufferoverflow,
848 STATUS_BUFFER_OVERFLOW,
852 /* Send the packet */
853 show_msg((char *)req->outbuf);
854 if (!srv_send_smb(smbd_server_fd(),
857 IS_CONN_ENCRYPTED(conn),
859 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
861 TALLOC_FREE(req->outbuf);
863 pp += params_sent_thistime;
864 pd += data_sent_thistime;
866 params_to_send -= params_sent_thistime;
867 data_to_send -= data_sent_thistime;
870 if(params_to_send < 0 || data_to_send < 0) {
871 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
872 params_to_send, data_to_send));
880 /****************************************************************************
881 Reply to a TRANSACT2_OPEN.
882 ****************************************************************************/
884 static void call_trans2open(connection_struct *conn,
885 struct smb_request *req,
886 char **pparams, int total_params,
887 char **ppdata, int total_data,
888 unsigned int max_data_bytes)
890 struct smb_filename *smb_fname = NULL;
891 char *params = *pparams;
892 char *pdata = *ppdata;
897 bool return_additional_info;
910 struct ea_list *ea_list = NULL;
915 uint32 create_disposition;
916 uint32 create_options = 0;
917 TALLOC_CTX *ctx = talloc_tos();
920 * Ensure we have enough parameters to perform the operation.
923 if (total_params < 29) {
924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
928 flags = SVAL(params, 0);
929 deny_mode = SVAL(params, 2);
930 open_attr = SVAL(params,6);
931 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
932 if (oplock_request) {
933 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
937 return_additional_info = BITSETW(params,0);
938 open_sattr = SVAL(params, 4);
939 open_time = make_unix_date3(params+8);
941 open_ofun = SVAL(params,12);
942 open_size = IVAL(params,14);
946 reply_doserror(req, ERRSRV, ERRaccess);
950 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
951 total_params - 28, STR_TERMINATE,
953 if (!NT_STATUS_IS_OK(status)) {
954 reply_nterror(req, status);
958 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
959 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
960 (unsigned int)open_ofun, open_size));
962 status = filename_convert(ctx,
964 req->flags2 & FLAGS2_DFS_PATHNAMES,
968 if (!NT_STATUS_IS_OK(status)) {
969 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
971 NT_STATUS_PATH_NOT_COVERED,
975 reply_nterror(req, status);
979 if (open_ofun == 0) {
980 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
984 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
990 reply_doserror(req, ERRDOS, ERRbadaccess);
994 /* Any data in this call is an EA list. */
995 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
996 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1000 if (total_data != 4) {
1001 if (total_data < 10) {
1002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1006 if (IVAL(pdata,0) > total_data) {
1007 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1008 IVAL(pdata,0), (unsigned int)total_data));
1009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1013 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1019 } else if (IVAL(pdata,0) != 4) {
1020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1024 status = SMB_VFS_CREATE_FILE(
1027 0, /* root_dir_fid */
1028 smb_fname, /* fname */
1029 access_mask, /* access_mask */
1030 share_mode, /* share_access */
1031 create_disposition, /* create_disposition*/
1032 create_options, /* create_options */
1033 open_attr, /* file_attributes */
1034 oplock_request, /* oplock_request */
1035 open_size, /* allocation_size */
1037 ea_list, /* ea_list */
1039 &smb_action); /* psbuf */
1041 if (!NT_STATUS_IS_OK(status)) {
1042 if (open_was_deferred(req->mid)) {
1043 /* We have re-scheduled this call. */
1046 reply_openerror(req, status);
1050 size = get_file_size_stat(&smb_fname->st);
1051 fattr = dos_mode(conn, smb_fname);
1052 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1053 inode = smb_fname->st.st_ex_ino;
1055 close_file(req, fsp, ERROR_CLOSE);
1056 reply_doserror(req, ERRDOS,ERRnoaccess);
1060 /* Realloc the size of parameters and data we will return */
1061 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1062 if(*pparams == NULL ) {
1063 reply_nterror(req, NT_STATUS_NO_MEMORY);
1068 SSVAL(params,0,fsp->fnum);
1069 SSVAL(params,2,fattr);
1070 srv_put_dos_date2(params,4, mtime);
1071 SIVAL(params,8, (uint32)size);
1072 SSVAL(params,12,deny_mode);
1073 SSVAL(params,14,0); /* open_type - file or directory. */
1074 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1076 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1077 smb_action |= EXTENDED_OPLOCK_GRANTED;
1080 SSVAL(params,18,smb_action);
1083 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1085 SIVAL(params,20,inode);
1086 SSVAL(params,24,0); /* Padding. */
1088 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1089 SIVAL(params, 26, ea_size);
1091 SIVAL(params, 26, 0);
1094 /* Send the required number of replies */
1095 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1097 TALLOC_FREE(smb_fname);
1100 /*********************************************************
1101 Routine to check if a given string matches exactly.
1102 as a special case a mask of "." does NOT match. That
1103 is required for correct wildcard semantics
1104 Case can be significant or not.
1105 **********************************************************/
1107 static bool exact_match(connection_struct *conn,
1111 if (mask[0] == '.' && mask[1] == 0)
1113 if (dptr_has_wild(conn->dirptr)) {
1116 if (conn->case_sensitive)
1117 return strcmp(str,mask)==0;
1119 return StrCaseCmp(str,mask) == 0;
1122 /****************************************************************************
1123 Return the filetype for UNIX extensions.
1124 ****************************************************************************/
1126 static uint32 unix_filetype(mode_t mode)
1129 return UNIX_TYPE_FILE;
1130 else if(S_ISDIR(mode))
1131 return UNIX_TYPE_DIR;
1133 else if(S_ISLNK(mode))
1134 return UNIX_TYPE_SYMLINK;
1137 else if(S_ISCHR(mode))
1138 return UNIX_TYPE_CHARDEV;
1141 else if(S_ISBLK(mode))
1142 return UNIX_TYPE_BLKDEV;
1145 else if(S_ISFIFO(mode))
1146 return UNIX_TYPE_FIFO;
1149 else if(S_ISSOCK(mode))
1150 return UNIX_TYPE_SOCKET;
1153 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1154 return UNIX_TYPE_UNKNOWN;
1157 /****************************************************************************
1158 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1159 ****************************************************************************/
1161 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1163 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1164 const SMB_STRUCT_STAT *psbuf,
1166 enum perm_type ptype,
1171 if (perms == SMB_MODE_NO_CHANGE) {
1172 if (!VALID_STAT(*psbuf)) {
1173 return NT_STATUS_INVALID_PARAMETER;
1175 *ret_perms = psbuf->st_ex_mode;
1176 return NT_STATUS_OK;
1180 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1181 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1182 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1183 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1184 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1185 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1186 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1187 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1188 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1190 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1193 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1196 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1201 /* Apply mode mask */
1202 ret &= lp_create_mask(SNUM(conn));
1203 /* Add in force bits */
1204 ret |= lp_force_create_mode(SNUM(conn));
1207 ret &= lp_dir_mask(SNUM(conn));
1208 /* Add in force bits */
1209 ret |= lp_force_dir_mode(SNUM(conn));
1211 case PERM_EXISTING_FILE:
1212 /* Apply mode mask */
1213 ret &= lp_security_mask(SNUM(conn));
1214 /* Add in force bits */
1215 ret |= lp_force_security_mode(SNUM(conn));
1217 case PERM_EXISTING_DIR:
1218 /* Apply mode mask */
1219 ret &= lp_dir_security_mask(SNUM(conn));
1220 /* Add in force bits */
1221 ret |= lp_force_dir_security_mode(SNUM(conn));
1226 return NT_STATUS_OK;
1229 /****************************************************************************
1230 Needed to show the msdfs symlinks as directories. Modifies psbuf
1231 to be a directory if it's a msdfs link.
1232 ****************************************************************************/
1234 static bool check_msdfs_link(connection_struct *conn,
1235 const char *pathname,
1236 SMB_STRUCT_STAT *psbuf)
1238 int saved_errno = errno;
1239 if(lp_host_msdfs() &&
1240 lp_msdfs_root(SNUM(conn)) &&
1241 is_msdfs_link(conn, pathname, psbuf)) {
1243 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1246 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1247 errno = saved_errno;
1250 errno = saved_errno;
1255 /****************************************************************************
1256 Get a level dependent lanman2 dir entry.
1257 ****************************************************************************/
1259 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1260 connection_struct *conn,
1262 const char *path_mask,
1265 int requires_resume_key,
1271 int space_remaining,
1273 bool *got_exact_match,
1274 int *last_entry_off,
1275 struct ea_list *name_list)
1279 SMB_STRUCT_STAT sbuf;
1280 const char *mask = NULL;
1281 char *pathreal = NULL;
1283 char *p, *q, *pdata = *ppdata;
1287 SMB_OFF_T file_size = 0;
1288 uint64_t allocation_size = 0;
1290 struct timespec mdate_ts, adate_ts, create_date_ts;
1291 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1293 char *last_entry_ptr;
1295 uint32 nt_extmode; /* Used for NT connections instead of mode */
1296 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1297 bool check_mangled_names = lp_manglednames(conn->params);
1298 char mangled_name[13]; /* mangled 8.3 name. */
1300 *out_of_space = False;
1301 *got_exact_match = False;
1303 ZERO_STRUCT(mdate_ts);
1304 ZERO_STRUCT(adate_ts);
1305 ZERO_STRUCT(create_date_ts);
1307 if (!conn->dirptr) {
1311 p = strrchr_m(path_mask,'/');
1314 mask = talloc_strdup(ctx,"*.*");
1324 bool ms_dfs_link = False;
1326 /* Needed if we run out of space */
1327 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1328 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1331 * Due to bugs in NT client redirectors we are not using
1332 * resume keys any more - set them to zero.
1333 * Check out the related comments in findfirst/findnext.
1339 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1340 (long)conn->dirptr,curr_dirpos));
1347 * fname may get mangled, dname is never mangled.
1348 * Whenever we're accessing the filesystem we use
1349 * pathreal which is composed from dname.
1355 /* Mangle fname if it's an illegal name. */
1356 if (mangle_must_mangle(dname,conn->params)) {
1357 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1359 continue; /* Error - couldn't mangle. */
1361 fname = talloc_strdup(ctx, mangled_name);
1367 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1368 got_match = mask_match(fname, mask, conn->case_sensitive);
1371 if(!got_match && check_mangled_names &&
1372 !mangle_is_8_3(fname, False, conn->params)) {
1374 * It turns out that NT matches wildcards against
1375 * both long *and* short names. This may explain some
1376 * of the wildcard wierdness from old DOS clients
1377 * that some people have been seeing.... JRA.
1379 /* Force the mangling into 8.3. */
1380 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1382 continue; /* Error - couldn't mangle. */
1385 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1386 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1391 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1392 struct smb_filename *smb_fname = NULL;
1395 if (dont_descend && !isdots) {
1402 pathreal = talloc_asprintf(ctx,
1407 pathreal = talloc_asprintf(ctx,
1418 /* A dirent from dptr_ReadDirName isn't a stream. */
1419 status = create_synthetic_smb_fname(ctx, pathreal,
1422 if (!NT_STATUS_IS_OK(status)) {
1426 if (INFO_LEVEL_IS_UNIX(info_level)) {
1427 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
1428 DEBUG(5,("get_lanman2_dir_entry: "
1429 "Couldn't lstat [%s] (%s)\n",
1430 smb_fname_str_dbg(smb_fname),
1432 TALLOC_FREE(smb_fname);
1433 TALLOC_FREE(pathreal);
1437 } else if (!VALID_STAT(smb_fname->st) &&
1438 SMB_VFS_STAT(conn, smb_fname) != 0) {
1439 /* Needed to show the msdfs symlinks as
1443 check_msdfs_link(conn,
1444 smb_fname->base_name,
1447 DEBUG(5,("get_lanman2_dir_entry: "
1448 "Couldn't stat [%s] (%s)\n",
1449 smb_fname_str_dbg(smb_fname),
1451 TALLOC_FREE(smb_fname);
1452 TALLOC_FREE(pathreal);
1459 mode = dos_mode_msdfs(conn, smb_fname);
1461 mode = dos_mode(conn, smb_fname);
1464 if (!dir_check_ftype(conn,mode,dirtype)) {
1465 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1466 TALLOC_FREE(smb_fname);
1467 TALLOC_FREE(pathreal);
1472 if (!(mode & aDIR)) {
1473 file_size = get_file_size_stat(&smb_fname->st);
1476 SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1478 if (ask_sharemode) {
1479 struct timespec write_time_ts;
1480 struct file_id fileid;
1482 ZERO_STRUCT(write_time_ts);
1483 fileid = vfs_file_id_from_sbuf(conn,
1485 get_file_infos(fileid, NULL, &write_time_ts);
1486 if (!null_timespec(write_time_ts)) {
1487 update_stat_ex_mtime(&smb_fname->st,
1492 mdate_ts = smb_fname->st.st_ex_mtime;
1493 adate_ts = smb_fname->st.st_ex_atime;
1494 create_date_ts = smb_fname->st.st_ex_btime;
1496 if (lp_dos_filetime_resolution(SNUM(conn))) {
1497 dos_filetime_timespec(&create_date_ts);
1498 dos_filetime_timespec(&mdate_ts);
1499 dos_filetime_timespec(&adate_ts);
1502 create_date = convert_timespec_to_time_t(create_date_ts);
1503 mdate = convert_timespec_to_time_t(mdate_ts);
1504 adate = convert_timespec_to_time_t(adate_ts);
1506 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1507 smb_fname_str_dbg(smb_fname), fname));
1511 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1512 sbuf = smb_fname->st;
1514 TALLOC_FREE(smb_fname);
1524 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1526 switch (info_level) {
1527 case SMB_FIND_INFO_STANDARD:
1528 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1529 if(requires_resume_key) {
1533 srv_put_dos_date2(p,0,create_date);
1534 srv_put_dos_date2(p,4,adate);
1535 srv_put_dos_date2(p,8,mdate);
1536 SIVAL(p,12,(uint32)file_size);
1537 SIVAL(p,16,(uint32)allocation_size);
1541 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1542 p += ucs2_align(base_data, p, 0);
1544 len = srvstr_push(base_data, flags2, p,
1545 fname, PTR_DIFF(end_data, p),
1547 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1549 SCVAL(nameptr, -1, len - 2);
1551 SCVAL(nameptr, -1, 0);
1555 SCVAL(nameptr, -1, len - 1);
1557 SCVAL(nameptr, -1, 0);
1563 case SMB_FIND_EA_SIZE:
1564 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1565 if(requires_resume_key) {
1569 srv_put_dos_date2(p,0,create_date);
1570 srv_put_dos_date2(p,4,adate);
1571 srv_put_dos_date2(p,8,mdate);
1572 SIVAL(p,12,(uint32)file_size);
1573 SIVAL(p,16,(uint32)allocation_size);
1576 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1577 SIVAL(p,22,ea_size); /* Extended attributes */
1581 len = srvstr_push(base_data, flags2,
1582 p, fname, PTR_DIFF(end_data, p),
1583 STR_TERMINATE | STR_NOALIGN);
1584 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1597 SCVAL(nameptr,0,len);
1599 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1602 case SMB_FIND_EA_LIST:
1604 struct ea_list *file_list = NULL;
1607 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1611 if(requires_resume_key) {
1615 srv_put_dos_date2(p,0,create_date);
1616 srv_put_dos_date2(p,4,adate);
1617 srv_put_dos_date2(p,8,mdate);
1618 SIVAL(p,12,(uint32)file_size);
1619 SIVAL(p,16,(uint32)allocation_size);
1621 p += 22; /* p now points to the EA area. */
1623 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1624 name_list = ea_list_union(name_list, file_list, &ea_len);
1626 /* We need to determine if this entry will fit in the space available. */
1627 /* Max string size is 255 bytes. */
1628 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1629 /* Move the dirptr back to prev_dirpos */
1630 dptr_SeekDir(conn->dirptr, prev_dirpos);
1631 *out_of_space = True;
1632 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1633 return False; /* Not finished - just out of space */
1636 /* Push the ea_data followed by the name. */
1637 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1639 len = srvstr_push(base_data, flags2,
1640 p + 1, fname, PTR_DIFF(end_data, p+1),
1641 STR_TERMINATE | STR_NOALIGN);
1642 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1655 SCVAL(nameptr,0,len);
1657 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1661 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1662 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1663 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1665 SIVAL(p,0,reskey); p += 4;
1666 put_long_date_timespec(p,create_date_ts); p += 8;
1667 put_long_date_timespec(p,adate_ts); p += 8;
1668 put_long_date_timespec(p,mdate_ts); p += 8;
1669 put_long_date_timespec(p,mdate_ts); p += 8;
1670 SOFF_T(p,0,file_size); p += 8;
1671 SOFF_T(p,0,allocation_size); p += 8;
1672 SIVAL(p,0,nt_extmode); p += 4;
1673 q = p; p += 4; /* q is placeholder for name length. */
1675 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1676 SIVAL(p,0,ea_size); /* Extended attributes */
1679 /* Clear the short name buffer. This is
1680 * IMPORTANT as not doing so will trigger
1681 * a Win2k client bug. JRA.
1683 if (!was_8_3 && check_mangled_names) {
1684 if (!name_to_8_3(fname,mangled_name,True,
1686 /* Error - mangle failed ! */
1687 memset(mangled_name,'\0',12);
1689 mangled_name[12] = 0;
1690 len = srvstr_push(base_data, flags2,
1691 p+2, mangled_name, 24,
1692 STR_UPPER|STR_UNICODE);
1694 memset(p + 2 + len,'\0',24 - len);
1701 len = srvstr_push(base_data, flags2, p,
1702 fname, PTR_DIFF(end_data, p),
1703 STR_TERMINATE_ASCII);
1706 SIVAL(p,0,0); /* Ensure any padding is null. */
1707 len = PTR_DIFF(p, pdata);
1708 len = (len + 3) & ~3;
1713 case SMB_FIND_FILE_DIRECTORY_INFO:
1714 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1716 SIVAL(p,0,reskey); p += 4;
1717 put_long_date_timespec(p,create_date_ts); p += 8;
1718 put_long_date_timespec(p,adate_ts); p += 8;
1719 put_long_date_timespec(p,mdate_ts); p += 8;
1720 put_long_date_timespec(p,mdate_ts); p += 8;
1721 SOFF_T(p,0,file_size); p += 8;
1722 SOFF_T(p,0,allocation_size); p += 8;
1723 SIVAL(p,0,nt_extmode); p += 4;
1724 len = srvstr_push(base_data, flags2,
1725 p + 4, fname, PTR_DIFF(end_data, p+4),
1726 STR_TERMINATE_ASCII);
1729 SIVAL(p,0,0); /* Ensure any padding is null. */
1730 len = PTR_DIFF(p, pdata);
1731 len = (len + 3) & ~3;
1736 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1737 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1739 SIVAL(p,0,reskey); p += 4;
1740 put_long_date_timespec(p,create_date_ts); p += 8;
1741 put_long_date_timespec(p,adate_ts); p += 8;
1742 put_long_date_timespec(p,mdate_ts); p += 8;
1743 put_long_date_timespec(p,mdate_ts); p += 8;
1744 SOFF_T(p,0,file_size); p += 8;
1745 SOFF_T(p,0,allocation_size); p += 8;
1746 SIVAL(p,0,nt_extmode); p += 4;
1747 q = p; p += 4; /* q is placeholder for name length. */
1749 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1750 SIVAL(p,0,ea_size); /* Extended attributes */
1753 len = srvstr_push(base_data, flags2, p,
1754 fname, PTR_DIFF(end_data, p),
1755 STR_TERMINATE_ASCII);
1759 SIVAL(p,0,0); /* Ensure any padding is null. */
1760 len = PTR_DIFF(p, pdata);
1761 len = (len + 3) & ~3;
1766 case SMB_FIND_FILE_NAMES_INFO:
1767 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1769 SIVAL(p,0,reskey); p += 4;
1771 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1772 acl on a dir (tridge) */
1773 len = srvstr_push(base_data, flags2, p,
1774 fname, PTR_DIFF(end_data, p),
1775 STR_TERMINATE_ASCII);
1778 SIVAL(p,0,0); /* Ensure any padding is null. */
1779 len = PTR_DIFF(p, pdata);
1780 len = (len + 3) & ~3;
1785 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1786 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1788 SIVAL(p,0,reskey); p += 4;
1789 put_long_date_timespec(p,create_date_ts); p += 8;
1790 put_long_date_timespec(p,adate_ts); p += 8;
1791 put_long_date_timespec(p,mdate_ts); p += 8;
1792 put_long_date_timespec(p,mdate_ts); p += 8;
1793 SOFF_T(p,0,file_size); p += 8;
1794 SOFF_T(p,0,allocation_size); p += 8;
1795 SIVAL(p,0,nt_extmode); p += 4;
1796 q = p; p += 4; /* q is placeholder for name length. */
1798 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1799 SIVAL(p,0,ea_size); /* Extended attributes */
1802 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1803 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1804 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1805 len = srvstr_push(base_data, flags2, p,
1806 fname, PTR_DIFF(end_data, p),
1807 STR_TERMINATE_ASCII);
1810 SIVAL(p,0,0); /* Ensure any padding is null. */
1811 len = PTR_DIFF(p, pdata);
1812 len = (len + 3) & ~3;
1817 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1819 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1821 SIVAL(p,0,reskey); p += 4;
1822 put_long_date_timespec(p,create_date_ts); p += 8;
1823 put_long_date_timespec(p,adate_ts); p += 8;
1824 put_long_date_timespec(p,mdate_ts); p += 8;
1825 put_long_date_timespec(p,mdate_ts); p += 8;
1826 SOFF_T(p,0,file_size); p += 8;
1827 SOFF_T(p,0,allocation_size); p += 8;
1828 SIVAL(p,0,nt_extmode); p += 4;
1829 q = p; p += 4; /* q is placeholder for name length */
1831 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1832 SIVAL(p,0,ea_size); /* Extended attributes */
1835 /* Clear the short name buffer. This is
1836 * IMPORTANT as not doing so will trigger
1837 * a Win2k client bug. JRA.
1839 if (!was_8_3 && check_mangled_names) {
1840 if (!name_to_8_3(fname,mangled_name,True,
1842 /* Error - mangle failed ! */
1843 memset(mangled_name,'\0',12);
1845 mangled_name[12] = 0;
1846 len = srvstr_push(base_data, flags2,
1847 p+2, mangled_name, 24,
1848 STR_UPPER|STR_UNICODE);
1851 memset(p + 2 + len,'\0',24 - len);
1858 SSVAL(p,0,0); p += 2; /* Reserved ? */
1859 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1860 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1861 len = srvstr_push(base_data, flags2, p,
1862 fname, PTR_DIFF(end_data, p),
1863 STR_TERMINATE_ASCII);
1866 SIVAL(p,0,0); /* Ensure any padding is null. */
1867 len = PTR_DIFF(p, pdata);
1868 len = (len + 3) & ~3;
1873 /* CIFS UNIX Extension. */
1875 case SMB_FIND_FILE_UNIX:
1876 case SMB_FIND_FILE_UNIX_INFO2:
1878 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1880 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1882 if (info_level == SMB_FIND_FILE_UNIX) {
1883 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1884 p = store_file_unix_basic(conn, p,
1886 len = srvstr_push(base_data, flags2, p,
1887 fname, PTR_DIFF(end_data, p),
1890 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1891 p = store_file_unix_basic_info2(conn, p,
1895 len = srvstr_push(base_data, flags2, p, fname,
1896 PTR_DIFF(end_data, p), 0);
1897 SIVAL(nameptr, 0, len);
1901 SIVAL(p,0,0); /* Ensure any padding is null. */
1903 len = PTR_DIFF(p, pdata);
1904 len = (len + 3) & ~3;
1905 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1907 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1917 if (PTR_DIFF(p,pdata) > space_remaining) {
1918 /* Move the dirptr back to prev_dirpos */
1919 dptr_SeekDir(conn->dirptr, prev_dirpos);
1920 *out_of_space = True;
1921 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1922 return False; /* Not finished - just out of space */
1925 /* Setup the last entry pointer, as an offset from base_data */
1926 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1927 /* Advance the data pointer to the next slot */
1933 /****************************************************************************
1934 Reply to a TRANS2_FINDFIRST.
1935 ****************************************************************************/
1937 static void call_trans2findfirst(connection_struct *conn,
1938 struct smb_request *req,
1939 char **pparams, int total_params,
1940 char **ppdata, int total_data,
1941 unsigned int max_data_bytes)
1943 /* We must be careful here that we don't return more than the
1944 allowed number of data bytes. If this means returning fewer than
1945 maxentries then so be it. We assume that the redirector has
1946 enough room for the fixed number of parameter bytes it has
1948 struct smb_filename *smb_dname = NULL;
1949 char *params = *pparams;
1950 char *pdata = *ppdata;
1954 uint16 findfirst_flags;
1955 bool close_after_first;
1957 bool requires_resume_key;
1959 char *directory = NULL;
1962 int last_entry_off=0;
1966 bool finished = False;
1967 bool dont_descend = False;
1968 bool out_of_space = False;
1969 int space_remaining;
1970 bool mask_contains_wcard = False;
1971 struct ea_list *ea_list = NULL;
1972 NTSTATUS ntstatus = NT_STATUS_OK;
1973 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1974 TALLOC_CTX *ctx = talloc_tos();
1976 if (total_params < 13) {
1977 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1981 dirtype = SVAL(params,0);
1982 maxentries = SVAL(params,2);
1983 findfirst_flags = SVAL(params,4);
1984 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1985 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1986 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1987 info_level = SVAL(params,6);
1989 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1990 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1991 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1992 info_level, max_data_bytes));
1995 /* W2K3 seems to treat zero as 1. */
1999 switch (info_level) {
2000 case SMB_FIND_INFO_STANDARD:
2001 case SMB_FIND_EA_SIZE:
2002 case SMB_FIND_EA_LIST:
2003 case SMB_FIND_FILE_DIRECTORY_INFO:
2004 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2005 case SMB_FIND_FILE_NAMES_INFO:
2006 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2007 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2008 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2010 case SMB_FIND_FILE_UNIX:
2011 case SMB_FIND_FILE_UNIX_INFO2:
2012 /* Always use filesystem for UNIX mtime query. */
2013 ask_sharemode = false;
2014 if (!lp_unix_extensions()) {
2015 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2020 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2024 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2025 params+12, total_params - 12,
2026 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2027 if (!NT_STATUS_IS_OK(ntstatus)) {
2028 reply_nterror(req, ntstatus);
2032 ntstatus = resolve_dfspath_wcard(ctx, conn,
2033 req->flags2 & FLAGS2_DFS_PATHNAMES,
2036 &mask_contains_wcard);
2037 if (!NT_STATUS_IS_OK(ntstatus)) {
2038 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2039 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2040 ERRSRV, ERRbadpath);
2043 reply_nterror(req, ntstatus);
2047 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2048 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2049 if (!NT_STATUS_IS_OK(ntstatus)) {
2050 reply_nterror(req, ntstatus);
2054 mask = smb_dname->original_lcomp;
2056 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2057 TALLOC_FREE(smb_dname);
2058 if (!NT_STATUS_IS_OK(ntstatus)) {
2059 reply_nterror(req, ntstatus);
2063 ntstatus = check_name(conn, directory);
2064 if (!NT_STATUS_IS_OK(ntstatus)) {
2065 reply_nterror(req, ntstatus);
2069 p = strrchr_m(directory,'/');
2071 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2072 if((directory[0] == '.') && (directory[1] == '\0')) {
2073 mask = talloc_strdup(ctx,"*");
2075 reply_nterror(req, NT_STATUS_NO_MEMORY);
2078 mask_contains_wcard = True;
2080 directory = talloc_strdup(talloc_tos(), "./");
2082 reply_nterror(req, NT_STATUS_NO_MEMORY);
2089 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2091 if (info_level == SMB_FIND_EA_LIST) {
2094 if (total_data < 4) {
2095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2099 ea_size = IVAL(pdata,0);
2100 if (ea_size != total_data) {
2101 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2102 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2103 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2107 if (!lp_ea_support(SNUM(conn))) {
2108 reply_doserror(req, ERRDOS, ERReasnotsupported);
2112 /* Pull out the list of names. */
2113 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2120 *ppdata = (char *)SMB_REALLOC(
2121 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2122 if(*ppdata == NULL ) {
2123 reply_nterror(req, NT_STATUS_NO_MEMORY);
2127 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2129 /* Realloc the params space */
2130 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2131 if (*pparams == NULL) {
2132 reply_nterror(req, NT_STATUS_NO_MEMORY);
2137 /* Save the wildcard match and attribs we are using on this directory -
2138 needed as lanman2 assumes these are being saved between calls */
2140 ntstatus = dptr_create(conn,
2146 mask_contains_wcard,
2150 if (!NT_STATUS_IS_OK(ntstatus)) {
2151 reply_nterror(req, ntstatus);
2155 dptr_num = dptr_dnum(conn->dirptr);
2156 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2158 /* Initialize per TRANS2_FIND_FIRST operation data */
2159 dptr_init_search_op(conn->dirptr);
2161 /* We don't need to check for VOL here as this is returned by
2162 a different TRANS2 call. */
2164 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2165 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2166 dont_descend = True;
2169 space_remaining = max_data_bytes;
2170 out_of_space = False;
2172 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2173 bool got_exact_match = False;
2175 /* this is a heuristic to avoid seeking the dirptr except when
2176 absolutely necessary. It allows for a filename of about 40 chars */
2177 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2178 out_of_space = True;
2181 finished = !get_lanman2_dir_entry(ctx,
2184 mask,dirtype,info_level,
2185 requires_resume_key,dont_descend,
2188 space_remaining, &out_of_space,
2190 &last_entry_off, ea_list);
2193 if (finished && out_of_space)
2196 if (!finished && !out_of_space)
2200 * As an optimisation if we know we aren't looking
2201 * for a wildcard name (ie. the name matches the wildcard exactly)
2202 * then we can finish on any (first) match.
2203 * This speeds up large directory searches. JRA.
2209 /* Ensure space_remaining never goes -ve. */
2210 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2211 space_remaining = 0;
2212 out_of_space = true;
2214 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2218 /* Check if we can close the dirptr */
2219 if(close_after_first || (finished && close_if_end)) {
2220 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2221 dptr_close(&dptr_num);
2225 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2226 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2227 * the protocol level is less than NT1. Tested with smbclient. JRA.
2228 * This should fix the OS/2 client bug #2335.
2231 if(numentries == 0) {
2232 dptr_close(&dptr_num);
2233 if (Protocol < PROTOCOL_NT1) {
2234 reply_doserror(req, ERRDOS, ERRnofiles);
2237 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2238 ERRDOS, ERRbadfile);
2243 /* At this point pdata points to numentries directory entries. */
2245 /* Set up the return parameter block */
2246 SSVAL(params,0,dptr_num);
2247 SSVAL(params,2,numentries);
2248 SSVAL(params,4,finished);
2249 SSVAL(params,6,0); /* Never an EA error */
2250 SSVAL(params,8,last_entry_off);
2252 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2255 if ((! *directory) && dptr_path(dptr_num)) {
2256 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2258 reply_nterror(req, NT_STATUS_NO_MEMORY);
2262 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2263 smb_fn_name(req->cmd),
2264 mask, directory, dirtype, numentries ) );
2267 * Force a name mangle here to ensure that the
2268 * mask as an 8.3 name is top of the mangled cache.
2269 * The reasons for this are subtle. Don't remove
2270 * this code unless you know what you are doing
2271 * (see PR#13758). JRA.
2274 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2275 char mangled_name[13];
2276 name_to_8_3(mask, mangled_name, True, conn->params);
2282 /****************************************************************************
2283 Reply to a TRANS2_FINDNEXT.
2284 ****************************************************************************/
2286 static void call_trans2findnext(connection_struct *conn,
2287 struct smb_request *req,
2288 char **pparams, int total_params,
2289 char **ppdata, int total_data,
2290 unsigned int max_data_bytes)
2292 /* We must be careful here that we don't return more than the
2293 allowed number of data bytes. If this means returning fewer than
2294 maxentries then so be it. We assume that the redirector has
2295 enough room for the fixed number of parameter bytes it has
2297 char *params = *pparams;
2298 char *pdata = *ppdata;
2304 uint16 findnext_flags;
2305 bool close_after_request;
2307 bool requires_resume_key;
2309 bool mask_contains_wcard = False;
2310 char *resume_name = NULL;
2311 const char *mask = NULL;
2312 const char *directory = NULL;
2316 int i, last_entry_off=0;
2317 bool finished = False;
2318 bool dont_descend = False;
2319 bool out_of_space = False;
2320 int space_remaining;
2321 struct ea_list *ea_list = NULL;
2322 NTSTATUS ntstatus = NT_STATUS_OK;
2323 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2324 TALLOC_CTX *ctx = talloc_tos();
2326 if (total_params < 13) {
2327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2331 dptr_num = SVAL(params,0);
2332 maxentries = SVAL(params,2);
2333 info_level = SVAL(params,4);
2334 resume_key = IVAL(params,6);
2335 findnext_flags = SVAL(params,10);
2336 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2337 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2338 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2339 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2341 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2343 total_params - 12, STR_TERMINATE, &ntstatus,
2344 &mask_contains_wcard);
2345 if (!NT_STATUS_IS_OK(ntstatus)) {
2346 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2347 complain (it thinks we're asking for the directory above the shared
2348 path or an invalid name). Catch this as the resume name is only compared, never used in
2349 a file access. JRA. */
2350 srvstr_pull_talloc(ctx, params, req->flags2,
2351 &resume_name, params+12,
2355 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2356 reply_nterror(req, ntstatus);
2361 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2362 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2363 resume_key = %d resume name = %s continue=%d level = %d\n",
2364 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2365 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2368 /* W2K3 seems to treat zero as 1. */
2372 switch (info_level) {
2373 case SMB_FIND_INFO_STANDARD:
2374 case SMB_FIND_EA_SIZE:
2375 case SMB_FIND_EA_LIST:
2376 case SMB_FIND_FILE_DIRECTORY_INFO:
2377 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2378 case SMB_FIND_FILE_NAMES_INFO:
2379 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2380 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2381 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2383 case SMB_FIND_FILE_UNIX:
2384 case SMB_FIND_FILE_UNIX_INFO2:
2385 /* Always use filesystem for UNIX mtime query. */
2386 ask_sharemode = false;
2387 if (!lp_unix_extensions()) {
2388 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2393 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2397 if (info_level == SMB_FIND_EA_LIST) {
2400 if (total_data < 4) {
2401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2405 ea_size = IVAL(pdata,0);
2406 if (ea_size != total_data) {
2407 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2408 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2413 if (!lp_ea_support(SNUM(conn))) {
2414 reply_doserror(req, ERRDOS, ERReasnotsupported);
2418 /* Pull out the list of names. */
2419 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2421 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2426 *ppdata = (char *)SMB_REALLOC(
2427 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2428 if(*ppdata == NULL) {
2429 reply_nterror(req, NT_STATUS_NO_MEMORY);
2434 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2436 /* Realloc the params space */
2437 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2438 if(*pparams == NULL ) {
2439 reply_nterror(req, NT_STATUS_NO_MEMORY);
2445 /* Check that the dptr is valid */
2446 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2447 reply_doserror(req, ERRDOS, ERRnofiles);
2451 string_set(&conn->dirpath,dptr_path(dptr_num));
2453 /* Get the wildcard mask from the dptr */
2454 if((p = dptr_wcard(dptr_num))== NULL) {
2455 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2456 reply_doserror(req, ERRDOS, ERRnofiles);
2461 directory = conn->dirpath;
2463 /* Get the attr mask from the dptr */
2464 dirtype = dptr_attr(dptr_num);
2466 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2467 dptr_num, mask, dirtype,
2469 dptr_TellDir(conn->dirptr)));
2471 /* Initialize per TRANS2_FIND_NEXT operation data */
2472 dptr_init_search_op(conn->dirptr);
2474 /* We don't need to check for VOL here as this is returned by
2475 a different TRANS2 call. */
2477 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2478 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2479 dont_descend = True;
2482 space_remaining = max_data_bytes;
2483 out_of_space = False;
2486 * Seek to the correct position. We no longer use the resume key but
2487 * depend on the last file name instead.
2490 if(*resume_name && !continue_bit) {
2493 long current_pos = 0;
2495 * Remember, name_to_8_3 is called by
2496 * get_lanman2_dir_entry(), so the resume name
2497 * could be mangled. Ensure we check the unmangled name.
2500 if (mangle_is_mangled(resume_name, conn->params)) {
2501 char *new_resume_name = NULL;
2502 mangle_lookup_name_from_8_3(ctx,
2506 if (new_resume_name) {
2507 resume_name = new_resume_name;
2512 * Fix for NT redirector problem triggered by resume key indexes
2513 * changing between directory scans. We now return a resume key of 0
2514 * and instead look for the filename to continue from (also given
2515 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2516 * findfirst/findnext (as is usual) then the directory pointer
2517 * should already be at the correct place.
2520 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2521 } /* end if resume_name && !continue_bit */
2523 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2524 bool got_exact_match = False;
2526 /* this is a heuristic to avoid seeking the dirptr except when
2527 absolutely necessary. It allows for a filename of about 40 chars */
2528 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2529 out_of_space = True;
2532 finished = !get_lanman2_dir_entry(ctx,
2535 mask,dirtype,info_level,
2536 requires_resume_key,dont_descend,
2539 space_remaining, &out_of_space,
2541 &last_entry_off, ea_list);
2544 if (finished && out_of_space)
2547 if (!finished && !out_of_space)
2551 * As an optimisation if we know we aren't looking
2552 * for a wildcard name (ie. the name matches the wildcard exactly)
2553 * then we can finish on any (first) match.
2554 * This speeds up large directory searches. JRA.
2560 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2563 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2564 smb_fn_name(req->cmd),
2565 mask, directory, dirtype, numentries ) );
2567 /* Check if we can close the dirptr */
2568 if(close_after_request || (finished && close_if_end)) {
2569 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2570 dptr_close(&dptr_num); /* This frees up the saved mask */
2573 /* Set up the return parameter block */
2574 SSVAL(params,0,numentries);
2575 SSVAL(params,2,finished);
2576 SSVAL(params,4,0); /* Never an EA error */
2577 SSVAL(params,6,last_entry_off);
2579 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2585 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2587 E_md4hash(lp_servicename(SNUM(conn)),objid);
2591 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2593 SMB_ASSERT(extended_info != NULL);
2595 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2596 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2597 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2598 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2599 #ifdef SAMBA_VERSION_REVISION
2600 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2602 extended_info->samba_subversion = 0;
2603 #ifdef SAMBA_VERSION_RC_RELEASE
2604 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2606 #ifdef SAMBA_VERSION_PRE_RELEASE
2607 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2610 #ifdef SAMBA_VERSION_VENDOR_PATCH
2611 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2613 extended_info->samba_gitcommitdate = 0;
2614 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2615 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2618 memset(extended_info->samba_version_string, 0,
2619 sizeof(extended_info->samba_version_string));
2621 snprintf (extended_info->samba_version_string,
2622 sizeof(extended_info->samba_version_string),
2623 "%s", samba_version_string());
2626 /****************************************************************************
2627 Reply to a TRANS2_QFSINFO (query filesystem info).
2628 ****************************************************************************/
2630 static void call_trans2qfsinfo(connection_struct *conn,
2631 struct smb_request *req,
2632 char **pparams, int total_params,
2633 char **ppdata, int total_data,
2634 unsigned int max_data_bytes)
2636 char *pdata, *end_data;
2637 char *params = *pparams;
2641 const char *vname = volume_label(SNUM(conn));
2642 int snum = SNUM(conn);
2643 char *fstype = lp_fstype(SNUM(conn));
2644 uint32 additional_flags = 0;
2646 if (total_params < 2) {
2647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2651 info_level = SVAL(params,0);
2654 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2655 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2656 "info level (0x%x) on IPC$.\n",
2657 (unsigned int)info_level));
2658 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2663 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2664 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2665 DEBUG(0,("call_trans2qfsinfo: encryption required "
2666 "and info level 0x%x sent.\n",
2667 (unsigned int)info_level));
2668 exit_server_cleanly("encryption required "
2674 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2676 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
2677 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2678 reply_doserror(req, ERRSRV, ERRinvdevice);
2682 *ppdata = (char *)SMB_REALLOC(
2683 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2684 if (*ppdata == NULL ) {
2685 reply_nterror(req, NT_STATUS_NO_MEMORY);
2690 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2691 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2693 switch (info_level) {
2694 case SMB_INFO_ALLOCATION:
2696 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2698 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2699 reply_unixerror(req, ERRHRD, ERRgeneral);
2703 block_size = lp_block_size(snum);
2704 if (bsize < block_size) {
2705 uint64_t factor = block_size/bsize;
2710 if (bsize > block_size) {
2711 uint64_t factor = bsize/block_size;
2716 bytes_per_sector = 512;
2717 sectors_per_unit = bsize/bytes_per_sector;
2719 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2720 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2721 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2723 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2724 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2725 SIVAL(pdata,l1_cUnit,dsize);
2726 SIVAL(pdata,l1_cUnitAvail,dfree);
2727 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2731 case SMB_INFO_VOLUME:
2732 /* Return volume name */
2734 * Add volume serial number - hash of a combination of
2735 * the called hostname and the service name.
2737 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2739 * Win2k3 and previous mess this up by sending a name length
2740 * one byte short. I believe only older clients (OS/2 Win9x) use
2741 * this call so try fixing this by adding a terminating null to
2742 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2746 pdata+l2_vol_szVolLabel, vname,
2747 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2748 STR_NOALIGN|STR_TERMINATE);
2749 SCVAL(pdata,l2_vol_cch,len);
2750 data_len = l2_vol_szVolLabel + len;
2751 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2752 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2756 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2757 case SMB_FS_ATTRIBUTE_INFORMATION:
2759 additional_flags = 0;
2760 #if defined(HAVE_SYS_QUOTAS)
2761 additional_flags |= FILE_VOLUME_QUOTAS;
2764 if(lp_nt_acl_support(SNUM(conn))) {
2765 additional_flags |= FILE_PERSISTENT_ACLS;
2768 /* Capabilities are filled in at connection time through STATVFS call */
2769 additional_flags |= conn->fs_capabilities;
2771 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2772 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2773 additional_flags); /* FS ATTRIBUTES */
2775 SIVAL(pdata,4,255); /* Max filename component length */
2776 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2777 and will think we can't do long filenames */
2778 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2779 PTR_DIFF(end_data, pdata+12),
2782 data_len = 12 + len;
2785 case SMB_QUERY_FS_LABEL_INFO:
2786 case SMB_FS_LABEL_INFORMATION:
2787 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2788 PTR_DIFF(end_data, pdata+4), 0);
2793 case SMB_QUERY_FS_VOLUME_INFO:
2794 case SMB_FS_VOLUME_INFORMATION:
2797 * Add volume serial number - hash of a combination of
2798 * the called hostname and the service name.
2800 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2801 (str_checksum(get_local_machine_name())<<16));
2803 /* Max label len is 32 characters. */
2804 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2805 PTR_DIFF(end_data, pdata+18),
2807 SIVAL(pdata,12,len);
2810 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2811 (int)strlen(vname),vname, lp_servicename(snum)));
2814 case SMB_QUERY_FS_SIZE_INFO:
2815 case SMB_FS_SIZE_INFORMATION:
2817 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2819 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2820 reply_unixerror(req, ERRHRD, ERRgeneral);
2823 block_size = lp_block_size(snum);
2824 if (bsize < block_size) {
2825 uint64_t factor = block_size/bsize;
2830 if (bsize > block_size) {
2831 uint64_t factor = bsize/block_size;
2836 bytes_per_sector = 512;
2837 sectors_per_unit = bsize/bytes_per_sector;
2838 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2839 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2840 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2841 SBIG_UINT(pdata,0,dsize);
2842 SBIG_UINT(pdata,8,dfree);
2843 SIVAL(pdata,16,sectors_per_unit);
2844 SIVAL(pdata,20,bytes_per_sector);
2848 case SMB_FS_FULL_SIZE_INFORMATION:
2850 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2852 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2853 reply_unixerror(req, ERRHRD, ERRgeneral);
2856 block_size = lp_block_size(snum);
2857 if (bsize < block_size) {
2858 uint64_t factor = block_size/bsize;
2863 if (bsize > block_size) {
2864 uint64_t factor = bsize/block_size;
2869 bytes_per_sector = 512;
2870 sectors_per_unit = bsize/bytes_per_sector;
2871 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2872 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2873 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2874 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2875 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2876 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2877 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2878 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2882 case SMB_QUERY_FS_DEVICE_INFO:
2883 case SMB_FS_DEVICE_INFORMATION:
2885 SIVAL(pdata,0,0); /* dev type */
2886 SIVAL(pdata,4,0); /* characteristics */
2889 #ifdef HAVE_SYS_QUOTAS
2890 case SMB_FS_QUOTA_INFORMATION:
2892 * what we have to send --metze:
2894 * Unknown1: 24 NULL bytes
2895 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2896 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2897 * Quota Flags: 2 byte :
2898 * Unknown3: 6 NULL bytes
2902 * details for Quota Flags:
2904 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2905 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2906 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2907 * 0x0001 Enable Quotas: enable quota for this fs
2911 /* we need to fake up a fsp here,
2912 * because its not send in this call
2915 SMB_NTQUOTA_STRUCT quotas;
2918 ZERO_STRUCT(quotas);
2924 if (conn->server_info->utok.uid != 0) {
2925 DEBUG(0,("set_user_quota: access_denied "
2926 "service [%s] user [%s]\n",
2927 lp_servicename(SNUM(conn)),
2928 conn->server_info->unix_name));
2929 reply_doserror(req, ERRDOS, ERRnoaccess);
2933 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2934 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2935 reply_doserror(req, ERRSRV, ERRerror);
2941 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2943 /* Unknown1 24 NULL bytes*/
2944 SBIG_UINT(pdata,0,(uint64_t)0);
2945 SBIG_UINT(pdata,8,(uint64_t)0);
2946 SBIG_UINT(pdata,16,(uint64_t)0);
2948 /* Default Soft Quota 8 bytes */
2949 SBIG_UINT(pdata,24,quotas.softlim);
2951 /* Default Hard Quota 8 bytes */
2952 SBIG_UINT(pdata,32,quotas.hardlim);
2954 /* Quota flag 2 bytes */
2955 SSVAL(pdata,40,quotas.qflags);
2957 /* Unknown3 6 NULL bytes */
2963 #endif /* HAVE_SYS_QUOTAS */
2964 case SMB_FS_OBJECTID_INFORMATION:
2966 unsigned char objid[16];
2967 struct smb_extended_info extended_info;
2968 memcpy(pdata,create_volume_objectid(conn, objid),16);
2969 samba_extended_info_version (&extended_info);
2970 SIVAL(pdata,16,extended_info.samba_magic);
2971 SIVAL(pdata,20,extended_info.samba_version);
2972 SIVAL(pdata,24,extended_info.samba_subversion);
2973 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2974 memcpy(pdata+36,extended_info.samba_version_string,28);
2980 * Query the version and capabilities of the CIFS UNIX extensions
2984 case SMB_QUERY_CIFS_UNIX_INFO:
2986 bool large_write = lp_min_receive_file_size() &&
2987 !srv_is_signing_active(smbd_server_conn);
2988 bool large_read = !srv_is_signing_active(smbd_server_conn);
2989 int encrypt_caps = 0;
2991 if (!lp_unix_extensions()) {
2992 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2996 switch (conn->encrypt_level) {
3002 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3005 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3006 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3007 large_write = false;
3013 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3014 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3016 /* We have POSIX ACLs, pathname, encryption,
3017 * large read/write, and locking capability. */
3019 SBIG_UINT(pdata,4,((uint64_t)(
3020 CIFS_UNIX_POSIX_ACLS_CAP|
3021 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3022 CIFS_UNIX_FCNTL_LOCKS_CAP|
3023 CIFS_UNIX_EXTATTR_CAP|
3024 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3026 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3028 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3032 case SMB_QUERY_POSIX_FS_INFO:
3035 vfs_statvfs_struct svfs;
3037 if (!lp_unix_extensions()) {
3038 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3042 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3046 SIVAL(pdata,0,svfs.OptimalTransferSize);
3047 SIVAL(pdata,4,svfs.BlockSize);
3048 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3049 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3050 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3051 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3052 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3053 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3054 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3056 } else if (rc == EOPNOTSUPP) {
3057 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3059 #endif /* EOPNOTSUPP */
3061 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3062 reply_doserror(req, ERRSRV, ERRerror);
3068 case SMB_QUERY_POSIX_WHOAMI:
3074 if (!lp_unix_extensions()) {
3075 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3079 if (max_data_bytes < 40) {
3080 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3084 /* We ARE guest if global_sid_Builtin_Guests is
3085 * in our list of SIDs.
3087 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3088 conn->server_info->ptok)) {
3089 flags |= SMB_WHOAMI_GUEST;
3092 /* We are NOT guest if global_sid_Authenticated_Users
3093 * is in our list of SIDs.
3095 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3096 conn->server_info->ptok)) {
3097 flags &= ~SMB_WHOAMI_GUEST;
3100 /* NOTE: 8 bytes for UID/GID, irrespective of native
3101 * platform size. This matches
3102 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3104 data_len = 4 /* flags */
3111 + 4 /* pad/reserved */
3112 + (conn->server_info->utok.ngroups * 8)
3114 + (conn->server_info->ptok->num_sids *
3118 SIVAL(pdata, 0, flags);
3119 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3121 (uint64_t)conn->server_info->utok.uid);
3122 SBIG_UINT(pdata, 16,
3123 (uint64_t)conn->server_info->utok.gid);
3126 if (data_len >= max_data_bytes) {
3127 /* Potential overflow, skip the GIDs and SIDs. */
3129 SIVAL(pdata, 24, 0); /* num_groups */
3130 SIVAL(pdata, 28, 0); /* num_sids */
3131 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3132 SIVAL(pdata, 36, 0); /* reserved */
3138 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3139 SIVAL(pdata, 28, conn->server_info->num_sids);
3141 /* We walk the SID list twice, but this call is fairly
3142 * infrequent, and I don't expect that it's performance
3143 * sensitive -- jpeach
3145 for (i = 0, sid_bytes = 0;
3146 i < conn->server_info->ptok->num_sids; ++i) {
3147 sid_bytes += ndr_size_dom_sid(
3148 &conn->server_info->ptok->user_sids[i],
3153 /* SID list byte count */
3154 SIVAL(pdata, 32, sid_bytes);
3156 /* 4 bytes pad/reserved - must be zero */
3157 SIVAL(pdata, 36, 0);
3161 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3162 SBIG_UINT(pdata, data_len,
3163 (uint64_t)conn->server_info->utok.groups[i]);
3169 i < conn->server_info->ptok->num_sids; ++i) {
3170 int sid_len = ndr_size_dom_sid(
3171 &conn->server_info->ptok->user_sids[i],
3175 sid_linearize(pdata + data_len, sid_len,
3176 &conn->server_info->ptok->user_sids[i]);
3177 data_len += sid_len;
3183 case SMB_MAC_QUERY_FS_INFO:
3185 * Thursby MAC extension... ONLY on NTFS filesystems
3186 * once we do streams then we don't need this
3188 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3190 SIVAL(pdata,84,0x100); /* Don't support mac... */
3195 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3200 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3203 DEBUG( 4, ( "%s info_level = %d\n",
3204 smb_fn_name(req->cmd), info_level) );
3209 /****************************************************************************
3210 Reply to a TRANS2_SETFSINFO (set filesystem info).
3211 ****************************************************************************/
3213 static void call_trans2setfsinfo(connection_struct *conn,
3214 struct smb_request *req,
3215 char **pparams, int total_params,
3216 char **ppdata, int total_data,
3217 unsigned int max_data_bytes)
3219 char *pdata = *ppdata;
3220 char *params = *pparams;
3223 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3226 if (total_params < 4) {
3227 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3233 info_level = SVAL(params,2);
3236 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3237 info_level != SMB_SET_CIFS_UNIX_INFO) {
3238 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3239 "info level (0x%x) on IPC$.\n",
3240 (unsigned int)info_level));
3241 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3246 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3247 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3248 DEBUG(0,("call_trans2setfsinfo: encryption required "
3249 "and info level 0x%x sent.\n",
3250 (unsigned int)info_level));
3251 exit_server_cleanly("encryption required "
3257 switch(info_level) {
3258 case SMB_SET_CIFS_UNIX_INFO:
3260 uint16 client_unix_major;
3261 uint16 client_unix_minor;
3262 uint32 client_unix_cap_low;
3263 uint32 client_unix_cap_high;
3265 if (!lp_unix_extensions()) {
3267 NT_STATUS_INVALID_LEVEL);
3271 /* There should be 12 bytes of capabilities set. */
3272 if (total_data < 8) {
3275 NT_STATUS_INVALID_PARAMETER);
3278 client_unix_major = SVAL(pdata,0);
3279 client_unix_minor = SVAL(pdata,2);
3280 client_unix_cap_low = IVAL(pdata,4);
3281 client_unix_cap_high = IVAL(pdata,8);
3282 /* Just print these values for now. */
3283 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3284 cap_low = 0x%x, cap_high = 0x%x\n",
3285 (unsigned int)client_unix_major,
3286 (unsigned int)client_unix_minor,
3287 (unsigned int)client_unix_cap_low,
3288 (unsigned int)client_unix_cap_high ));
3290 /* Here is where we must switch to posix pathname processing... */
3291 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3292 lp_set_posix_pathnames();
3293 mangle_change_to_posix();
3296 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3297 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3298 /* Client that knows how to do posix locks,
3299 * but not posix open/mkdir operations. Set a
3300 * default type for read/write checks. */
3302 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3308 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3311 size_t param_len = 0;
3312 size_t data_len = total_data;
3314 if (!lp_unix_extensions()) {
3317 NT_STATUS_INVALID_LEVEL);
3321 if (lp_smb_encrypt(SNUM(conn)) == false) {
3324 NT_STATUS_NOT_SUPPORTED);
3328 DEBUG( 4,("call_trans2setfsinfo: "
3329 "request transport encryption.\n"));
3331 status = srv_request_encryption_setup(conn,
3332 (unsigned char **)ppdata,
3334 (unsigned char **)pparams,
3337 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3338 !NT_STATUS_IS_OK(status)) {
3339 reply_nterror(req, status);
3343 send_trans2_replies(conn, req,
3350 if (NT_STATUS_IS_OK(status)) {
3351 /* Server-side transport
3352 * encryption is now *on*. */
3353 status = srv_encryption_start(conn);
3354 if (!NT_STATUS_IS_OK(status)) {
3355 exit_server_cleanly(
3356 "Failure in setting "
3357 "up encrypted transport");
3363 case SMB_FS_QUOTA_INFORMATION:
3365 files_struct *fsp = NULL;
3366 SMB_NTQUOTA_STRUCT quotas;
3368 ZERO_STRUCT(quotas);
3371 if ((conn->server_info->utok.uid != 0)
3372 ||!CAN_WRITE(conn)) {
3373 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3374 lp_servicename(SNUM(conn)),
3375 conn->server_info->unix_name));
3376 reply_doserror(req, ERRSRV, ERRaccess);
3380 /* note: normaly there're 48 bytes,
3381 * but we didn't use the last 6 bytes for now
3384 fsp = file_fsp(req, SVAL(params,0));
3386 if (!check_fsp_ntquota_handle(conn, req,
3388 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3390 req, NT_STATUS_INVALID_HANDLE);
3394 if (total_data < 42) {
3395 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3399 NT_STATUS_INVALID_PARAMETER);
3403 /* unknown_1 24 NULL bytes in pdata*/
3405 /* the soft quotas 8 bytes (uint64_t)*/
3406 quotas.softlim = (uint64_t)IVAL(pdata,24);
3407 #ifdef LARGE_SMB_OFF_T
3408 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3409 #else /* LARGE_SMB_OFF_T */
3410 if ((IVAL(pdata,28) != 0)&&
3411 ((quotas.softlim != 0xFFFFFFFF)||
3412 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3413 /* more than 32 bits? */
3416 NT_STATUS_INVALID_PARAMETER);
3419 #endif /* LARGE_SMB_OFF_T */
3421 /* the hard quotas 8 bytes (uint64_t)*/
3422 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3423 #ifdef LARGE_SMB_OFF_T
3424 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3425 #else /* LARGE_SMB_OFF_T */
3426 if ((IVAL(pdata,36) != 0)&&
3427 ((quotas.hardlim != 0xFFFFFFFF)||
3428 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3429 /* more than 32 bits? */
3432 NT_STATUS_INVALID_PARAMETER);
3435 #endif /* LARGE_SMB_OFF_T */
3437 /* quota_flags 2 bytes **/
3438 quotas.qflags = SVAL(pdata,40);
3440 /* unknown_2 6 NULL bytes follow*/
3442 /* now set the quotas */
3443 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3444 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3445 reply_doserror(req, ERRSRV, ERRerror);
3452 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3454 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3460 * sending this reply works fine,
3461 * but I'm not sure it's the same
3462 * like windows do...
3465 reply_outbuf(req, 10, 0);
3468 #if defined(HAVE_POSIX_ACLS)
3469 /****************************************************************************
3470 Utility function to count the number of entries in a POSIX acl.
3471 ****************************************************************************/
3473 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3475 unsigned int ace_count = 0;
3476 int entry_id = SMB_ACL_FIRST_ENTRY;
3477 SMB_ACL_ENTRY_T entry;
3479 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3481 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3482 entry_id = SMB_ACL_NEXT_ENTRY;
3489 /****************************************************************************
3490 Utility function to marshall a POSIX acl into wire format.
3491 ****************************************************************************/
3493 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3495 int entry_id = SMB_ACL_FIRST_ENTRY;
3496 SMB_ACL_ENTRY_T entry;
3498 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3499 SMB_ACL_TAG_T tagtype;
3500 SMB_ACL_PERMSET_T permset;
3501 unsigned char perms = 0;
3502 unsigned int own_grp;
3505 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3506 entry_id = SMB_ACL_NEXT_ENTRY;
3509 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3510 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3514 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3515 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3519 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3520 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3521 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3523 SCVAL(pdata,1,perms);
3526 case SMB_ACL_USER_OBJ:
3527 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3528 own_grp = (unsigned int)pst->st_ex_uid;
3529 SIVAL(pdata,2,own_grp);
3534 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3536 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3539 own_grp = (unsigned int)*puid;
3540 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3541 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3542 SIVAL(pdata,2,own_grp);
3546 case SMB_ACL_GROUP_OBJ:
3547 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3548 own_grp = (unsigned int)pst->st_ex_gid;
3549 SIVAL(pdata,2,own_grp);
3554 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3556 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3559 own_grp = (unsigned int)*pgid;
3560 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3561 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3562 SIVAL(pdata,2,own_grp);
3567 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3568 SIVAL(pdata,2,0xFFFFFFFF);
3569 SIVAL(pdata,6,0xFFFFFFFF);
3572 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3573 SIVAL(pdata,2,0xFFFFFFFF);
3574 SIVAL(pdata,6,0xFFFFFFFF);
3577 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3580 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3587 /****************************************************************************
3588 Store the FILE_UNIX_BASIC info.
3589 ****************************************************************************/
3591 static char *store_file_unix_basic(connection_struct *conn,
3594 const SMB_STRUCT_STAT *psbuf)
3596 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3597 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3599 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3602 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3605 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3606 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3607 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3610 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3614 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3618 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3621 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3625 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3629 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3632 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3636 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3643 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3644 * the chflags(2) (or equivalent) flags.
3646 * XXX: this really should be behind the VFS interface. To do this, we would
3647 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3648 * Each VFS module could then implement its own mapping as appropriate for the
3649 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3651 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3655 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3659 { UF_IMMUTABLE, EXT_IMMUTABLE },
3663 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3667 { UF_HIDDEN, EXT_HIDDEN },
3670 /* Do not remove. We need to guarantee that this array has at least one
3671 * entry to build on HP-UX.
3677 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3678 uint32 *smb_fflags, uint32 *smb_fmask)
3682 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3683 *smb_fmask |= info2_flags_map[i].smb_fflag;
3684 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3685 *smb_fflags |= info2_flags_map[i].smb_fflag;
3690 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3691 const uint32 smb_fflags,
3692 const uint32 smb_fmask,
3695 uint32 max_fmask = 0;
3698 *stat_fflags = psbuf->st_ex_flags;
3700 /* For each flags requested in smb_fmask, check the state of the
3701 * corresponding flag in smb_fflags and set or clear the matching
3705 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3706 max_fmask |= info2_flags_map[i].smb_fflag;
3707 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3708 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3709 *stat_fflags |= info2_flags_map[i].stat_fflag;
3711 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3716 /* If smb_fmask is asking to set any bits that are not supported by
3717 * our flag mappings, we should fail.
3719 if ((smb_fmask & max_fmask) != smb_fmask) {
3727 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3728 * of file flags and birth (create) time.
3730 static char *store_file_unix_basic_info2(connection_struct *conn,
3733 const SMB_STRUCT_STAT *psbuf)
3735 uint32 file_flags = 0;
3736 uint32 flags_mask = 0;
3738 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3740 /* Create (birth) time 64 bit */
3741 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3744 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3745 SIVAL(pdata, 0, file_flags); /* flags */
3746 SIVAL(pdata, 4, flags_mask); /* mask */
3752 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3753 const struct stream_struct *streams,
3755 unsigned int max_data_bytes,
3756 unsigned int *data_size)
3759 unsigned int ofs = 0;
3761 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3762 unsigned int next_offset;
3764 smb_ucs2_t *namebuf;
3766 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3767 streams[i].name, &namelen) ||
3770 return NT_STATUS_INVALID_PARAMETER;
3774 * name_buf is now null-terminated, we need to marshall as not
3780 SIVAL(data, ofs+4, namelen);
3781 SOFF_T(data, ofs+8, streams[i].size);
3782 SOFF_T(data, ofs+16, streams[i].alloc_size);
3783 memcpy(data+ofs+24, namebuf, namelen);
3784 TALLOC_FREE(namebuf);
3786 next_offset = ofs + 24 + namelen;
3788 if (i == num_streams-1) {
3789 SIVAL(data, ofs, 0);
3792 unsigned int align = ndr_align_size(next_offset, 8);
3794 memset(data+next_offset, 0, align);
3795 next_offset += align;
3797 SIVAL(data, ofs, next_offset - ofs);
3806 return NT_STATUS_OK;
3809 /****************************************************************************
3810 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3811 ****************************************************************************/
3813 static void call_trans2qpipeinfo(connection_struct *conn,
3814 struct smb_request *req,
3815 unsigned int tran_call,
3816 char **pparams, int total_params,
3817 char **ppdata, int total_data,
3818 unsigned int max_data_bytes)
3820 char *params = *pparams;
3821 char *pdata = *ppdata;
3822 unsigned int data_size = 0;
3823 unsigned int param_size = 2;
3828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3832 if (total_params < 4) {
3833 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3837 fsp = file_fsp(req, SVAL(params,0));
3838 if (!fsp_is_np(fsp)) {
3839 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3843 info_level = SVAL(params,2);
3845 *pparams = (char *)SMB_REALLOC(*pparams,2);
3846 if (*pparams == NULL) {
3847 reply_nterror(req, NT_STATUS_NO_MEMORY);
3852 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3853 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3854 if (*ppdata == NULL ) {
3855 reply_nterror(req, NT_STATUS_NO_MEMORY);
3860 switch (info_level) {
3861 case SMB_FILE_STANDARD_INFORMATION:
3863 SOFF_T(pdata,0,4096LL);
3870 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3874 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3880 /****************************************************************************
3881 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3882 file name or file id).
3883 ****************************************************************************/
3885 static void call_trans2qfilepathinfo(connection_struct *conn,
3886 struct smb_request *req,
3887 unsigned int tran_call,
3888 char **pparams, int total_params,
3889 char **ppdata, int total_data,
3890 unsigned int max_data_bytes)
3892 char *params = *pparams;
3893 char *pdata = *ppdata;
3894 char *dstart, *dend;
3898 SMB_OFF_T file_size=0;
3899 uint64_t allocation_size=0;
3900 unsigned int data_size = 0;
3901 unsigned int param_size = 2;
3902 SMB_STRUCT_STAT sbuf;
3903 char *dos_fname = NULL;
3905 struct smb_filename *smb_fname = NULL;
3910 bool delete_pending = False;
3912 time_t create_time, mtime, atime;
3913 struct timespec create_time_ts, mtime_ts, atime_ts;
3914 struct timespec write_time_ts;
3915 files_struct *fsp = NULL;
3916 struct file_id fileid;
3917 struct ea_list *ea_list = NULL;
3918 char *lock_data = NULL;
3919 bool ms_dfs_link = false;
3920 TALLOC_CTX *ctx = talloc_tos();
3921 NTSTATUS status = NT_STATUS_OK;
3924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3928 ZERO_STRUCT(write_time_ts);
3930 if (tran_call == TRANSACT2_QFILEINFO) {
3931 if (total_params < 4) {
3932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3937 call_trans2qpipeinfo(conn, req, tran_call,
3938 pparams, total_params,
3944 fsp = file_fsp(req, SVAL(params,0));
3945 info_level = SVAL(params,2);
3947 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3949 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3954 /* Initial check for valid fsp ptr. */
3955 if (!check_fsp_open(conn, req, fsp)) {
3959 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3961 reply_nterror(req, NT_STATUS_NO_MEMORY);
3965 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
3967 if (!NT_STATUS_IS_OK(status)) {
3968 reply_nterror(req, status);
3972 if(fsp->fake_file_handle) {
3974 * This is actually for the QUOTA_FAKE_FILE --metze
3977 /* We know this name is ok, it's already passed the checks. */
3979 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3981 * This is actually a QFILEINFO on a directory
3982 * handle (returned from an NT SMB). NT5.0 seems
3983 * to do this call. JRA.
3986 if (INFO_LEVEL_IS_UNIX(info_level)) {
3987 /* Always do lstat for UNIX calls. */
3988 if (SMB_VFS_LSTAT(conn, smb_fname)) {
3989 DEBUG(3,("call_trans2qfilepathinfo: "
3990 "SMB_VFS_LSTAT of %s failed "
3992 smb_fname_str_dbg(smb_fname),
3994 reply_unixerror(req,ERRDOS,ERRbadpath);
3997 } else if (SMB_VFS_STAT(conn, smb_fname)) {
3998 DEBUG(3,("call_trans2qfilepathinfo: "
3999 "SMB_VFS_STAT of %s failed (%s)\n",
4000 smb_fname_str_dbg(smb_fname),
4002 reply_unixerror(req, ERRDOS, ERRbadpath);
4006 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4007 get_file_infos(fileid, &delete_pending, &write_time_ts);
4010 * Original code - this is an open file.
4012 if (!check_fsp(conn, req, fsp)) {
4016 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4017 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4018 fsp->fnum, strerror(errno)));
4019 reply_unixerror(req, ERRDOS, ERRbadfid);
4022 pos = fsp->fh->position_information;
4023 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4024 get_file_infos(fileid, &delete_pending, &write_time_ts);
4029 if (total_params < 7) {
4030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4034 info_level = SVAL(params,0);
4036 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4038 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4039 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4043 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
4045 STR_TERMINATE, &status);
4046 if (!NT_STATUS_IS_OK(status)) {
4047 reply_nterror(req, status);
4051 status = filename_convert(ctx,
4053 req->flags2 & FLAGS2_DFS_PATHNAMES,
4057 if (!NT_STATUS_IS_OK(status)) {
4058 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4059 reply_botherror(req,
4060 NT_STATUS_PATH_NOT_COVERED,
4061 ERRSRV, ERRbadpath);
4064 reply_nterror(req, status);
4068 /* If this is a stream, check if there is a delete_pending. */
4069 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4070 && is_ntfs_stream_smb_fname(smb_fname)) {
4071 struct smb_filename *smb_fname_base = NULL;
4073 /* Create an smb_filename with stream_name == NULL. */
4075 create_synthetic_smb_fname(talloc_tos(),
4076 smb_fname->base_name,
4079 if (!NT_STATUS_IS_OK(status)) {
4080 reply_nterror(req, status);
4084 if (INFO_LEVEL_IS_UNIX(info_level)) {
4085 /* Always do lstat for UNIX calls. */
4086 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4087 DEBUG(3,("call_trans2qfilepathinfo: "
4088 "SMB_VFS_LSTAT of %s failed "
4090 smb_fname_str_dbg(smb_fname_base),
4092 TALLOC_FREE(smb_fname_base);
4093 reply_unixerror(req,ERRDOS,ERRbadpath);
4097 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4098 DEBUG(3,("call_trans2qfilepathinfo: "
4099 "fileinfo of %s failed "
4101 smb_fname_str_dbg(smb_fname_base),
4103 TALLOC_FREE(smb_fname_base);
4104 reply_unixerror(req,ERRDOS,ERRbadpath);
4109 fileid = vfs_file_id_from_sbuf(conn,
4110 &smb_fname_base->st);
4111 TALLOC_FREE(smb_fname_base);
4112 get_file_infos(fileid, &delete_pending, NULL);
4113 if (delete_pending) {
4114 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4119 if (INFO_LEVEL_IS_UNIX(info_level)) {
4120 /* Always do lstat for UNIX calls. */
4121 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4122 DEBUG(3,("call_trans2qfilepathinfo: "
4123 "SMB_VFS_LSTAT of %s failed (%s)\n",
4124 smb_fname_str_dbg(smb_fname),
4126 reply_unixerror(req, ERRDOS, ERRbadpath);
4130 } else if (!VALID_STAT(smb_fname->st) &&
4131 SMB_VFS_STAT(conn, smb_fname) &&
4132 (info_level != SMB_INFO_IS_NAME_VALID)) {
4133 ms_dfs_link = check_msdfs_link(conn, fname,
4137 DEBUG(3,("call_trans2qfilepathinfo: "
4138 "SMB_VFS_STAT of %s failed (%s)\n",
4139 smb_fname_str_dbg(smb_fname),
4141 reply_unixerror(req, ERRDOS, ERRbadpath);
4146 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4147 get_file_infos(fileid, &delete_pending, &write_time_ts);
4148 if (delete_pending) {
4149 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4154 /* Set sbuf for use below. */
4155 sbuf = smb_fname->st;
4157 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4158 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4162 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4163 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4165 p = strrchr_m(smb_fname->base_name,'/');
4167 base_name = smb_fname->base_name;
4172 mode = dos_mode_msdfs(conn, smb_fname);
4174 mode = dos_mode(conn, smb_fname);
4177 mode = FILE_ATTRIBUTE_NORMAL;
4179 nlink = sbuf.st_ex_nlink;
4181 if (nlink && (mode&aDIR)) {
4185 if ((nlink > 0) && delete_pending) {
4189 fullpathname = fname;
4191 file_size = get_file_size_stat(&sbuf);
4193 /* Pull out any data sent here before we realloc. */
4194 switch (info_level) {
4195 case SMB_INFO_QUERY_EAS_FROM_LIST:
4197 /* Pull any EA list from the data portion. */
4200 if (total_data < 4) {
4202 req, NT_STATUS_INVALID_PARAMETER);
4205 ea_size = IVAL(pdata,0);
4207 if (total_data > 0 && ea_size != total_data) {
4208 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4209 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4211 req, NT_STATUS_INVALID_PARAMETER);
4215 if (!lp_ea_support(SNUM(conn))) {
4216 reply_doserror(req, ERRDOS,
4217 ERReasnotsupported);
4221 /* Pull out the list of names. */
4222 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4225 req, NT_STATUS_INVALID_PARAMETER);
4231 case SMB_QUERY_POSIX_LOCK:
4233 if (fsp == NULL || fsp->fh->fd == -1) {
4234 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4238 if (total_data != POSIX_LOCK_DATA_SIZE) {
4240 req, NT_STATUS_INVALID_PARAMETER);
4244 /* Copy the lock range data. */
4245 lock_data = (char *)TALLOC_MEMDUP(
4246 ctx, pdata, total_data);
4248 reply_nterror(req, NT_STATUS_NO_MEMORY);
4256 *pparams = (char *)SMB_REALLOC(*pparams,2);
4257 if (*pparams == NULL) {
4258 reply_nterror(req, NT_STATUS_NO_MEMORY);
4263 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4264 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4265 if (*ppdata == NULL ) {
4266 reply_nterror(req, NT_STATUS_NO_MEMORY);
4271 dend = dstart + data_size - 1;
4273 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4276 /* Do we have this path open ? */
4278 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4279 fsp1 = file_find_di_first(fileid);
4280 if (fsp1 && fsp1->initial_allocation_size) {
4281 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4285 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4286 update_stat_ex_mtime(&sbuf, write_time_ts);
4289 create_time_ts = sbuf.st_ex_btime;
4290 mtime_ts = sbuf.st_ex_mtime;
4291 atime_ts = sbuf.st_ex_atime;
4293 if (lp_dos_filetime_resolution(SNUM(conn))) {
4294 dos_filetime_timespec(&create_time_ts);
4295 dos_filetime_timespec(&mtime_ts);
4296 dos_filetime_timespec(&atime_ts);
4299 create_time = convert_timespec_to_time_t(create_time_ts);
4300 mtime = convert_timespec_to_time_t(mtime_ts);
4301 atime = convert_timespec_to_time_t(atime_ts);
4303 /* NT expects the name to be in an exact form of the *full*
4304 filename. See the trans2 torture test */
4305 if (ISDOT(base_name)) {
4306 dos_fname = talloc_strdup(ctx, "\\");
4308 reply_nterror(req, NT_STATUS_NO_MEMORY);
4312 dos_fname = talloc_asprintf(ctx,
4316 reply_nterror(req, NT_STATUS_NO_MEMORY);
4319 string_replace(dos_fname, '/', '\\');
4322 switch (info_level) {
4323 case SMB_INFO_STANDARD:
4324 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4326 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4327 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4328 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4329 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4330 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4331 SSVAL(pdata,l1_attrFile,mode);
4334 case SMB_INFO_QUERY_EA_SIZE:
4336 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4337 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4339 srv_put_dos_date2(pdata,0,create_time);
4340 srv_put_dos_date2(pdata,4,atime);
4341 srv_put_dos_date2(pdata,8,mtime); /* write time */
4342 SIVAL(pdata,12,(uint32)file_size);
4343 SIVAL(pdata,16,(uint32)allocation_size);
4344 SSVAL(pdata,20,mode);
4345 SIVAL(pdata,22,ea_size);
4349 case SMB_INFO_IS_NAME_VALID:
4350 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4351 if (tran_call == TRANSACT2_QFILEINFO) {
4352 /* os/2 needs this ? really ?*/
4353 reply_doserror(req, ERRDOS, ERRbadfunc);
4360 case SMB_INFO_QUERY_EAS_FROM_LIST:
4362 size_t total_ea_len = 0;
4363 struct ea_list *ea_file_list = NULL;
4365 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4367 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4368 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4370 if (!ea_list || (total_ea_len > data_size)) {
4372 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4376 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4380 case SMB_INFO_QUERY_ALL_EAS:
4382 /* We have data_size bytes to put EA's into. */
4383 size_t total_ea_len = 0;
4385 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4387 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4388 if (!ea_list || (total_ea_len > data_size)) {
4390 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4394 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4398 case SMB_FILE_BASIC_INFORMATION:
4399 case SMB_QUERY_FILE_BASIC_INFO:
4401 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4402 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4403 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4405 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4409 put_long_date_timespec(pdata,create_time_ts);
4410 put_long_date_timespec(pdata+8,atime_ts);
4411 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4412 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4413 SIVAL(pdata,32,mode);
4415 DEBUG(5,("SMB_QFBI - "));
4416 DEBUG(5,("create: %s ", ctime(&create_time)));
4417 DEBUG(5,("access: %s ", ctime(&atime)));
4418 DEBUG(5,("write: %s ", ctime(&mtime)));
4419 DEBUG(5,("change: %s ", ctime(&mtime)));
4420 DEBUG(5,("mode: %x\n", mode));
4423 case SMB_FILE_STANDARD_INFORMATION:
4424 case SMB_QUERY_FILE_STANDARD_INFO:
4426 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4428 SOFF_T(pdata,0,allocation_size);
4429 SOFF_T(pdata,8,file_size);
4430 SIVAL(pdata,16,nlink);
4431 SCVAL(pdata,20,delete_pending?1:0);
4432 SCVAL(pdata,21,(mode&aDIR)?1:0);
4433 SSVAL(pdata,22,0); /* Padding. */
4436 case SMB_FILE_EA_INFORMATION:
4437 case SMB_QUERY_FILE_EA_INFO:
4439 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4440 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4442 SIVAL(pdata,0,ea_size);
4446 /* Get the 8.3 name - used if NT SMB was negotiated. */
4447 case SMB_QUERY_FILE_ALT_NAME_INFO:
4448 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4450 char mangled_name[13];
4451 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4452 if (!name_to_8_3(base_name,mangled_name,
4453 True,conn->params)) {
4456 NT_STATUS_NO_MEMORY);
4458 len = srvstr_push(dstart, req->flags2,
4459 pdata+4, mangled_name,
4460 PTR_DIFF(dend, pdata+4),
4462 data_size = 4 + len;
4467 case SMB_QUERY_FILE_NAME_INFO:
4469 this must be *exactly* right for ACLs on mapped drives to work
4471 len = srvstr_push(dstart, req->flags2,
4473 PTR_DIFF(dend, pdata+4),
4475 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4476 data_size = 4 + len;
4480 case SMB_FILE_ALLOCATION_INFORMATION:
4481 case SMB_QUERY_FILE_ALLOCATION_INFO:
4482 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4484 SOFF_T(pdata,0,allocation_size);
4487 case SMB_FILE_END_OF_FILE_INFORMATION:
4488 case SMB_QUERY_FILE_END_OF_FILEINFO:
4489 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4491 SOFF_T(pdata,0,file_size);
4494 case SMB_QUERY_FILE_ALL_INFO:
4495 case SMB_FILE_ALL_INFORMATION:
4497 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4498 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4499 put_long_date_timespec(pdata,create_time_ts);
4500 put_long_date_timespec(pdata+8,atime_ts);
4501 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4502 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4503 SIVAL(pdata,32,mode);
4504 SIVAL(pdata,36,0); /* padding. */
4506 SOFF_T(pdata,0,allocation_size);
4507 SOFF_T(pdata,8,file_size);
4508 SIVAL(pdata,16,nlink);
4509 SCVAL(pdata,20,delete_pending);
4510 SCVAL(pdata,21,(mode&aDIR)?1:0);
4513 SIVAL(pdata,0,ea_size);
4514 pdata += 4; /* EA info */
4515 len = srvstr_push(dstart, req->flags2,
4517 PTR_DIFF(dend, pdata+4),
4521 data_size = PTR_DIFF(pdata,(*ppdata));
4524 case SMB_FILE_INTERNAL_INFORMATION:
4525 /* This should be an index number - looks like
4528 I think this causes us to fail the IFSKIT
4529 BasicFileInformationTest. -tpot */
4531 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4532 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4533 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4537 case SMB_FILE_ACCESS_INFORMATION:
4538 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4540 SIVAL(pdata,0,fsp->access_mask);
4542 /* GENERIC_EXECUTE mapping from Windows */
4543 SIVAL(pdata,0,0x12019F);
4548 case SMB_FILE_NAME_INFORMATION:
4549 /* Pathname with leading '\'. */
4552 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4553 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4554 SIVAL(pdata,0,byte_len);
4555 data_size = 4 + byte_len;
4559 case SMB_FILE_DISPOSITION_INFORMATION:
4560 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4562 SCVAL(pdata,0,delete_pending);
4565 case SMB_FILE_POSITION_INFORMATION:
4566 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4568 SOFF_T(pdata,0,pos);
4571 case SMB_FILE_MODE_INFORMATION:
4572 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4573 SIVAL(pdata,0,mode);
4577 case SMB_FILE_ALIGNMENT_INFORMATION:
4578 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4579 SIVAL(pdata,0,0); /* No alignment needed. */
4584 * NT4 server just returns "invalid query" to this - if we try
4585 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4588 /* The first statement above is false - verified using Thursby
4589 * client against NT4 -- gcolley.
4591 case SMB_QUERY_FILE_STREAM_INFO:
4592 case SMB_FILE_STREAM_INFORMATION: {
4593 unsigned int num_streams;
4594 struct stream_struct *streams;
4596 DEBUG(10,("call_trans2qfilepathinfo: "
4597 "SMB_FILE_STREAM_INFORMATION\n"));
4599 status = SMB_VFS_STREAMINFO(
4600 conn, fsp, fname, talloc_tos(),
4601 &num_streams, &streams);
4603 if (!NT_STATUS_IS_OK(status)) {
4604 DEBUG(10, ("could not get stream info: %s\n",
4605 nt_errstr(status)));
4606 reply_nterror(req, status);
4610 status = marshall_stream_info(num_streams, streams,
4611 pdata, max_data_bytes,
4614 if (!NT_STATUS_IS_OK(status)) {
4615 DEBUG(10, ("marshall_stream_info failed: %s\n",
4616 nt_errstr(status)));
4617 reply_nterror(req, status);
4621 TALLOC_FREE(streams);
4625 case SMB_QUERY_COMPRESSION_INFO:
4626 case SMB_FILE_COMPRESSION_INFORMATION:
4627 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4628 SOFF_T(pdata,0,file_size);
4629 SIVAL(pdata,8,0); /* ??? */
4630 SIVAL(pdata,12,0); /* ??? */
4634 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4635 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4636 put_long_date_timespec(pdata,create_time_ts);
4637 put_long_date_timespec(pdata+8,atime_ts);
4638 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4639 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4640 SOFF_T(pdata,32,allocation_size);
4641 SOFF_T(pdata,40,file_size);
4642 SIVAL(pdata,48,mode);
4643 SIVAL(pdata,52,0); /* ??? */
4647 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4648 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4649 SIVAL(pdata,0,mode);
4655 * CIFS UNIX Extensions.
4658 case SMB_QUERY_FILE_UNIX_BASIC:
4660 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4661 data_size = PTR_DIFF(pdata,(*ppdata));
4665 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4667 for (i=0; i<100; i++)
4668 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4674 case SMB_QUERY_FILE_UNIX_INFO2:
4676 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4677 data_size = PTR_DIFF(pdata,(*ppdata));
4681 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4683 for (i=0; i<100; i++)
4684 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4690 case SMB_QUERY_FILE_UNIX_LINK:
4692 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4695 reply_nterror(req, NT_STATUS_NO_MEMORY);
4699 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4701 if(!S_ISLNK(sbuf.st_ex_mode)) {
4702 reply_unixerror(req, ERRSRV,
4707 reply_unixerror(req, ERRDOS, ERRbadlink);
4710 len = SMB_VFS_READLINK(conn,fullpathname,
4713 reply_unixerror(req, ERRDOS,
4718 len = srvstr_push(dstart, req->flags2,
4720 PTR_DIFF(dend, pdata),
4723 data_size = PTR_DIFF(pdata,(*ppdata));
4728 #if defined(HAVE_POSIX_ACLS)
4729 case SMB_QUERY_POSIX_ACL:
4731 SMB_ACL_T file_acl = NULL;
4732 SMB_ACL_T def_acl = NULL;
4733 uint16 num_file_acls = 0;
4734 uint16 num_def_acls = 0;
4736 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4737 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4739 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4742 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4743 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4747 NT_STATUS_NOT_IMPLEMENTED);
4751 if (S_ISDIR(sbuf.st_ex_mode)) {
4752 if (fsp && fsp->is_directory) {
4753 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4755 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4757 def_acl = free_empty_sys_acl(conn, def_acl);
4760 num_file_acls = count_acl_entries(conn, file_acl);
4761 num_def_acls = count_acl_entries(conn, def_acl);
4763 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4764 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4766 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4767 SMB_POSIX_ACL_HEADER_SIZE) ));
4769 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4772 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4776 NT_STATUS_BUFFER_TOO_SMALL);
4780 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4781 SSVAL(pdata,2,num_file_acls);
4782 SSVAL(pdata,4,num_def_acls);
4783 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4785 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4788 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4791 req, NT_STATUS_INTERNAL_ERROR);
4794 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4796 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4799 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4803 NT_STATUS_INTERNAL_ERROR);
4808 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4811 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4813 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4819 case SMB_QUERY_POSIX_LOCK:
4824 enum brl_type lock_type;
4826 if (total_data != POSIX_LOCK_DATA_SIZE) {
4828 req, NT_STATUS_INVALID_PARAMETER);
4832 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4833 case POSIX_LOCK_TYPE_READ:
4834 lock_type = READ_LOCK;
4836 case POSIX_LOCK_TYPE_WRITE:
4837 lock_type = WRITE_LOCK;
4839 case POSIX_LOCK_TYPE_UNLOCK:
4841 /* There's no point in asking for an unlock... */
4844 NT_STATUS_INVALID_PARAMETER);
4848 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4849 #if defined(HAVE_LONGLONG)
4850 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4851 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4852 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4853 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4854 #else /* HAVE_LONGLONG */
4855 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4856 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4857 #endif /* HAVE_LONGLONG */
4859 status = query_lock(fsp,
4866 if (ERROR_WAS_LOCK_DENIED(status)) {
4867 /* Here we need to report who has it locked... */
4868 data_size = POSIX_LOCK_DATA_SIZE;
4870 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4871 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4872 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4873 #if defined(HAVE_LONGLONG)
4874 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4875 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4876 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4877 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4878 #else /* HAVE_LONGLONG */
4879 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4880 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4881 #endif /* HAVE_LONGLONG */
4883 } else if (NT_STATUS_IS_OK(status)) {
4884 /* For success we just return a copy of what we sent
4885 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4886 data_size = POSIX_LOCK_DATA_SIZE;
4887 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4888 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4890 reply_nterror(req, status);
4897 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4901 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4907 /****************************************************************************
4908 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4910 ****************************************************************************/
4912 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4913 connection_struct *conn,
4914 const struct smb_filename *smb_fname_old,
4915 const struct smb_filename *smb_fname_new)
4917 char *oldname = NULL;
4918 char *newname = NULL;
4919 NTSTATUS status = NT_STATUS_OK;
4921 /* source must already exist. */
4922 if (!VALID_STAT(smb_fname_old->st)) {
4923 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4926 /* Disallow if newname already exists. */
4927 if (VALID_STAT(smb_fname_new->st)) {
4928 return NT_STATUS_OBJECT_NAME_COLLISION;
4931 /* No links from a directory. */
4932 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
4933 return NT_STATUS_FILE_IS_A_DIRECTORY;
4936 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
4937 if (!NT_STATUS_IS_OK(status)) {
4940 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
4941 if (!NT_STATUS_IS_OK(status)) {
4945 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4947 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4948 status = map_nt_error_from_unix(errno);
4949 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4950 nt_errstr(status), newname, oldname));
4953 TALLOC_FREE(newname);
4954 TALLOC_FREE(oldname);
4958 /****************************************************************************
4959 Deal with setting the time from any of the setfilepathinfo functions.
4960 ****************************************************************************/
4962 NTSTATUS smb_set_file_time(connection_struct *conn,
4964 const struct smb_filename *smb_fname,
4965 struct smb_file_time *ft,
4966 bool setting_write_time)
4968 struct smb_filename *smb_fname_base = NULL;
4970 FILE_NOTIFY_CHANGE_LAST_ACCESS
4971 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4974 if (!VALID_STAT(smb_fname->st)) {
4975 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4978 /* get some defaults (no modifications) if any info is zero or -1. */
4979 if (null_timespec(ft->atime)) {
4980 ft->atime= smb_fname->st.st_ex_atime;
4981 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4984 if (null_timespec(ft->mtime)) {
4985 ft->mtime = smb_fname->st.st_ex_mtime;
4986 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4989 if (!setting_write_time) {
4990 /* ft->mtime comes from change time, not write time. */
4991 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4994 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4995 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4996 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4997 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4998 if (!null_timespec(ft->create_time)) {
4999 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5000 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5004 * Try and set the times of this file if
5005 * they are different from the current values.
5009 struct timespec mts = smb_fname->st.st_ex_mtime;
5010 struct timespec ats = smb_fname->st.st_ex_atime;
5011 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5012 (timespec_compare(&ft->mtime, &mts) == 0)) {
5013 return NT_STATUS_OK;
5017 if (setting_write_time) {
5019 * This was a Windows setfileinfo on an open file.
5020 * NT does this a lot. We also need to
5021 * set the time here, as it can be read by
5022 * FindFirst/FindNext and with the patch for bug #2045
5023 * in smbd/fileio.c it ensures that this timestamp is
5024 * kept sticky even after a write. We save the request
5025 * away and will set it on file close and after a write. JRA.
5028 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5029 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5032 if (fsp->base_fsp) {
5033 set_sticky_write_time_fsp(fsp->base_fsp,
5036 set_sticky_write_time_fsp(fsp, ft->mtime);
5039 set_sticky_write_time_path(
5040 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5045 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5047 /* Always call ntimes on the base, even if a stream was passed in. */
5048 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5049 NULL, &smb_fname->st,
5051 if (!NT_STATUS_IS_OK(status)) {
5055 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5056 TALLOC_FREE(smb_fname_base);
5057 return map_nt_error_from_unix(errno);
5059 TALLOC_FREE(smb_fname_base);
5061 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5062 smb_fname->base_name);
5063 return NT_STATUS_OK;
5066 /****************************************************************************
5067 Deal with setting the dosmode from any of the setfilepathinfo functions.
5068 ****************************************************************************/
5070 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5071 const struct smb_filename *smb_fname,
5074 struct smb_filename *smb_fname_base = NULL;
5077 if (!VALID_STAT(smb_fname->st)) {
5078 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5081 /* Always operate on the base_name, even if a stream was passed in. */
5082 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5083 NULL, &smb_fname->st,
5085 if (!NT_STATUS_IS_OK(status)) {
5090 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5097 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5099 /* check the mode isn't different, before changing it */
5100 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5101 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5102 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5103 (unsigned int)dosmode));
5105 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5107 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5109 smb_fname_str_dbg(smb_fname_base),
5111 status = map_nt_error_from_unix(errno);
5115 status = NT_STATUS_OK;
5117 TALLOC_FREE(smb_fname_base);
5121 /****************************************************************************
5122 Deal with setting the size from any of the setfilepathinfo functions.
5123 ****************************************************************************/
5125 static NTSTATUS smb_set_file_size(connection_struct *conn,
5126 struct smb_request *req,
5128 const struct smb_filename *smb_fname,
5129 const SMB_STRUCT_STAT *psbuf,
5132 NTSTATUS status = NT_STATUS_OK;
5133 struct smb_filename *smb_fname_tmp = NULL;
5134 files_struct *new_fsp = NULL;
5136 if (!VALID_STAT(*psbuf)) {
5137 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5140 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5142 if (size == get_file_size_stat(psbuf)) {
5143 return NT_STATUS_OK;
5146 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5147 smb_fname_str_dbg(smb_fname), (double)size));
5149 if (fsp && fsp->fh->fd != -1) {
5150 /* Handle based call. */
5151 if (vfs_set_filelen(fsp, size) == -1) {
5152 return map_nt_error_from_unix(errno);
5154 trigger_write_time_update_immediate(fsp);
5155 return NT_STATUS_OK;
5158 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5159 if (!NT_STATUS_IS_OK(status)) {
5163 smb_fname_tmp->st = *psbuf;
5165 status = SMB_VFS_CREATE_FILE(
5168 0, /* root_dir_fid */
5169 smb_fname_tmp, /* fname */
5170 FILE_WRITE_ATTRIBUTES, /* access_mask */
5171 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5173 FILE_OPEN, /* create_disposition*/
5174 0, /* create_options */
5175 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5176 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5177 0, /* allocation_size */
5180 &new_fsp, /* result */
5183 TALLOC_FREE(smb_fname_tmp);
5185 if (!NT_STATUS_IS_OK(status)) {
5186 /* NB. We check for open_was_deferred in the caller. */
5190 if (vfs_set_filelen(new_fsp, size) == -1) {
5191 status = map_nt_error_from_unix(errno);
5192 close_file(req, new_fsp,NORMAL_CLOSE);
5196 trigger_write_time_update_immediate(new_fsp);
5197 close_file(req, new_fsp,NORMAL_CLOSE);
5198 return NT_STATUS_OK;
5201 /****************************************************************************
5202 Deal with SMB_INFO_SET_EA.
5203 ****************************************************************************/
5205 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5209 const struct smb_filename *smb_fname)
5211 struct ea_list *ea_list = NULL;
5212 TALLOC_CTX *ctx = NULL;
5213 NTSTATUS status = NT_STATUS_OK;
5215 if (total_data < 10) {
5217 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5218 length. They seem to have no effect. Bug #3212. JRA */
5220 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5221 /* We're done. We only get EA info in this call. */
5222 return NT_STATUS_OK;
5225 return NT_STATUS_INVALID_PARAMETER;
5228 if (IVAL(pdata,0) > total_data) {
5229 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5230 IVAL(pdata,0), (unsigned int)total_data));
5231 return NT_STATUS_INVALID_PARAMETER;
5235 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5237 return NT_STATUS_INVALID_PARAMETER;
5239 status = set_ea(conn, fsp, smb_fname, ea_list);
5244 /****************************************************************************
5245 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5246 ****************************************************************************/
5248 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5252 const struct smb_filename *smb_fname)
5254 NTSTATUS status = NT_STATUS_OK;
5255 bool delete_on_close;
5258 if (total_data < 1) {
5259 return NT_STATUS_INVALID_PARAMETER;
5263 return NT_STATUS_INVALID_HANDLE;
5266 delete_on_close = (CVAL(pdata,0) ? True : False);
5267 dosmode = dos_mode(conn, smb_fname);
5269 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5270 "delete_on_close = %u\n",
5271 smb_fname_str_dbg(smb_fname),
5272 (unsigned int)dosmode,
5273 (unsigned int)delete_on_close ));
5275 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5277 if (!NT_STATUS_IS_OK(status)) {
5281 /* The set is across all open files on this dev/inode pair. */
5282 if (!set_delete_on_close(fsp, delete_on_close,
5283 &conn->server_info->utok)) {
5284 return NT_STATUS_ACCESS_DENIED;
5286 return NT_STATUS_OK;
5289 /****************************************************************************
5290 Deal with SMB_FILE_POSITION_INFORMATION.
5291 ****************************************************************************/
5293 static NTSTATUS smb_file_position_information(connection_struct *conn,
5298 uint64_t position_information;
5300 if (total_data < 8) {
5301 return NT_STATUS_INVALID_PARAMETER;
5305 /* Ignore on pathname based set. */
5306 return NT_STATUS_OK;
5309 position_information = (uint64_t)IVAL(pdata,0);
5310 #ifdef LARGE_SMB_OFF_T
5311 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5312 #else /* LARGE_SMB_OFF_T */
5313 if (IVAL(pdata,4) != 0) {
5314 /* more than 32 bits? */
5315 return NT_STATUS_INVALID_PARAMETER;
5317 #endif /* LARGE_SMB_OFF_T */
5319 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5320 fsp->fsp_name, (double)position_information ));
5321 fsp->fh->position_information = position_information;
5322 return NT_STATUS_OK;
5325 /****************************************************************************
5326 Deal with SMB_FILE_MODE_INFORMATION.
5327 ****************************************************************************/
5329 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5335 if (total_data < 4) {
5336 return NT_STATUS_INVALID_PARAMETER;
5338 mode = IVAL(pdata,0);
5339 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5340 return NT_STATUS_INVALID_PARAMETER;
5342 return NT_STATUS_OK;
5345 /****************************************************************************
5346 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5347 ****************************************************************************/
5349 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5350 struct smb_request *req,
5355 char *link_target = NULL;
5356 const char *newname = fname;
5357 NTSTATUS status = NT_STATUS_OK;
5358 TALLOC_CTX *ctx = talloc_tos();
5360 /* Set a symbolic link. */
5361 /* Don't allow this if follow links is false. */
5363 if (total_data == 0) {
5364 return NT_STATUS_INVALID_PARAMETER;
5367 if (!lp_symlinks(SNUM(conn))) {
5368 return NT_STATUS_ACCESS_DENIED;
5371 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5372 total_data, STR_TERMINATE);
5375 return NT_STATUS_INVALID_PARAMETER;
5378 /* !widelinks forces the target path to be within the share. */
5379 /* This means we can interpret the target as a pathname. */
5380 if (!lp_widelinks(SNUM(conn))) {
5381 char *rel_name = NULL;
5382 char *last_dirp = NULL;
5384 if (*link_target == '/') {
5385 /* No absolute paths allowed. */
5386 return NT_STATUS_ACCESS_DENIED;
5388 rel_name = talloc_strdup(ctx,newname);
5390 return NT_STATUS_NO_MEMORY;
5392 last_dirp = strrchr_m(rel_name, '/');
5394 last_dirp[1] = '\0';
5396 rel_name = talloc_strdup(ctx,"./");
5398 return NT_STATUS_NO_MEMORY;
5401 rel_name = talloc_asprintf_append(rel_name,
5405 return NT_STATUS_NO_MEMORY;
5408 status = check_name(conn, rel_name);
5409 if (!NT_STATUS_IS_OK(status)) {
5414 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5415 newname, link_target ));
5417 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5418 return map_nt_error_from_unix(errno);
5421 return NT_STATUS_OK;
5424 /****************************************************************************
5425 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5426 ****************************************************************************/
5428 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5429 struct smb_request *req,
5430 const char *pdata, int total_data,
5431 const struct smb_filename *smb_fname_new)
5433 char *oldname = NULL;
5434 struct smb_filename *smb_fname_old = NULL;
5435 TALLOC_CTX *ctx = talloc_tos();
5436 NTSTATUS status = NT_STATUS_OK;
5438 /* Set a hard link. */
5439 if (total_data == 0) {
5440 return NT_STATUS_INVALID_PARAMETER;
5443 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5444 total_data, STR_TERMINATE, &status);
5445 if (!NT_STATUS_IS_OK(status)) {
5449 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5450 smb_fname_str_dbg(smb_fname_new), oldname));
5452 status = filename_convert(ctx,
5454 req->flags2 & FLAGS2_DFS_PATHNAMES,
5458 if (!NT_STATUS_IS_OK(status)) {
5462 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5465 /****************************************************************************
5466 Deal with SMB_FILE_RENAME_INFORMATION.
5467 ****************************************************************************/
5469 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5470 struct smb_request *req,
5479 char *newname = NULL;
5480 char *base_name = NULL;
5481 struct smb_filename *smb_fname = NULL;
5482 bool dest_has_wcard = False;
5483 NTSTATUS status = NT_STATUS_OK;
5485 TALLOC_CTX *ctx = talloc_tos();
5487 if (total_data < 13) {
5488 return NT_STATUS_INVALID_PARAMETER;
5491 overwrite = (CVAL(pdata,0) ? True : False);
5492 root_fid = IVAL(pdata,4);
5493 len = IVAL(pdata,8);
5495 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5496 return NT_STATUS_INVALID_PARAMETER;
5499 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5502 if (!NT_STATUS_IS_OK(status)) {
5506 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5509 status = resolve_dfspath_wcard(ctx, conn,
5510 req->flags2 & FLAGS2_DFS_PATHNAMES,
5514 if (!NT_STATUS_IS_OK(status)) {
5518 /* Check the new name has no '/' characters. */
5519 if (strchr_m(newname, '/')) {
5520 return NT_STATUS_NOT_SUPPORTED;
5523 if (fsp && fsp->base_fsp) {
5524 /* newname must be a stream name. */
5525 if (newname[0] != ':') {
5526 return NT_STATUS_NOT_SUPPORTED;
5529 /* Create an smb_fname to call rename_internals_fsp() with. */
5530 status = create_synthetic_smb_fname(talloc_tos(),
5531 fsp->base_fsp->fsp_name,
5532 newname, NULL, &smb_fname);
5533 if (!NT_STATUS_IS_OK(status)) {
5538 * Set the original last component, since
5539 * rename_internals_fsp() requires it.
5541 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5542 if (smb_fname->original_lcomp == NULL) {
5543 status = NT_STATUS_NO_MEMORY;
5547 /* Create a char * to call rename_internals() with. */
5548 base_name = talloc_asprintf(ctx, "%s%s",
5549 fsp->base_fsp->fsp_name,
5552 status = NT_STATUS_NO_MEMORY;
5556 /* newname must *not* be a stream name. */
5557 if (is_ntfs_stream_name(newname)) {
5558 return NT_STATUS_NOT_SUPPORTED;
5561 /* Create the base directory. */
5562 base_name = talloc_strdup(ctx, fname);
5564 return NT_STATUS_NO_MEMORY;
5566 p = strrchr_m(base_name, '/');
5570 base_name = talloc_strdup(ctx, "./");
5572 return NT_STATUS_NO_MEMORY;
5575 /* Append the new name. */
5576 base_name = talloc_asprintf_append(base_name,
5580 return NT_STATUS_NO_MEMORY;
5583 status = unix_convert(ctx, conn, base_name, &smb_fname,
5586 /* If an error we expect this to be
5587 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5589 if (!NT_STATUS_IS_OK(status)) {
5590 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5594 /* Create an smb_fname to call rename_internals_fsp() */
5595 status = create_synthetic_smb_fname(talloc_tos(),
5598 if (!NT_STATUS_IS_OK(status)) {
5606 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5607 fsp->fnum, fsp->fsp_name, base_name ));
5608 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5611 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5612 fname, base_name ));
5613 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5614 overwrite, False, dest_has_wcard,
5615 FILE_WRITE_ATTRIBUTES);
5618 TALLOC_FREE(smb_fname);
5622 /****************************************************************************
5623 Deal with SMB_SET_POSIX_ACL.
5624 ****************************************************************************/
5626 #if defined(HAVE_POSIX_ACLS)
5627 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5632 SMB_STRUCT_STAT *psbuf)
5634 uint16 posix_acl_version;
5635 uint16 num_file_acls;
5636 uint16 num_def_acls;
5637 bool valid_file_acls = True;
5638 bool valid_def_acls = True;
5640 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5641 return NT_STATUS_INVALID_PARAMETER;
5643 posix_acl_version = SVAL(pdata,0);
5644 num_file_acls = SVAL(pdata,2);
5645 num_def_acls = SVAL(pdata,4);
5647 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5648 valid_file_acls = False;
5652 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5653 valid_def_acls = False;
5657 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5658 return NT_STATUS_INVALID_PARAMETER;
5661 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5662 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5663 return NT_STATUS_INVALID_PARAMETER;
5666 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5667 fname ? fname : fsp->fsp_name,
5668 (unsigned int)num_file_acls,
5669 (unsigned int)num_def_acls));
5671 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5672 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5673 return map_nt_error_from_unix(errno);
5676 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5677 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5678 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5679 return map_nt_error_from_unix(errno);
5681 return NT_STATUS_OK;
5685 /****************************************************************************
5686 Deal with SMB_SET_POSIX_LOCK.
5687 ****************************************************************************/
5689 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5690 struct smb_request *req,
5698 bool blocking_lock = False;
5699 enum brl_type lock_type;
5701 NTSTATUS status = NT_STATUS_OK;
5703 if (fsp == NULL || fsp->fh->fd == -1) {
5704 return NT_STATUS_INVALID_HANDLE;
5707 if (total_data != POSIX_LOCK_DATA_SIZE) {
5708 return NT_STATUS_INVALID_PARAMETER;
5711 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5712 case POSIX_LOCK_TYPE_READ:
5713 lock_type = READ_LOCK;
5715 case POSIX_LOCK_TYPE_WRITE:
5716 /* Return the right POSIX-mappable error code for files opened read-only. */
5717 if (!fsp->can_write) {
5718 return NT_STATUS_INVALID_HANDLE;
5720 lock_type = WRITE_LOCK;
5722 case POSIX_LOCK_TYPE_UNLOCK:
5723 lock_type = UNLOCK_LOCK;
5726 return NT_STATUS_INVALID_PARAMETER;
5729 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5730 blocking_lock = False;
5731 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5732 blocking_lock = True;
5734 return NT_STATUS_INVALID_PARAMETER;
5737 if (!lp_blocking_locks(SNUM(conn))) {
5738 blocking_lock = False;
5741 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5742 #if defined(HAVE_LONGLONG)
5743 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5744 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5745 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5746 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5747 #else /* HAVE_LONGLONG */
5748 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5749 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5750 #endif /* HAVE_LONGLONG */
5752 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5753 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5755 (unsigned int)lock_type,
5756 (unsigned int)lock_pid,
5760 if (lock_type == UNLOCK_LOCK) {
5761 status = do_unlock(smbd_messaging_context(),
5768 uint32 block_smbpid;
5770 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5782 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5784 * A blocking lock was requested. Package up
5785 * this smb into a queued request and push it
5786 * onto the blocking lock queue.
5788 if(push_blocking_lock_request(br_lck,
5791 -1, /* infinite timeout. */
5799 TALLOC_FREE(br_lck);
5803 TALLOC_FREE(br_lck);
5809 /****************************************************************************
5810 Deal with SMB_INFO_STANDARD.
5811 ****************************************************************************/
5813 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5817 const struct smb_filename *smb_fname)
5819 struct smb_file_time ft;
5822 if (total_data < 12) {
5823 return NT_STATUS_INVALID_PARAMETER;
5827 ft.create_time = interpret_long_date(pdata);
5830 ft.atime = interpret_long_date(pdata + 8);
5833 ft.mtime = interpret_long_date(pdata + 16);
5835 DEBUG(10,("smb_set_info_standard: file %s\n",
5836 smb_fname_str_dbg(smb_fname)));
5838 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5841 /****************************************************************************
5842 Deal with SMB_SET_FILE_BASIC_INFO.
5843 ****************************************************************************/
5845 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5849 const struct smb_filename *smb_fname)
5851 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5852 struct timespec write_time;
5853 struct timespec changed_time;
5854 struct smb_file_time ft;
5856 NTSTATUS status = NT_STATUS_OK;
5857 bool setting_write_time = true;
5861 if (total_data < 36) {
5862 return NT_STATUS_INVALID_PARAMETER;
5865 /* Set the attributes */
5866 dosmode = IVAL(pdata,32);
5867 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
5868 if (!NT_STATUS_IS_OK(status)) {
5873 ft.atime = interpret_long_date(pdata+8);
5875 write_time = interpret_long_date(pdata+16);
5876 changed_time = interpret_long_date(pdata+24);
5879 ft.mtime = timespec_min(&write_time, &changed_time);
5882 ft.create_time = interpret_long_date(pdata);
5884 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5885 !null_timespec(write_time)) {
5886 ft.mtime = write_time;
5889 /* Prefer a defined time to an undefined one. */
5890 if (null_timespec(ft.mtime)) {
5891 if (null_timespec(write_time)) {
5892 ft.mtime = changed_time;
5893 setting_write_time = false;
5895 ft.mtime = write_time;
5899 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
5900 smb_fname_str_dbg(smb_fname)));
5902 return smb_set_file_time(conn, fsp, smb_fname, &ft,
5903 setting_write_time);
5906 /****************************************************************************
5907 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5908 ****************************************************************************/
5910 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5911 struct smb_request *req,
5916 SMB_STRUCT_STAT *psbuf)
5918 struct smb_filename *smb_fname = NULL;
5919 uint64_t allocation_size = 0;
5920 NTSTATUS status = NT_STATUS_OK;
5921 files_struct *new_fsp = NULL;
5923 if (!VALID_STAT(*psbuf)) {
5924 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5927 if (total_data < 8) {
5928 return NT_STATUS_INVALID_PARAMETER;
5931 allocation_size = (uint64_t)IVAL(pdata,0);
5932 #ifdef LARGE_SMB_OFF_T
5933 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5934 #else /* LARGE_SMB_OFF_T */
5935 if (IVAL(pdata,4) != 0) {
5936 /* more than 32 bits? */
5937 return NT_STATUS_INVALID_PARAMETER;
5939 #endif /* LARGE_SMB_OFF_T */
5941 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5942 fname, (double)allocation_size ));
5944 if (allocation_size) {
5945 allocation_size = smb_roundup(conn, allocation_size);
5948 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5949 fname, (double)allocation_size ));
5951 if (fsp && fsp->fh->fd != -1) {
5952 /* Open file handle. */
5953 /* Only change if needed. */
5954 if (allocation_size != get_file_size_stat(psbuf)) {
5955 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5956 return map_nt_error_from_unix(errno);
5959 /* But always update the time. */
5961 * This is equivalent to a write. Ensure it's seen immediately
5962 * if there are no pending writes.
5964 trigger_write_time_update_immediate(fsp);
5965 return NT_STATUS_OK;
5968 /* Pathname or stat or directory file. */
5970 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5972 if (!NT_STATUS_IS_OK(status)) {
5976 status = SMB_VFS_CREATE_FILE(
5979 0, /* root_dir_fid */
5980 smb_fname, /* fname */
5981 FILE_WRITE_DATA, /* access_mask */
5982 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5984 FILE_OPEN, /* create_disposition*/
5985 0, /* create_options */
5986 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5987 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5988 0, /* allocation_size */
5991 &new_fsp, /* result */
5994 *psbuf = smb_fname->st;
5995 TALLOC_FREE(smb_fname);
5997 if (!NT_STATUS_IS_OK(status)) {
5998 /* NB. We check for open_was_deferred in the caller. */
6002 /* Only change if needed. */
6003 if (allocation_size != get_file_size_stat(psbuf)) {
6004 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6005 status = map_nt_error_from_unix(errno);
6006 close_file(req, new_fsp, NORMAL_CLOSE);
6011 /* Changing the allocation size should set the last mod time. */
6013 * This is equivalent to a write. Ensure it's seen immediately
6014 * if there are no pending writes.
6016 trigger_write_time_update_immediate(new_fsp);
6018 close_file(req, new_fsp, NORMAL_CLOSE);
6019 return NT_STATUS_OK;
6022 /****************************************************************************
6023 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6024 ****************************************************************************/
6026 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6027 struct smb_request *req,
6031 const struct smb_filename *smb_fname)
6035 if (total_data < 8) {
6036 return NT_STATUS_INVALID_PARAMETER;
6039 size = IVAL(pdata,0);
6040 #ifdef LARGE_SMB_OFF_T
6041 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6042 #else /* LARGE_SMB_OFF_T */
6043 if (IVAL(pdata,4) != 0) {
6044 /* more than 32 bits? */
6045 return NT_STATUS_INVALID_PARAMETER;
6047 #endif /* LARGE_SMB_OFF_T */
6048 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6049 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6052 return smb_set_file_size(conn, req,
6059 /****************************************************************************
6060 Allow a UNIX info mknod.
6061 ****************************************************************************/
6063 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6066 const struct smb_filename *smb_fname)
6068 uint32 file_type = IVAL(pdata,56);
6069 #if defined(HAVE_MAKEDEV)
6070 uint32 dev_major = IVAL(pdata,60);
6071 uint32 dev_minor = IVAL(pdata,68);
6073 SMB_DEV_T dev = (SMB_DEV_T)0;
6074 uint32 raw_unixmode = IVAL(pdata,84);
6078 if (total_data < 100) {
6079 return NT_STATUS_INVALID_PARAMETER;
6082 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6083 PERM_NEW_FILE, &unixmode);
6084 if (!NT_STATUS_IS_OK(status)) {
6088 #if defined(HAVE_MAKEDEV)
6089 dev = makedev(dev_major, dev_minor);
6092 switch (file_type) {
6093 #if defined(S_IFIFO)
6094 case UNIX_TYPE_FIFO:
6095 unixmode |= S_IFIFO;
6098 #if defined(S_IFSOCK)
6099 case UNIX_TYPE_SOCKET:
6100 unixmode |= S_IFSOCK;
6103 #if defined(S_IFCHR)
6104 case UNIX_TYPE_CHARDEV:
6105 unixmode |= S_IFCHR;
6108 #if defined(S_IFBLK)
6109 case UNIX_TYPE_BLKDEV:
6110 unixmode |= S_IFBLK;
6114 return NT_STATUS_INVALID_PARAMETER;
6117 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6118 "%.0f mode 0%o for file %s\n", (double)dev,
6119 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6121 /* Ok - do the mknod. */
6122 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6123 return map_nt_error_from_unix(errno);
6126 /* If any of the other "set" calls fail we
6127 * don't want to end up with a half-constructed mknod.
6130 if (lp_inherit_perms(SNUM(conn))) {
6132 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6134 return NT_STATUS_NO_MEMORY;
6136 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6138 TALLOC_FREE(parent);
6141 return NT_STATUS_OK;
6144 /****************************************************************************
6145 Deal with SMB_SET_FILE_UNIX_BASIC.
6146 ****************************************************************************/
6148 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6149 struct smb_request *req,
6153 const struct smb_filename *smb_fname)
6155 struct smb_file_time ft;
6156 uint32 raw_unixmode;
6159 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6160 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6161 NTSTATUS status = NT_STATUS_OK;
6162 bool delete_on_fail = False;
6163 enum perm_type ptype;
6164 files_struct *all_fsps = NULL;
6165 bool modify_mtime = true;
6167 SMB_STRUCT_STAT sbuf;
6171 if (total_data < 100) {
6172 return NT_STATUS_INVALID_PARAMETER;
6175 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6176 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6177 size=IVAL(pdata,0); /* first 8 Bytes are size */
6178 #ifdef LARGE_SMB_OFF_T
6179 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6180 #else /* LARGE_SMB_OFF_T */
6181 if (IVAL(pdata,4) != 0) {
6182 /* more than 32 bits? */
6183 return NT_STATUS_INVALID_PARAMETER;
6185 #endif /* LARGE_SMB_OFF_T */
6188 ft.atime = interpret_long_date(pdata+24); /* access_time */
6189 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6190 set_owner = (uid_t)IVAL(pdata,40);
6191 set_grp = (gid_t)IVAL(pdata,48);
6192 raw_unixmode = IVAL(pdata,84);
6194 if (VALID_STAT(smb_fname->st)) {
6195 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6196 ptype = PERM_EXISTING_DIR;
6198 ptype = PERM_EXISTING_FILE;
6201 ptype = PERM_NEW_FILE;
6204 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6206 if (!NT_STATUS_IS_OK(status)) {
6210 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6211 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6212 smb_fname_str_dbg(smb_fname), (double)size,
6213 (unsigned int)set_owner, (unsigned int)set_grp,
6214 (int)raw_unixmode));
6216 sbuf = smb_fname->st;
6218 if (!VALID_STAT(sbuf)) {
6219 struct smb_filename *smb_fname_tmp = NULL;
6221 * The only valid use of this is to create character and block
6222 * devices, and named pipes. This is deprecated (IMHO) and
6223 * a new info level should be used for mknod. JRA.
6226 status = smb_unix_mknod(conn,
6230 if (!NT_STATUS_IS_OK(status)) {
6234 status = copy_smb_filename(talloc_tos(), smb_fname,
6236 if (!NT_STATUS_IS_OK(status)) {
6240 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6241 status = map_nt_error_from_unix(errno);
6242 TALLOC_FREE(smb_fname_tmp);
6243 SMB_VFS_UNLINK(conn, smb_fname);
6247 sbuf = smb_fname_tmp->st;
6248 TALLOC_FREE(smb_fname_tmp);
6250 /* Ensure we don't try and change anything else. */
6251 raw_unixmode = SMB_MODE_NO_CHANGE;
6252 size = get_file_size_stat(&sbuf);
6253 ft.atime = sbuf.st_ex_atime;
6254 ft.mtime = sbuf.st_ex_mtime;
6256 * We continue here as we might want to change the
6259 delete_on_fail = True;
6263 /* Horrible backwards compatibility hack as an old server bug
6264 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6268 size = get_file_size_stat(&sbuf);
6273 * Deal with the UNIX specific mode set.
6276 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6277 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6278 "setting mode 0%o for file %s\n",
6279 (unsigned int)unixmode,
6280 smb_fname_str_dbg(smb_fname)));
6281 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6282 return map_nt_error_from_unix(errno);
6287 * Deal with the UNIX specific uid set.
6290 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6291 (sbuf.st_ex_uid != set_owner)) {
6294 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6295 "changing owner %u for path %s\n",
6296 (unsigned int)set_owner,
6297 smb_fname_str_dbg(smb_fname)));
6299 if (S_ISLNK(sbuf.st_ex_mode)) {
6300 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6301 set_owner, (gid_t)-1);
6303 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6304 set_owner, (gid_t)-1);
6308 status = map_nt_error_from_unix(errno);
6309 if (delete_on_fail) {
6310 SMB_VFS_UNLINK(conn, smb_fname);
6317 * Deal with the UNIX specific gid set.
6320 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6321 (sbuf.st_ex_gid != set_grp)) {
6322 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6323 "changing group %u for file %s\n",
6324 (unsigned int)set_owner,
6325 smb_fname_str_dbg(smb_fname)));
6326 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6328 status = map_nt_error_from_unix(errno);
6329 if (delete_on_fail) {
6330 SMB_VFS_UNLINK(conn, smb_fname);
6336 /* Deal with any size changes. */
6338 status = smb_set_file_size(conn, req,
6343 if (!NT_STATUS_IS_OK(status)) {
6347 /* Deal with any time changes. */
6348 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6349 /* No change, don't cancel anything. */
6353 id = vfs_file_id_from_sbuf(conn, &sbuf);
6354 for(all_fsps = file_find_di_first(id); all_fsps;
6355 all_fsps = file_find_di_next(all_fsps)) {
6357 * We're setting the time explicitly for UNIX.
6358 * Cancel any pending changes over all handles.
6360 all_fsps->update_write_time_on_close = false;
6361 TALLOC_FREE(all_fsps->update_write_time_event);
6365 * Override the "setting_write_time"
6366 * parameter here as it almost does what
6367 * we need. Just remember if we modified
6368 * mtime and send the notify ourselves.
6370 if (null_timespec(ft.mtime)) {
6371 modify_mtime = false;
6374 status = smb_set_file_time(conn,
6380 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6381 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6386 /****************************************************************************
6387 Deal with SMB_SET_FILE_UNIX_INFO2.
6388 ****************************************************************************/
6390 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6391 struct smb_request *req,
6395 const struct smb_filename *smb_fname)
6401 if (total_data < 116) {
6402 return NT_STATUS_INVALID_PARAMETER;
6405 /* Start by setting all the fields that are common between UNIX_BASIC
6408 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6410 if (!NT_STATUS_IS_OK(status)) {
6414 smb_fflags = IVAL(pdata, 108);
6415 smb_fmask = IVAL(pdata, 112);
6417 /* NB: We should only attempt to alter the file flags if the client
6418 * sends a non-zero mask.
6420 if (smb_fmask != 0) {
6421 int stat_fflags = 0;
6423 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6424 smb_fmask, &stat_fflags)) {
6425 /* Client asked to alter a flag we don't understand. */
6426 return NT_STATUS_INVALID_PARAMETER;
6429 if (fsp && fsp->fh->fd != -1) {
6430 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6431 return NT_STATUS_NOT_SUPPORTED;
6433 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6434 stat_fflags) != 0) {
6435 return map_nt_error_from_unix(errno);
6440 /* XXX: need to add support for changing the create_time here. You
6441 * can do this for paths on Darwin with setattrlist(2). The right way
6442 * to hook this up is probably by extending the VFS utimes interface.
6445 return NT_STATUS_OK;
6448 /****************************************************************************
6449 Create a directory with POSIX semantics.
6450 ****************************************************************************/
6452 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6453 struct smb_request *req,
6457 SMB_STRUCT_STAT *psbuf,
6458 int *pdata_return_size)
6460 struct smb_filename *smb_fname;
6461 NTSTATUS status = NT_STATUS_OK;
6462 uint32 raw_unixmode = 0;
6463 uint32 mod_unixmode = 0;
6464 mode_t unixmode = (mode_t)0;
6465 files_struct *fsp = NULL;
6466 uint16 info_level_return = 0;
6468 char *pdata = *ppdata;
6470 if (total_data < 18) {
6471 return NT_STATUS_INVALID_PARAMETER;
6474 raw_unixmode = IVAL(pdata,8);
6475 /* Next 4 bytes are not yet defined. */
6477 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6478 if (!NT_STATUS_IS_OK(status)) {
6482 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6484 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6485 fname, (unsigned int)unixmode ));
6487 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6489 if (!NT_STATUS_IS_OK(status)) {
6493 status = SMB_VFS_CREATE_FILE(
6496 0, /* root_dir_fid */
6497 smb_fname, /* fname */
6498 FILE_READ_ATTRIBUTES, /* access_mask */
6499 FILE_SHARE_NONE, /* share_access */
6500 FILE_CREATE, /* create_disposition*/
6501 FILE_DIRECTORY_FILE, /* create_options */
6502 mod_unixmode, /* file_attributes */
6503 0, /* oplock_request */
6504 0, /* allocation_size */
6510 *psbuf = smb_fname->st;
6511 TALLOC_FREE(smb_fname);
6513 if (NT_STATUS_IS_OK(status)) {
6514 close_file(req, fsp, NORMAL_CLOSE);
6517 info_level_return = SVAL(pdata,16);
6519 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6520 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6521 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6522 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6524 *pdata_return_size = 12;
6527 /* Realloc the data size */
6528 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6529 if (*ppdata == NULL) {
6530 *pdata_return_size = 0;
6531 return NT_STATUS_NO_MEMORY;
6535 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6536 SSVAL(pdata,2,0); /* No fnum. */
6537 SIVAL(pdata,4,info); /* Was directory created. */
6539 switch (info_level_return) {
6540 case SMB_QUERY_FILE_UNIX_BASIC:
6541 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6542 SSVAL(pdata,10,0); /* Padding. */
6543 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6545 case SMB_QUERY_FILE_UNIX_INFO2:
6546 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6547 SSVAL(pdata,10,0); /* Padding. */
6548 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6551 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6552 SSVAL(pdata,10,0); /* Padding. */
6559 /****************************************************************************
6560 Open/Create a file with POSIX semantics.
6561 ****************************************************************************/
6563 static NTSTATUS smb_posix_open(connection_struct *conn,
6564 struct smb_request *req,
6568 SMB_STRUCT_STAT *psbuf,
6569 int *pdata_return_size)
6571 struct smb_filename *smb_fname = NULL;
6572 bool extended_oplock_granted = False;
6573 char *pdata = *ppdata;
6575 uint32 wire_open_mode = 0;
6576 uint32 raw_unixmode = 0;
6577 uint32 mod_unixmode = 0;
6578 uint32 create_disp = 0;
6579 uint32 access_mask = 0;
6580 uint32 create_options = 0;
6581 NTSTATUS status = NT_STATUS_OK;
6582 mode_t unixmode = (mode_t)0;
6583 files_struct *fsp = NULL;
6584 int oplock_request = 0;
6586 uint16 info_level_return = 0;
6588 if (total_data < 18) {
6589 return NT_STATUS_INVALID_PARAMETER;
6592 flags = IVAL(pdata,0);
6593 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6594 if (oplock_request) {
6595 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6598 wire_open_mode = IVAL(pdata,4);
6600 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6601 return smb_posix_mkdir(conn, req,
6609 switch (wire_open_mode & SMB_ACCMODE) {
6611 access_mask = FILE_READ_DATA;
6614 access_mask = FILE_WRITE_DATA;
6617 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6620 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6621 (unsigned int)wire_open_mode ));
6622 return NT_STATUS_INVALID_PARAMETER;
6625 wire_open_mode &= ~SMB_ACCMODE;
6627 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6628 create_disp = FILE_CREATE;
6629 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6630 create_disp = FILE_OVERWRITE_IF;
6631 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6632 create_disp = FILE_OPEN_IF;
6633 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6634 create_disp = FILE_OPEN;
6636 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6637 (unsigned int)wire_open_mode ));
6638 return NT_STATUS_INVALID_PARAMETER;
6641 raw_unixmode = IVAL(pdata,8);
6642 /* Next 4 bytes are not yet defined. */
6644 status = unix_perms_from_wire(conn,
6647 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6650 if (!NT_STATUS_IS_OK(status)) {
6654 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6656 if (wire_open_mode & SMB_O_SYNC) {
6657 create_options |= FILE_WRITE_THROUGH;
6659 if (wire_open_mode & SMB_O_APPEND) {
6660 access_mask |= FILE_APPEND_DATA;
6662 if (wire_open_mode & SMB_O_DIRECT) {
6663 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6666 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6668 (unsigned int)wire_open_mode,
6669 (unsigned int)unixmode ));
6671 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6673 if (!NT_STATUS_IS_OK(status)) {
6677 status = SMB_VFS_CREATE_FILE(
6680 0, /* root_dir_fid */
6681 smb_fname, /* fname */
6682 access_mask, /* access_mask */
6683 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6685 create_disp, /* create_disposition*/
6686 FILE_NON_DIRECTORY_FILE, /* create_options */
6687 mod_unixmode, /* file_attributes */
6688 oplock_request, /* oplock_request */
6689 0, /* allocation_size */
6695 *psbuf = smb_fname->st;
6696 TALLOC_FREE(smb_fname);
6698 if (!NT_STATUS_IS_OK(status)) {
6702 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6703 extended_oplock_granted = True;
6706 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6707 extended_oplock_granted = True;
6710 info_level_return = SVAL(pdata,16);
6712 /* Allocate the correct return size. */
6714 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6715 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6716 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6717 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6719 *pdata_return_size = 12;
6722 /* Realloc the data size */
6723 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6724 if (*ppdata == NULL) {
6725 close_file(req, fsp, ERROR_CLOSE);
6726 *pdata_return_size = 0;
6727 return NT_STATUS_NO_MEMORY;
6731 if (extended_oplock_granted) {
6732 if (flags & REQUEST_BATCH_OPLOCK) {
6733 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6735 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6737 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6738 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6740 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6743 SSVAL(pdata,2,fsp->fnum);
6744 SIVAL(pdata,4,info); /* Was file created etc. */
6746 switch (info_level_return) {
6747 case SMB_QUERY_FILE_UNIX_BASIC:
6748 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6749 SSVAL(pdata,10,0); /* padding. */
6750 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6752 case SMB_QUERY_FILE_UNIX_INFO2:
6753 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6754 SSVAL(pdata,10,0); /* padding. */
6755 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6758 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6759 SSVAL(pdata,10,0); /* padding. */
6762 return NT_STATUS_OK;
6765 /****************************************************************************
6766 Delete a file with POSIX semantics.
6767 ****************************************************************************/
6769 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6770 struct smb_request *req,
6773 struct smb_filename *smb_fname)
6775 NTSTATUS status = NT_STATUS_OK;
6776 files_struct *fsp = NULL;
6780 int create_options = 0;
6782 struct share_mode_lock *lck = NULL;
6784 if (total_data < 2) {
6785 return NT_STATUS_INVALID_PARAMETER;
6788 flags = SVAL(pdata,0);
6790 if (!VALID_STAT(smb_fname->st)) {
6791 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6794 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6795 !VALID_STAT_OF_DIR(smb_fname->st)) {
6796 return NT_STATUS_NOT_A_DIRECTORY;
6799 DEBUG(10,("smb_posix_unlink: %s %s\n",
6800 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6801 smb_fname_str_dbg(smb_fname)));
6803 if (VALID_STAT_OF_DIR(smb_fname->st)) {
6804 create_options |= FILE_DIRECTORY_FILE;
6807 status = SMB_VFS_CREATE_FILE(
6810 0, /* root_dir_fid */
6811 smb_fname, /* fname */
6812 DELETE_ACCESS, /* access_mask */
6813 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6815 FILE_OPEN, /* create_disposition*/
6816 create_options, /* create_options */
6817 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6818 0, /* oplock_request */
6819 0, /* allocation_size */
6825 if (!NT_STATUS_IS_OK(status)) {
6830 * Don't lie to client. If we can't really delete due to
6831 * non-POSIX opens return SHARING_VIOLATION.
6834 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6837 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6838 "lock for file %s\n", fsp->fsp_name));
6839 close_file(req, fsp, NORMAL_CLOSE);
6840 return NT_STATUS_INVALID_PARAMETER;
6844 * See if others still have the file open. If this is the case, then
6845 * don't delete. If all opens are POSIX delete we can set the delete
6846 * on close disposition.
6848 for (i=0; i<lck->num_share_modes; i++) {
6849 struct share_mode_entry *e = &lck->share_modes[i];
6850 if (is_valid_share_mode_entry(e)) {
6851 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6854 /* Fail with sharing violation. */
6855 close_file(req, fsp, NORMAL_CLOSE);
6857 return NT_STATUS_SHARING_VIOLATION;
6862 * Set the delete on close.
6864 status = smb_set_file_disposition_info(conn,
6870 if (!NT_STATUS_IS_OK(status)) {
6871 close_file(req, fsp, NORMAL_CLOSE);
6876 return close_file(req, fsp, NORMAL_CLOSE);
6879 /****************************************************************************
6880 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6881 ****************************************************************************/
6883 static void call_trans2setfilepathinfo(connection_struct *conn,
6884 struct smb_request *req,
6885 unsigned int tran_call,
6886 char **pparams, int total_params,
6887 char **ppdata, int total_data,
6888 unsigned int max_data_bytes)
6890 char *params = *pparams;
6891 char *pdata = *ppdata;
6893 SMB_STRUCT_STAT sbuf;
6895 struct smb_filename *smb_fname = NULL;
6896 files_struct *fsp = NULL;
6897 NTSTATUS status = NT_STATUS_OK;
6898 int data_return_size = 0;
6899 TALLOC_CTX *ctx = talloc_tos();
6902 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6906 if (tran_call == TRANSACT2_SETFILEINFO) {
6907 if (total_params < 4) {
6908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6912 fsp = file_fsp(req, SVAL(params,0));
6913 /* Basic check for non-null fsp. */
6914 if (!check_fsp_open(conn, req, fsp)) {
6917 info_level = SVAL(params,2);
6919 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6921 reply_nterror(req, NT_STATUS_NO_MEMORY);
6925 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
6927 if (!NT_STATUS_IS_OK(status)) {
6928 reply_nterror(req, status);
6932 if(fsp->is_directory || fsp->fh->fd == -1) {
6934 * This is actually a SETFILEINFO on a directory
6935 * handle (returned from an NT SMB). NT5.0 seems
6936 * to do this call. JRA.
6938 if (INFO_LEVEL_IS_UNIX(info_level)) {
6939 /* Always do lstat for UNIX calls. */
6940 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6941 DEBUG(3,("call_trans2setfilepathinfo: "
6942 "SMB_VFS_LSTAT of %s failed "
6944 smb_fname_str_dbg(smb_fname),
6946 reply_unixerror(req,ERRDOS,ERRbadpath);
6950 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6951 DEBUG(3,("call_trans2setfilepathinfo: "
6952 "fileinfo of %s failed (%s)\n",
6953 smb_fname_str_dbg(smb_fname),
6955 reply_unixerror(req,ERRDOS,ERRbadpath);
6959 } else if (fsp->print_file) {
6961 * Doing a DELETE_ON_CLOSE should cancel a print job.
6963 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6964 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6966 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6969 send_trans2_replies(conn, req, params, 2,
6974 reply_unixerror(req, ERRDOS, ERRbadpath);
6979 * Original code - this is an open file.
6981 if (!check_fsp(conn, req, fsp)) {
6985 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6986 DEBUG(3,("call_trans2setfilepathinfo: fstat "
6987 "of fnum %d failed (%s)\n", fsp->fnum,
6989 reply_unixerror(req, ERRDOS, ERRbadfid);
6995 if (total_params < 7) {
6996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7000 info_level = SVAL(params,0);
7001 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
7002 total_params - 6, STR_TERMINATE,
7004 if (!NT_STATUS_IS_OK(status)) {
7005 reply_nterror(req, status);
7009 status = filename_convert(ctx, conn,
7010 req->flags2 & FLAGS2_DFS_PATHNAMES,
7014 if (!NT_STATUS_IS_OK(status)) {
7015 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7016 reply_botherror(req,
7017 NT_STATUS_PATH_NOT_COVERED,
7018 ERRSRV, ERRbadpath);
7021 reply_nterror(req, status);
7025 if (INFO_LEVEL_IS_UNIX(info_level)) {
7027 * For CIFS UNIX extensions the target name may not exist.
7030 /* Always do lstat for UNIX calls. */
7031 SMB_VFS_LSTAT(conn, smb_fname);
7033 } else if (!VALID_STAT(smb_fname->st) &&
7034 SMB_VFS_STAT(conn, smb_fname)) {
7035 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7037 smb_fname_str_dbg(smb_fname),
7039 reply_unixerror(req, ERRDOS, ERRbadpath);
7044 /* Set sbuf for use below. */
7045 sbuf = smb_fname->st;
7047 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7048 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7052 if (!CAN_WRITE(conn)) {
7053 /* Allow POSIX opens. The open path will deny
7054 * any non-readonly opens. */
7055 if (info_level != SMB_POSIX_PATH_OPEN) {
7056 reply_doserror(req, ERRSRV, ERRaccess);
7061 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
7062 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
7064 /* Realloc the parameter size */
7065 *pparams = (char *)SMB_REALLOC(*pparams,2);
7066 if (*pparams == NULL) {
7067 reply_nterror(req, NT_STATUS_NO_MEMORY);
7074 switch (info_level) {
7076 case SMB_INFO_STANDARD:
7078 status = smb_set_info_standard(conn,
7086 case SMB_INFO_SET_EA:
7088 status = smb_info_set_ea(conn,
7096 case SMB_SET_FILE_BASIC_INFO:
7097 case SMB_FILE_BASIC_INFORMATION:
7099 status = smb_set_file_basic_info(conn,
7107 case SMB_FILE_ALLOCATION_INFORMATION:
7108 case SMB_SET_FILE_ALLOCATION_INFO:
7110 status = smb_set_file_allocation_info(conn, req,
7119 case SMB_FILE_END_OF_FILE_INFORMATION:
7120 case SMB_SET_FILE_END_OF_FILE_INFO:
7122 status = smb_set_file_end_of_file_info(conn, req,
7130 case SMB_FILE_DISPOSITION_INFORMATION:
7131 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7134 /* JRA - We used to just ignore this on a path ?
7135 * Shouldn't this be invalid level on a pathname
7138 if (tran_call != TRANSACT2_SETFILEINFO) {
7139 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7142 status = smb_set_file_disposition_info(conn,
7150 case SMB_FILE_POSITION_INFORMATION:
7152 status = smb_file_position_information(conn,
7159 /* From tridge Samba4 :
7160 * MODE_INFORMATION in setfileinfo (I have no
7161 * idea what "mode information" on a file is - it takes a value of 0,
7162 * 2, 4 or 6. What could it be?).
7165 case SMB_FILE_MODE_INFORMATION:
7167 status = smb_file_mode_information(conn,
7174 * CIFS UNIX extensions.
7177 case SMB_SET_FILE_UNIX_BASIC:
7179 status = smb_set_file_unix_basic(conn, req,
7187 case SMB_SET_FILE_UNIX_INFO2:
7189 status = smb_set_file_unix_info2(conn, req,
7197 case SMB_SET_FILE_UNIX_LINK:
7199 if (tran_call != TRANSACT2_SETPATHINFO) {
7200 /* We must have a pathname for this. */
7201 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7204 status = smb_set_file_unix_link(conn, req, pdata,
7209 case SMB_SET_FILE_UNIX_HLINK:
7211 if (tran_call != TRANSACT2_SETPATHINFO || smb_fname == NULL) {
7212 /* We must have a pathname for this. */
7213 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7216 status = smb_set_file_unix_hlink(conn, req,
7222 case SMB_FILE_RENAME_INFORMATION:
7224 status = smb_file_rename_information(conn, req,
7230 #if defined(HAVE_POSIX_ACLS)
7231 case SMB_SET_POSIX_ACL:
7233 status = smb_set_posix_acl(conn,
7243 case SMB_SET_POSIX_LOCK:
7245 if (tran_call != TRANSACT2_SETFILEINFO) {
7246 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7249 status = smb_set_posix_lock(conn, req,
7250 pdata, total_data, fsp);
7254 case SMB_POSIX_PATH_OPEN:
7256 if (tran_call != TRANSACT2_SETPATHINFO) {
7257 /* We must have a pathname for this. */
7258 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7262 status = smb_posix_open(conn, req,
7271 case SMB_POSIX_PATH_UNLINK:
7273 if (tran_call != TRANSACT2_SETPATHINFO) {
7274 /* We must have a pathname for this. */
7275 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7279 status = smb_posix_unlink(conn, req,
7287 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7291 if (!NT_STATUS_IS_OK(status)) {
7292 if (open_was_deferred(req->mid)) {
7293 /* We have re-scheduled this call. */
7296 if (blocking_lock_was_deferred(req->mid)) {
7297 /* We have re-scheduled this call. */
7300 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7301 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7302 ERRSRV, ERRbadpath);
7305 if (info_level == SMB_POSIX_PATH_OPEN) {
7306 reply_openerror(req, status);
7310 reply_nterror(req, status);
7315 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7321 /****************************************************************************
7322 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7323 ****************************************************************************/
7325 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7326 char **pparams, int total_params,
7327 char **ppdata, int total_data,
7328 unsigned int max_data_bytes)
7330 struct smb_filename *smb_dname = NULL;
7331 char *params = *pparams;
7332 char *pdata = *ppdata;
7333 char *directory = NULL;
7334 NTSTATUS status = NT_STATUS_OK;
7335 struct ea_list *ea_list = NULL;
7336 TALLOC_CTX *ctx = talloc_tos();
7338 if (!CAN_WRITE(conn)) {
7339 reply_doserror(req, ERRSRV, ERRaccess);
7343 if (total_params < 5) {
7344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7348 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7349 total_params - 4, STR_TERMINATE,
7351 if (!NT_STATUS_IS_OK(status)) {
7352 reply_nterror(req, status);
7356 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7358 status = filename_convert(ctx,
7360 req->flags2 & FLAGS2_DFS_PATHNAMES,
7365 if (!NT_STATUS_IS_OK(status)) {
7366 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7367 reply_botherror(req,
7368 NT_STATUS_PATH_NOT_COVERED,
7369 ERRSRV, ERRbadpath);
7372 reply_nterror(req, status);
7376 /* Any data in this call is an EA list. */
7377 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7378 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7383 * OS/2 workplace shell seems to send SET_EA requests of "null"
7384 * length (4 bytes containing IVAL 4).
7385 * They seem to have no effect. Bug #3212. JRA.
7388 if (total_data != 4) {
7389 if (total_data < 10) {
7390 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7394 if (IVAL(pdata,0) > total_data) {
7395 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7396 IVAL(pdata,0), (unsigned int)total_data));
7397 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7401 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7408 /* If total_data == 4 Windows doesn't care what values
7409 * are placed in that field, it just ignores them.
7410 * The System i QNTC IBM SMB client puts bad values here,
7411 * so ignore them. */
7413 status = create_directory(conn, req, smb_dname);
7415 if (!NT_STATUS_IS_OK(status)) {
7416 reply_nterror(req, status);
7420 /* Try and set any given EA. */
7422 status = set_ea(conn, NULL, smb_dname, ea_list);
7423 if (!NT_STATUS_IS_OK(status)) {
7424 reply_nterror(req, status);
7429 /* Realloc the parameter and data sizes */
7430 *pparams = (char *)SMB_REALLOC(*pparams,2);
7431 if(*pparams == NULL) {
7432 reply_nterror(req, NT_STATUS_NO_MEMORY);
7439 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7442 TALLOC_FREE(smb_dname);
7446 /****************************************************************************
7447 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7448 We don't actually do this - we just send a null response.
7449 ****************************************************************************/
7451 static void call_trans2findnotifyfirst(connection_struct *conn,
7452 struct smb_request *req,
7453 char **pparams, int total_params,
7454 char **ppdata, int total_data,
7455 unsigned int max_data_bytes)
7457 char *params = *pparams;
7460 if (total_params < 6) {
7461 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7465 info_level = SVAL(params,4);
7466 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7468 switch (info_level) {
7473 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7477 /* Realloc the parameter and data sizes */
7478 *pparams = (char *)SMB_REALLOC(*pparams,6);
7479 if (*pparams == NULL) {
7480 reply_nterror(req, NT_STATUS_NO_MEMORY);
7485 SSVAL(params,0,fnf_handle);
7486 SSVAL(params,2,0); /* No changes */
7487 SSVAL(params,4,0); /* No EA errors */
7494 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7499 /****************************************************************************
7500 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7501 changes). Currently this does nothing.
7502 ****************************************************************************/
7504 static void call_trans2findnotifynext(connection_struct *conn,
7505 struct smb_request *req,
7506 char **pparams, int total_params,
7507 char **ppdata, int total_data,
7508 unsigned int max_data_bytes)
7510 char *params = *pparams;
7512 DEBUG(3,("call_trans2findnotifynext\n"));
7514 /* Realloc the parameter and data sizes */
7515 *pparams = (char *)SMB_REALLOC(*pparams,4);
7516 if (*pparams == NULL) {
7517 reply_nterror(req, NT_STATUS_NO_MEMORY);
7522 SSVAL(params,0,0); /* No changes */
7523 SSVAL(params,2,0); /* No EA errors */
7525 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7530 /****************************************************************************
7531 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7532 ****************************************************************************/
7534 static void call_trans2getdfsreferral(connection_struct *conn,
7535 struct smb_request *req,
7536 char **pparams, int total_params,
7537 char **ppdata, int total_data,
7538 unsigned int max_data_bytes)
7540 char *params = *pparams;
7541 char *pathname = NULL;
7543 int max_referral_level;
7544 NTSTATUS status = NT_STATUS_OK;
7545 TALLOC_CTX *ctx = talloc_tos();
7547 DEBUG(10,("call_trans2getdfsreferral\n"));
7549 if (total_params < 3) {
7550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7554 max_referral_level = SVAL(params,0);
7556 if(!lp_host_msdfs()) {
7557 reply_doserror(req, ERRDOS, ERRbadfunc);
7561 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7562 total_params - 2, STR_TERMINATE);
7564 reply_nterror(req, NT_STATUS_NOT_FOUND);
7567 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7568 ppdata,&status)) < 0) {
7569 reply_nterror(req, status);
7573 SSVAL(req->inbuf, smb_flg2,
7574 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7575 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7580 #define LMCAT_SPL 0x53
7581 #define LMFUNC_GETJOBID 0x60
7583 /****************************************************************************
7584 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7585 ****************************************************************************/
7587 static void call_trans2ioctl(connection_struct *conn,
7588 struct smb_request *req,
7589 char **pparams, int total_params,
7590 char **ppdata, int total_data,
7591 unsigned int max_data_bytes)
7593 char *pdata = *ppdata;
7594 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7596 /* check for an invalid fid before proceeding */
7599 reply_doserror(req, ERRDOS, ERRbadfid);
7603 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7604 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7605 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7606 if (*ppdata == NULL) {
7607 reply_nterror(req, NT_STATUS_NO_MEMORY);
7612 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7613 CAN ACCEPT THIS IN UNICODE. JRA. */
7615 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7616 srvstr_push(pdata, req->flags2, pdata + 2,
7617 global_myname(), 15,
7618 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7619 srvstr_push(pdata, req->flags2, pdata+18,
7620 lp_servicename(SNUM(conn)), 13,
7621 STR_ASCII|STR_TERMINATE); /* Service name */
7622 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7627 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7628 reply_doserror(req, ERRSRV, ERRerror);
7631 /****************************************************************************
7632 Reply to a SMBfindclose (stop trans2 directory search).
7633 ****************************************************************************/
7635 void reply_findclose(struct smb_request *req)
7639 START_PROFILE(SMBfindclose);
7642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7643 END_PROFILE(SMBfindclose);
7647 dptr_num = SVALS(req->vwv+0, 0);
7649 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7651 dptr_close(&dptr_num);
7653 reply_outbuf(req, 0, 0);
7655 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7657 END_PROFILE(SMBfindclose);
7661 /****************************************************************************
7662 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7663 ****************************************************************************/
7665 void reply_findnclose(struct smb_request *req)
7669 START_PROFILE(SMBfindnclose);
7672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7673 END_PROFILE(SMBfindnclose);
7677 dptr_num = SVAL(req->vwv+0, 0);
7679 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7681 /* We never give out valid handles for a
7682 findnotifyfirst - so any dptr_num is ok here.
7685 reply_outbuf(req, 0, 0);
7687 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7689 END_PROFILE(SMBfindnclose);
7693 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7694 struct trans_state *state)
7696 if (Protocol >= PROTOCOL_NT1) {
7697 req->flags2 |= 0x40; /* IS_LONG_NAME */
7698 SSVAL(req->inbuf,smb_flg2,req->flags2);
7701 if (conn->encrypt_level == Required && !req->encrypted) {
7702 if (state->call != TRANSACT2_QFSINFO &&
7703 state->call != TRANSACT2_SETFSINFO) {
7704 DEBUG(0,("handle_trans2: encryption required "
7706 (unsigned int)state->call));
7707 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7712 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7714 /* Now we must call the relevant TRANS2 function */
7715 switch(state->call) {
7716 case TRANSACT2_OPEN:
7718 START_PROFILE(Trans2_open);
7719 call_trans2open(conn, req,
7720 &state->param, state->total_param,
7721 &state->data, state->total_data,
7722 state->max_data_return);
7723 END_PROFILE(Trans2_open);
7727 case TRANSACT2_FINDFIRST:
7729 START_PROFILE(Trans2_findfirst);
7730 call_trans2findfirst(conn, req,
7731 &state->param, state->total_param,
7732 &state->data, state->total_data,
7733 state->max_data_return);
7734 END_PROFILE(Trans2_findfirst);
7738 case TRANSACT2_FINDNEXT:
7740 START_PROFILE(Trans2_findnext);
7741 call_trans2findnext(conn, req,
7742 &state->param, state->total_param,
7743 &state->data, state->total_data,
7744 state->max_data_return);
7745 END_PROFILE(Trans2_findnext);
7749 case TRANSACT2_QFSINFO:
7751 START_PROFILE(Trans2_qfsinfo);
7752 call_trans2qfsinfo(conn, req,
7753 &state->param, state->total_param,
7754 &state->data, state->total_data,
7755 state->max_data_return);
7756 END_PROFILE(Trans2_qfsinfo);
7760 case TRANSACT2_SETFSINFO:
7762 START_PROFILE(Trans2_setfsinfo);
7763 call_trans2setfsinfo(conn, req,
7764 &state->param, state->total_param,
7765 &state->data, state->total_data,
7766 state->max_data_return);
7767 END_PROFILE(Trans2_setfsinfo);
7771 case TRANSACT2_QPATHINFO:
7772 case TRANSACT2_QFILEINFO:
7774 START_PROFILE(Trans2_qpathinfo);
7775 call_trans2qfilepathinfo(conn, req, state->call,
7776 &state->param, state->total_param,
7777 &state->data, state->total_data,
7778 state->max_data_return);
7779 END_PROFILE(Trans2_qpathinfo);
7783 case TRANSACT2_SETPATHINFO:
7784 case TRANSACT2_SETFILEINFO:
7786 START_PROFILE(Trans2_setpathinfo);
7787 call_trans2setfilepathinfo(conn, req, state->call,
7788 &state->param, state->total_param,
7789 &state->data, state->total_data,
7790 state->max_data_return);
7791 END_PROFILE(Trans2_setpathinfo);
7795 case TRANSACT2_FINDNOTIFYFIRST:
7797 START_PROFILE(Trans2_findnotifyfirst);
7798 call_trans2findnotifyfirst(conn, req,
7799 &state->param, state->total_param,
7800 &state->data, state->total_data,
7801 state->max_data_return);
7802 END_PROFILE(Trans2_findnotifyfirst);
7806 case TRANSACT2_FINDNOTIFYNEXT:
7808 START_PROFILE(Trans2_findnotifynext);
7809 call_trans2findnotifynext(conn, req,
7810 &state->param, state->total_param,
7811 &state->data, state->total_data,
7812 state->max_data_return);
7813 END_PROFILE(Trans2_findnotifynext);
7817 case TRANSACT2_MKDIR:
7819 START_PROFILE(Trans2_mkdir);
7820 call_trans2mkdir(conn, req,
7821 &state->param, state->total_param,
7822 &state->data, state->total_data,
7823 state->max_data_return);
7824 END_PROFILE(Trans2_mkdir);
7828 case TRANSACT2_GET_DFS_REFERRAL:
7830 START_PROFILE(Trans2_get_dfs_referral);
7831 call_trans2getdfsreferral(conn, req,
7832 &state->param, state->total_param,
7833 &state->data, state->total_data,
7834 state->max_data_return);
7835 END_PROFILE(Trans2_get_dfs_referral);
7839 case TRANSACT2_IOCTL:
7841 START_PROFILE(Trans2_ioctl);
7842 call_trans2ioctl(conn, req,
7843 &state->param, state->total_param,
7844 &state->data, state->total_data,
7845 state->max_data_return);
7846 END_PROFILE(Trans2_ioctl);
7851 /* Error in request */
7852 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7853 reply_doserror(req, ERRSRV,ERRerror);
7857 /****************************************************************************
7858 Reply to a SMBtrans2.
7859 ****************************************************************************/
7861 void reply_trans2(struct smb_request *req)
7863 connection_struct *conn = req->conn;
7868 unsigned int tran_call;
7869 struct trans_state *state;
7872 START_PROFILE(SMBtrans2);
7874 if (req->wct < 14) {
7875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7876 END_PROFILE(SMBtrans2);
7880 dsoff = SVAL(req->vwv+12, 0);
7881 dscnt = SVAL(req->vwv+11, 0);
7882 psoff = SVAL(req->vwv+10, 0);
7883 pscnt = SVAL(req->vwv+9, 0);
7884 tran_call = SVAL(req->vwv+14, 0);
7886 result = allow_new_trans(conn->pending_trans, req->mid);
7887 if (!NT_STATUS_IS_OK(result)) {
7888 DEBUG(2, ("Got invalid trans2 request: %s\n",
7889 nt_errstr(result)));
7890 reply_nterror(req, result);
7891 END_PROFILE(SMBtrans2);
7896 switch (tran_call) {
7897 /* List the allowed trans2 calls on IPC$ */
7898 case TRANSACT2_OPEN:
7899 case TRANSACT2_GET_DFS_REFERRAL:
7900 case TRANSACT2_QFILEINFO:
7901 case TRANSACT2_QFSINFO:
7902 case TRANSACT2_SETFSINFO:
7905 reply_doserror(req, ERRSRV, ERRaccess);
7906 END_PROFILE(SMBtrans2);
7911 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7912 DEBUG(0, ("talloc failed\n"));
7913 reply_nterror(req, NT_STATUS_NO_MEMORY);
7914 END_PROFILE(SMBtrans2);
7918 state->cmd = SMBtrans2;
7920 state->mid = req->mid;
7921 state->vuid = req->vuid;
7922 state->setup_count = SVAL(req->vwv+13, 0);
7923 state->setup = NULL;
7924 state->total_param = SVAL(req->vwv+0, 0);
7925 state->param = NULL;
7926 state->total_data = SVAL(req->vwv+1, 0);
7928 state->max_param_return = SVAL(req->vwv+2, 0);
7929 state->max_data_return = SVAL(req->vwv+3, 0);
7930 state->max_setup_return = SVAL(req->vwv+4, 0);
7931 state->close_on_completion = BITSETW(req->vwv+5, 0);
7932 state->one_way = BITSETW(req->vwv+5, 1);
7934 state->call = tran_call;
7936 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7937 is so as a sanity check */
7938 if (state->setup_count != 1) {
7940 * Need to have rc=0 for ioctl to get job id for OS/2.
7941 * Network printing will fail if function is not successful.
7942 * Similar function in reply.c will be used if protocol
7943 * is LANMAN1.0 instead of LM1.2X002.
7944 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7945 * outbuf doesn't have to be set(only job id is used).
7947 if ( (state->setup_count == 4)
7948 && (tran_call == TRANSACT2_IOCTL)
7949 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7950 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7951 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7953 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7954 DEBUG(2,("Transaction is %d\n",tran_call));
7956 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7957 END_PROFILE(SMBtrans2);
7962 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7965 if (state->total_data) {
7967 if (trans_oob(state->total_data, 0, dscnt)
7968 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7972 /* Can't use talloc here, the core routines do realloc on the
7973 * params and data. */
7974 state->data = (char *)SMB_MALLOC(state->total_data);
7975 if (state->data == NULL) {
7976 DEBUG(0,("reply_trans2: data malloc fail for %u "
7977 "bytes !\n", (unsigned int)state->total_data));
7979 reply_nterror(req, NT_STATUS_NO_MEMORY);
7980 END_PROFILE(SMBtrans2);
7984 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7987 if (state->total_param) {
7989 if (trans_oob(state->total_param, 0, pscnt)
7990 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7994 /* Can't use talloc here, the core routines do realloc on the
7995 * params and data. */
7996 state->param = (char *)SMB_MALLOC(state->total_param);
7997 if (state->param == NULL) {
7998 DEBUG(0,("reply_trans: param malloc fail for %u "
7999 "bytes !\n", (unsigned int)state->total_param));
8000 SAFE_FREE(state->data);
8002 reply_nterror(req, NT_STATUS_NO_MEMORY);
8003 END_PROFILE(SMBtrans2);
8007 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8010 state->received_data = dscnt;
8011 state->received_param = pscnt;
8013 if ((state->received_param == state->total_param) &&
8014 (state->received_data == state->total_data)) {
8016 handle_trans2(conn, req, state);
8018 SAFE_FREE(state->data);
8019 SAFE_FREE(state->param);
8021 END_PROFILE(SMBtrans2);
8025 DLIST_ADD(conn->pending_trans, state);
8027 /* We need to send an interim response then receive the rest
8028 of the parameter/data bytes */
8029 reply_outbuf(req, 0, 0);
8030 show_msg((char *)req->outbuf);
8031 END_PROFILE(SMBtrans2);
8036 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8037 SAFE_FREE(state->data);
8038 SAFE_FREE(state->param);
8040 END_PROFILE(SMBtrans2);
8041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8045 /****************************************************************************
8046 Reply to a SMBtranss2
8047 ****************************************************************************/
8049 void reply_transs2(struct smb_request *req)
8051 connection_struct *conn = req->conn;
8052 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8053 struct trans_state *state;
8055 START_PROFILE(SMBtranss2);
8057 show_msg((char *)req->inbuf);
8060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8061 END_PROFILE(SMBtranss2);
8065 for (state = conn->pending_trans; state != NULL;
8066 state = state->next) {
8067 if (state->mid == req->mid) {
8072 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8073 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8074 END_PROFILE(SMBtranss2);
8078 /* Revise state->total_param and state->total_data in case they have
8079 changed downwards */
8081 if (SVAL(req->vwv+0, 0) < state->total_param)
8082 state->total_param = SVAL(req->vwv+0, 0);
8083 if (SVAL(req->vwv+1, 0) < state->total_data)
8084 state->total_data = SVAL(req->vwv+1, 0);
8086 pcnt = SVAL(req->vwv+2, 0);
8087 poff = SVAL(req->vwv+3, 0);
8088 pdisp = SVAL(req->vwv+4, 0);
8090 dcnt = SVAL(req->vwv+5, 0);
8091 doff = SVAL(req->vwv+6, 0);
8092 ddisp = SVAL(req->vwv+7, 0);
8094 state->received_param += pcnt;
8095 state->received_data += dcnt;
8097 if ((state->received_data > state->total_data) ||
8098 (state->received_param > state->total_param))
8102 if (trans_oob(state->total_param, pdisp, pcnt)
8103 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8106 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8110 if (trans_oob(state->total_data, ddisp, dcnt)
8111 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8114 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8117 if ((state->received_param < state->total_param) ||
8118 (state->received_data < state->total_data)) {
8119 END_PROFILE(SMBtranss2);
8123 handle_trans2(conn, req, state);
8125 DLIST_REMOVE(conn->pending_trans, state);
8126 SAFE_FREE(state->data);
8127 SAFE_FREE(state->param);
8130 END_PROFILE(SMBtranss2);
8135 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8136 DLIST_REMOVE(conn->pending_trans, state);
8137 SAFE_FREE(state->data);
8138 SAFE_FREE(state->param);
8140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8141 END_PROFILE(SMBtranss2);