2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
247 *pnum_names = num_names;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list *ea_list_head = NULL;
266 if (!lp_ea_support(SNUM(conn))) {
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
285 listp = TALLOC_P(mem_ctx, struct ea_list);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
346 if (ea_list->ea.value.length > 65535) {
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
372 size_t total_ea_len = 0;
373 TALLOC_CTX *mem_ctx = NULL;
375 if (!lp_ea_support(SNUM(conn))) {
378 mem_ctx = talloc_tos();
379 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
383 /****************************************************************************
384 Ensure the EA name is case insensitive by matching any existing EA name.
385 ****************************************************************************/
387 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
390 TALLOC_CTX *mem_ctx = talloc_tos();
391 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
393 for (; ea_list; ea_list = ea_list->next) {
394 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
395 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
396 &unix_ea_name[5], ea_list->ea.name));
397 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
403 /****************************************************************************
404 Set or delete an extended attribute.
405 ****************************************************************************/
407 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
408 const struct smb_filename *smb_fname, struct ea_list *ea_list)
413 if (!lp_ea_support(SNUM(conn))) {
414 return NT_STATUS_EAS_NOT_SUPPORTED;
417 status = get_full_smb_filename(talloc_tos(), smb_fname,
419 if (!NT_STATUS_IS_OK(status)) {
423 for (;ea_list; ea_list = ea_list->next) {
425 fstring unix_ea_name;
427 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
428 fstrcat(unix_ea_name, ea_list->ea.name);
430 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
432 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
434 if (samba_private_attr_name(unix_ea_name)) {
435 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
436 return NT_STATUS_ACCESS_DENIED;
439 if (ea_list->ea.value.length == 0) {
440 /* Remove the attribute. */
441 if (fsp && (fsp->fh->fd != -1)) {
442 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
443 unix_ea_name, fsp->fsp_name));
444 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
446 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
447 unix_ea_name, fname));
448 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
451 /* Removing a non existent attribute always succeeds. */
452 if (ret == -1 && errno == ENOATTR) {
453 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
459 if (fsp && (fsp->fh->fd != -1)) {
460 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
461 unix_ea_name, fsp->fsp_name));
462 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
463 ea_list->ea.value.data, ea_list->ea.value.length, 0);
465 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
466 unix_ea_name, fname));
467 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
468 ea_list->ea.value.data, ea_list->ea.value.length, 0);
474 if (errno == ENOTSUP) {
475 return NT_STATUS_EAS_NOT_SUPPORTED;
478 return map_nt_error_from_unix(errno);
484 /****************************************************************************
485 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
486 ****************************************************************************/
488 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
490 struct ea_list *ea_list_head = NULL;
491 size_t converted_size, offset = 0;
493 while (offset + 2 < data_size) {
494 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
495 unsigned int namelen = CVAL(pdata,offset);
497 offset++; /* Go past the namelen byte. */
499 /* integer wrap paranioa. */
500 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
501 (offset > data_size) || (namelen > data_size) ||
502 (offset + namelen >= data_size)) {
505 /* Ensure the name is null terminated. */
506 if (pdata[offset + namelen] != '\0') {
509 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
511 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
512 "failed: %s", strerror(errno)));
518 offset += (namelen + 1); /* Go past the name + terminating zero. */
519 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
520 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
526 /****************************************************************************
527 Read one EA list entry from the buffer.
528 ****************************************************************************/
530 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
532 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
534 unsigned int namelen;
535 size_t converted_size;
545 eal->ea.flags = CVAL(pdata,0);
546 namelen = CVAL(pdata,1);
547 val_len = SVAL(pdata,2);
549 if (4 + namelen + 1 + val_len > data_size) {
553 /* Ensure the name is null terminated. */
554 if (pdata[namelen + 4] != '\0') {
557 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
558 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
565 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
566 if (!eal->ea.value.data) {
570 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
572 /* Ensure we're null terminated just in case we print the value. */
573 eal->ea.value.data[val_len] = '\0';
574 /* But don't count the null. */
575 eal->ea.value.length--;
578 *pbytes_used = 4 + namelen + 1 + val_len;
581 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
582 dump_data(10, eal->ea.value.data, eal->ea.value.length);
587 /****************************************************************************
588 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
589 ****************************************************************************/
591 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
593 struct ea_list *ea_list_head = NULL;
595 size_t bytes_used = 0;
597 while (offset < data_size) {
598 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
604 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
605 offset += bytes_used;
611 /****************************************************************************
612 Count the total EA size needed.
613 ****************************************************************************/
615 static size_t ea_list_size(struct ea_list *ealist)
618 struct ea_list *listp;
621 for (listp = ealist; listp; listp = listp->next) {
622 push_ascii_fstring(dos_ea_name, listp->ea.name);
623 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
625 /* Add on 4 for total length. */
633 /****************************************************************************
634 Return a union of EA's from a file list and a list of names.
635 The TALLOC context for the two lists *MUST* be identical as we steal
636 memory from one list to add to another. JRA.
637 ****************************************************************************/
639 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
641 struct ea_list *nlistp, *flistp;
643 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
644 for (flistp = file_list; flistp; flistp = flistp->next) {
645 if (strequal(nlistp->ea.name, flistp->ea.name)) {
651 /* Copy the data from this entry. */
652 nlistp->ea.flags = flistp->ea.flags;
653 nlistp->ea.value = flistp->ea.value;
656 nlistp->ea.flags = 0;
657 ZERO_STRUCT(nlistp->ea.value);
661 *total_ea_len = ea_list_size(name_list);
665 /****************************************************************************
666 Send the required number of replies back.
667 We assume all fields other than the data fields are
668 set correctly for the type of call.
669 HACK ! Always assumes smb_setup field is zero.
670 ****************************************************************************/
672 void send_trans2_replies(connection_struct *conn,
673 struct smb_request *req,
680 /* As we are using a protocol > LANMAN1 then the max_send
681 variable must have been set in the sessetupX call.
682 This takes precedence over the max_xmit field in the
683 global struct. These different max_xmit variables should
684 be merged as this is now too confusing */
686 int data_to_send = datasize;
687 int params_to_send = paramsize;
689 const char *pp = params;
690 const char *pd = pdata;
691 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
692 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
693 int data_alignment_offset = 0;
694 bool overflow = False;
695 struct smbd_server_connection *sconn = smbd_server_conn;
696 int max_send = sconn->smb1.sessions.max_send;
698 /* Modify the data_to_send and datasize and set the error if
699 we're trying to send more than max_data_bytes. We still send
700 the part of the packet(s) that fit. Strange, but needed
703 if (max_data_bytes > 0 && datasize > max_data_bytes) {
704 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
705 max_data_bytes, datasize ));
706 datasize = data_to_send = max_data_bytes;
710 /* If there genuinely are no parameters or data to send just send the empty packet */
712 if(params_to_send == 0 && data_to_send == 0) {
713 reply_outbuf(req, 10, 0);
714 show_msg((char *)req->outbuf);
715 if (!srv_send_smb(smbd_server_fd(),
718 IS_CONN_ENCRYPTED(conn),
720 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
722 TALLOC_FREE(req->outbuf);
726 /* When sending params and data ensure that both are nicely aligned */
727 /* Only do this alignment when there is also data to send - else
728 can cause NT redirector problems. */
730 if (((params_to_send % 4) != 0) && (data_to_send != 0))
731 data_alignment_offset = 4 - (params_to_send % 4);
733 /* Space is bufsize minus Netbios over TCP header minus SMB header */
734 /* The alignment_offset is to align the param bytes on an even byte
735 boundary. NT 4.0 Beta needs this to work correctly. */
737 useable_space = max_send - (smb_size
740 + data_alignment_offset);
742 if (useable_space < 0) {
743 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
744 "= %d!!!", useable_space));
745 exit_server_cleanly("send_trans2_replies: Not enough space");
748 while (params_to_send || data_to_send) {
749 /* Calculate whether we will totally or partially fill this packet */
751 total_sent_thistime = params_to_send + data_to_send;
753 /* We can never send more than useable_space */
755 * Note that 'useable_space' does not include the alignment offsets,
756 * but we must include the alignment offsets in the calculation of
757 * the length of the data we send over the wire, as the alignment offsets
758 * are sent here. Fix from Marc_Jacobsen@hp.com.
761 total_sent_thistime = MIN(total_sent_thistime, useable_space);
763 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
764 + data_alignment_offset);
767 * We might have SMBtrans2s in req which was transferred to
768 * the outbuf, fix that.
770 SCVAL(req->outbuf, smb_com, SMBtrans2);
772 /* Set total params and data to be sent */
773 SSVAL(req->outbuf,smb_tprcnt,paramsize);
774 SSVAL(req->outbuf,smb_tdrcnt,datasize);
776 /* Calculate how many parameters and data we can fit into
777 * this packet. Parameters get precedence
780 params_sent_thistime = MIN(params_to_send,useable_space);
781 data_sent_thistime = useable_space - params_sent_thistime;
782 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
784 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
786 /* smb_proff is the offset from the start of the SMB header to the
787 parameter bytes, however the first 4 bytes of outbuf are
788 the Netbios over TCP header. Thus use smb_base() to subtract
789 them from the calculation */
791 SSVAL(req->outbuf,smb_proff,
792 ((smb_buf(req->outbuf)+alignment_offset)
793 - smb_base(req->outbuf)));
795 if(params_sent_thistime == 0)
796 SSVAL(req->outbuf,smb_prdisp,0);
798 /* Absolute displacement of param bytes sent in this packet */
799 SSVAL(req->outbuf,smb_prdisp,pp - params);
801 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
802 if(data_sent_thistime == 0) {
803 SSVAL(req->outbuf,smb_droff,0);
804 SSVAL(req->outbuf,smb_drdisp, 0);
806 /* The offset of the data bytes is the offset of the
807 parameter bytes plus the number of parameters being sent this time */
808 SSVAL(req->outbuf, smb_droff,
809 ((smb_buf(req->outbuf)+alignment_offset)
810 - smb_base(req->outbuf))
811 + params_sent_thistime + data_alignment_offset);
812 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
815 /* Initialize the padding for alignment */
817 if (alignment_offset != 0) {
818 memset(smb_buf(req->outbuf), 0, alignment_offset);
821 /* Copy the param bytes into the packet */
823 if(params_sent_thistime) {
824 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
825 params_sent_thistime);
828 /* Copy in the data bytes */
829 if(data_sent_thistime) {
830 if (data_alignment_offset != 0) {
831 memset((smb_buf(req->outbuf)+alignment_offset+
832 params_sent_thistime), 0,
833 data_alignment_offset);
835 memcpy(smb_buf(req->outbuf)+alignment_offset
836 +params_sent_thistime+data_alignment_offset,
837 pd,data_sent_thistime);
840 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
841 params_sent_thistime, data_sent_thistime, useable_space));
842 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
843 params_to_send, data_to_send, paramsize, datasize));
846 error_packet_set((char *)req->outbuf,
847 ERRDOS,ERRbufferoverflow,
848 STATUS_BUFFER_OVERFLOW,
852 /* Send the packet */
853 show_msg((char *)req->outbuf);
854 if (!srv_send_smb(smbd_server_fd(),
857 IS_CONN_ENCRYPTED(conn),
859 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
861 TALLOC_FREE(req->outbuf);
863 pp += params_sent_thistime;
864 pd += data_sent_thistime;
866 params_to_send -= params_sent_thistime;
867 data_to_send -= data_sent_thistime;
870 if(params_to_send < 0 || data_to_send < 0) {
871 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
872 params_to_send, data_to_send));
880 /****************************************************************************
881 Reply to a TRANSACT2_OPEN.
882 ****************************************************************************/
884 static void call_trans2open(connection_struct *conn,
885 struct smb_request *req,
886 char **pparams, int total_params,
887 char **ppdata, int total_data,
888 unsigned int max_data_bytes)
890 struct smb_filename *smb_fname = NULL;
891 char *params = *pparams;
892 char *pdata = *ppdata;
897 bool return_additional_info;
910 struct ea_list *ea_list = NULL;
915 uint32 create_disposition;
916 uint32 create_options = 0;
917 TALLOC_CTX *ctx = talloc_tos();
920 * Ensure we have enough parameters to perform the operation.
923 if (total_params < 29) {
924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
928 flags = SVAL(params, 0);
929 deny_mode = SVAL(params, 2);
930 open_attr = SVAL(params,6);
931 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
932 if (oplock_request) {
933 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
937 return_additional_info = BITSETW(params,0);
938 open_sattr = SVAL(params, 4);
939 open_time = make_unix_date3(params+8);
941 open_ofun = SVAL(params,12);
942 open_size = IVAL(params,14);
946 reply_doserror(req, ERRSRV, ERRaccess);
950 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
951 total_params - 28, STR_TERMINATE,
953 if (!NT_STATUS_IS_OK(status)) {
954 reply_nterror(req, status);
958 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
959 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
960 (unsigned int)open_ofun, open_size));
962 status = filename_convert(ctx,
964 req->flags2 & FLAGS2_DFS_PATHNAMES,
968 if (!NT_STATUS_IS_OK(status)) {
969 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
971 NT_STATUS_PATH_NOT_COVERED,
975 reply_nterror(req, status);
979 if (open_ofun == 0) {
980 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
984 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
989 reply_doserror(req, ERRDOS, ERRbadaccess);
993 /* Any data in this call is an EA list. */
994 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
995 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
999 if (total_data != 4) {
1000 if (total_data < 10) {
1001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1005 if (IVAL(pdata,0) > total_data) {
1006 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1007 IVAL(pdata,0), (unsigned int)total_data));
1008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1012 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1018 } else if (IVAL(pdata,0) != 4) {
1019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1023 status = SMB_VFS_CREATE_FILE(
1026 0, /* root_dir_fid */
1027 smb_fname, /* fname */
1028 access_mask, /* access_mask */
1029 share_mode, /* share_access */
1030 create_disposition, /* create_disposition*/
1031 create_options, /* create_options */
1032 open_attr, /* file_attributes */
1033 oplock_request, /* oplock_request */
1034 open_size, /* allocation_size */
1036 ea_list, /* ea_list */
1038 &smb_action); /* psbuf */
1040 if (!NT_STATUS_IS_OK(status)) {
1041 if (open_was_deferred(req->mid)) {
1042 /* We have re-scheduled this call. */
1045 reply_openerror(req, status);
1049 size = get_file_size_stat(&smb_fname->st);
1050 fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st);
1051 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1052 inode = smb_fname->st.st_ex_ino;
1054 close_file(req, fsp, ERROR_CLOSE);
1055 reply_doserror(req, ERRDOS,ERRnoaccess);
1059 /* Realloc the size of parameters and data we will return */
1060 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1061 if(*pparams == NULL ) {
1062 reply_nterror(req, NT_STATUS_NO_MEMORY);
1067 SSVAL(params,0,fsp->fnum);
1068 SSVAL(params,2,fattr);
1069 srv_put_dos_date2(params,4, mtime);
1070 SIVAL(params,8, (uint32)size);
1071 SSVAL(params,12,deny_mode);
1072 SSVAL(params,14,0); /* open_type - file or directory. */
1073 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1075 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1076 smb_action |= EXTENDED_OPLOCK_GRANTED;
1079 SSVAL(params,18,smb_action);
1082 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1084 SIVAL(params,20,inode);
1085 SSVAL(params,24,0); /* Padding. */
1087 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1088 SIVAL(params, 26, ea_size);
1090 SIVAL(params, 26, 0);
1093 /* Send the required number of replies */
1094 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1096 TALLOC_FREE(smb_fname);
1099 /*********************************************************
1100 Routine to check if a given string matches exactly.
1101 as a special case a mask of "." does NOT match. That
1102 is required for correct wildcard semantics
1103 Case can be significant or not.
1104 **********************************************************/
1106 static bool exact_match(connection_struct *conn,
1110 if (mask[0] == '.' && mask[1] == 0)
1112 if (dptr_has_wild(conn->dirptr)) {
1115 if (conn->case_sensitive)
1116 return strcmp(str,mask)==0;
1118 return StrCaseCmp(str,mask) == 0;
1121 /****************************************************************************
1122 Return the filetype for UNIX extensions.
1123 ****************************************************************************/
1125 static uint32 unix_filetype(mode_t mode)
1128 return UNIX_TYPE_FILE;
1129 else if(S_ISDIR(mode))
1130 return UNIX_TYPE_DIR;
1132 else if(S_ISLNK(mode))
1133 return UNIX_TYPE_SYMLINK;
1136 else if(S_ISCHR(mode))
1137 return UNIX_TYPE_CHARDEV;
1140 else if(S_ISBLK(mode))
1141 return UNIX_TYPE_BLKDEV;
1144 else if(S_ISFIFO(mode))
1145 return UNIX_TYPE_FIFO;
1148 else if(S_ISSOCK(mode))
1149 return UNIX_TYPE_SOCKET;
1152 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1153 return UNIX_TYPE_UNKNOWN;
1156 /****************************************************************************
1157 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1158 ****************************************************************************/
1160 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1162 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1163 const SMB_STRUCT_STAT *psbuf,
1165 enum perm_type ptype,
1170 if (perms == SMB_MODE_NO_CHANGE) {
1171 if (!VALID_STAT(*psbuf)) {
1172 return NT_STATUS_INVALID_PARAMETER;
1174 *ret_perms = psbuf->st_ex_mode;
1175 return NT_STATUS_OK;
1179 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1180 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1181 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1182 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1183 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1184 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1185 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1186 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1187 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1189 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1192 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1195 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1200 /* Apply mode mask */
1201 ret &= lp_create_mask(SNUM(conn));
1202 /* Add in force bits */
1203 ret |= lp_force_create_mode(SNUM(conn));
1206 ret &= lp_dir_mask(SNUM(conn));
1207 /* Add in force bits */
1208 ret |= lp_force_dir_mode(SNUM(conn));
1210 case PERM_EXISTING_FILE:
1211 /* Apply mode mask */
1212 ret &= lp_security_mask(SNUM(conn));
1213 /* Add in force bits */
1214 ret |= lp_force_security_mode(SNUM(conn));
1216 case PERM_EXISTING_DIR:
1217 /* Apply mode mask */
1218 ret &= lp_dir_security_mask(SNUM(conn));
1219 /* Add in force bits */
1220 ret |= lp_force_dir_security_mode(SNUM(conn));
1225 return NT_STATUS_OK;
1228 /****************************************************************************
1229 Needed to show the msdfs symlinks as directories. Modifies psbuf
1230 to be a directory if it's a msdfs link.
1231 ****************************************************************************/
1233 static bool check_msdfs_link(connection_struct *conn,
1234 const char *pathname,
1235 SMB_STRUCT_STAT *psbuf)
1237 int saved_errno = errno;
1238 if(lp_host_msdfs() &&
1239 lp_msdfs_root(SNUM(conn)) &&
1240 is_msdfs_link(conn, pathname, psbuf)) {
1242 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1245 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1246 errno = saved_errno;
1249 errno = saved_errno;
1254 /****************************************************************************
1255 Get a level dependent lanman2 dir entry.
1256 ****************************************************************************/
1258 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1259 connection_struct *conn,
1261 const char *path_mask,
1264 int requires_resume_key,
1270 int space_remaining,
1272 bool *got_exact_match,
1273 int *last_entry_off,
1274 struct ea_list *name_list)
1278 SMB_STRUCT_STAT sbuf;
1279 const char *mask = NULL;
1280 char *pathreal = NULL;
1282 char *p, *q, *pdata = *ppdata;
1286 SMB_OFF_T file_size = 0;
1287 uint64_t allocation_size = 0;
1289 struct timespec mdate_ts, adate_ts, create_date_ts;
1290 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1292 char *last_entry_ptr;
1294 uint32 nt_extmode; /* Used for NT connections instead of mode */
1295 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1296 bool check_mangled_names = lp_manglednames(conn->params);
1297 char mangled_name[13]; /* mangled 8.3 name. */
1299 *out_of_space = False;
1300 *got_exact_match = False;
1302 ZERO_STRUCT(mdate_ts);
1303 ZERO_STRUCT(adate_ts);
1304 ZERO_STRUCT(create_date_ts);
1306 if (!conn->dirptr) {
1310 p = strrchr_m(path_mask,'/');
1313 mask = talloc_strdup(ctx,"*.*");
1323 bool ms_dfs_link = False;
1325 /* Needed if we run out of space */
1326 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1327 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1330 * Due to bugs in NT client redirectors we are not using
1331 * resume keys any more - set them to zero.
1332 * Check out the related comments in findfirst/findnext.
1338 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1339 (long)conn->dirptr,curr_dirpos));
1346 * fname may get mangled, dname is never mangled.
1347 * Whenever we're accessing the filesystem we use
1348 * pathreal which is composed from dname.
1354 /* Mangle fname if it's an illegal name. */
1355 if (mangle_must_mangle(dname,conn->params)) {
1356 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1358 continue; /* Error - couldn't mangle. */
1360 fname = talloc_strdup(ctx, mangled_name);
1366 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1367 got_match = mask_match(fname, mask, conn->case_sensitive);
1370 if(!got_match && check_mangled_names &&
1371 !mangle_is_8_3(fname, False, conn->params)) {
1373 * It turns out that NT matches wildcards against
1374 * both long *and* short names. This may explain some
1375 * of the wildcard wierdness from old DOS clients
1376 * that some people have been seeing.... JRA.
1378 /* Force the mangling into 8.3. */
1379 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1381 continue; /* Error - couldn't mangle. */
1384 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1385 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1390 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1392 if (dont_descend && !isdots) {
1399 pathreal = talloc_asprintf(ctx,
1404 pathreal = talloc_asprintf(ctx,
1415 if (INFO_LEVEL_IS_UNIX(info_level)) {
1416 if (vfs_lstat_smb_fname(conn, pathreal,
1418 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1419 pathreal,strerror(errno)));
1420 TALLOC_FREE(pathreal);
1424 } else if (!VALID_STAT(sbuf) &&
1425 vfs_stat_smb_fname(conn, pathreal,
1427 /* Needed to show the msdfs symlinks as
1430 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1432 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1433 pathreal,strerror(errno)));
1434 TALLOC_FREE(pathreal);
1441 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1443 mode = dos_mode(conn,pathreal,&sbuf);
1446 if (!dir_check_ftype(conn,mode,dirtype)) {
1447 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1448 TALLOC_FREE(pathreal);
1453 if (!(mode & aDIR)) {
1454 file_size = get_file_size_stat(&sbuf);
1456 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1458 mdate_ts = sbuf.st_ex_mtime;
1459 adate_ts = sbuf.st_ex_atime;
1460 create_date_ts = sbuf.st_ex_btime;
1462 if (ask_sharemode) {
1463 struct timespec write_time_ts;
1464 struct file_id fileid;
1466 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1467 get_file_infos(fileid, NULL, &write_time_ts);
1468 if (!null_timespec(write_time_ts)) {
1469 mdate_ts = write_time_ts;
1473 if (lp_dos_filetime_resolution(SNUM(conn))) {
1474 dos_filetime_timespec(&create_date_ts);
1475 dos_filetime_timespec(&mdate_ts);
1476 dos_filetime_timespec(&adate_ts);
1479 create_date = convert_timespec_to_time_t(create_date_ts);
1480 mdate = convert_timespec_to_time_t(mdate_ts);
1481 adate = convert_timespec_to_time_t(adate_ts);
1483 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1488 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1498 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1500 switch (info_level) {
1501 case SMB_FIND_INFO_STANDARD:
1502 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1503 if(requires_resume_key) {
1507 srv_put_dos_date2(p,0,create_date);
1508 srv_put_dos_date2(p,4,adate);
1509 srv_put_dos_date2(p,8,mdate);
1510 SIVAL(p,12,(uint32)file_size);
1511 SIVAL(p,16,(uint32)allocation_size);
1515 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1516 p += ucs2_align(base_data, p, 0);
1518 len = srvstr_push(base_data, flags2, p,
1519 fname, PTR_DIFF(end_data, p),
1521 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1523 SCVAL(nameptr, -1, len - 2);
1525 SCVAL(nameptr, -1, 0);
1529 SCVAL(nameptr, -1, len - 1);
1531 SCVAL(nameptr, -1, 0);
1537 case SMB_FIND_EA_SIZE:
1538 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1539 if(requires_resume_key) {
1543 srv_put_dos_date2(p,0,create_date);
1544 srv_put_dos_date2(p,4,adate);
1545 srv_put_dos_date2(p,8,mdate);
1546 SIVAL(p,12,(uint32)file_size);
1547 SIVAL(p,16,(uint32)allocation_size);
1550 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1551 SIVAL(p,22,ea_size); /* Extended attributes */
1555 len = srvstr_push(base_data, flags2,
1556 p, fname, PTR_DIFF(end_data, p),
1557 STR_TERMINATE | STR_NOALIGN);
1558 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1571 SCVAL(nameptr,0,len);
1573 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1576 case SMB_FIND_EA_LIST:
1578 struct ea_list *file_list = NULL;
1581 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1585 if(requires_resume_key) {
1589 srv_put_dos_date2(p,0,create_date);
1590 srv_put_dos_date2(p,4,adate);
1591 srv_put_dos_date2(p,8,mdate);
1592 SIVAL(p,12,(uint32)file_size);
1593 SIVAL(p,16,(uint32)allocation_size);
1595 p += 22; /* p now points to the EA area. */
1597 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1598 name_list = ea_list_union(name_list, file_list, &ea_len);
1600 /* We need to determine if this entry will fit in the space available. */
1601 /* Max string size is 255 bytes. */
1602 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1603 /* Move the dirptr back to prev_dirpos */
1604 dptr_SeekDir(conn->dirptr, prev_dirpos);
1605 *out_of_space = True;
1606 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1607 return False; /* Not finished - just out of space */
1610 /* Push the ea_data followed by the name. */
1611 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1613 len = srvstr_push(base_data, flags2,
1614 p + 1, fname, PTR_DIFF(end_data, p+1),
1615 STR_TERMINATE | STR_NOALIGN);
1616 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1629 SCVAL(nameptr,0,len);
1631 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1635 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1636 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1637 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1639 SIVAL(p,0,reskey); p += 4;
1640 put_long_date_timespec(p,create_date_ts); p += 8;
1641 put_long_date_timespec(p,adate_ts); p += 8;
1642 put_long_date_timespec(p,mdate_ts); p += 8;
1643 put_long_date_timespec(p,mdate_ts); p += 8;
1644 SOFF_T(p,0,file_size); p += 8;
1645 SOFF_T(p,0,allocation_size); p += 8;
1646 SIVAL(p,0,nt_extmode); p += 4;
1647 q = p; p += 4; /* q is placeholder for name length. */
1649 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1650 SIVAL(p,0,ea_size); /* Extended attributes */
1653 /* Clear the short name buffer. This is
1654 * IMPORTANT as not doing so will trigger
1655 * a Win2k client bug. JRA.
1657 if (!was_8_3 && check_mangled_names) {
1658 if (!name_to_8_3(fname,mangled_name,True,
1660 /* Error - mangle failed ! */
1661 memset(mangled_name,'\0',12);
1663 mangled_name[12] = 0;
1664 len = srvstr_push(base_data, flags2,
1665 p+2, mangled_name, 24,
1666 STR_UPPER|STR_UNICODE);
1668 memset(p + 2 + len,'\0',24 - len);
1675 len = srvstr_push(base_data, flags2, p,
1676 fname, PTR_DIFF(end_data, p),
1677 STR_TERMINATE_ASCII);
1680 SIVAL(p,0,0); /* Ensure any padding is null. */
1681 len = PTR_DIFF(p, pdata);
1682 len = (len + 3) & ~3;
1687 case SMB_FIND_FILE_DIRECTORY_INFO:
1688 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1690 SIVAL(p,0,reskey); p += 4;
1691 put_long_date_timespec(p,create_date_ts); p += 8;
1692 put_long_date_timespec(p,adate_ts); p += 8;
1693 put_long_date_timespec(p,mdate_ts); p += 8;
1694 put_long_date_timespec(p,mdate_ts); p += 8;
1695 SOFF_T(p,0,file_size); p += 8;
1696 SOFF_T(p,0,allocation_size); p += 8;
1697 SIVAL(p,0,nt_extmode); p += 4;
1698 len = srvstr_push(base_data, flags2,
1699 p + 4, fname, PTR_DIFF(end_data, p+4),
1700 STR_TERMINATE_ASCII);
1703 SIVAL(p,0,0); /* Ensure any padding is null. */
1704 len = PTR_DIFF(p, pdata);
1705 len = (len + 3) & ~3;
1710 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1711 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1713 SIVAL(p,0,reskey); p += 4;
1714 put_long_date_timespec(p,create_date_ts); p += 8;
1715 put_long_date_timespec(p,adate_ts); p += 8;
1716 put_long_date_timespec(p,mdate_ts); p += 8;
1717 put_long_date_timespec(p,mdate_ts); p += 8;
1718 SOFF_T(p,0,file_size); p += 8;
1719 SOFF_T(p,0,allocation_size); p += 8;
1720 SIVAL(p,0,nt_extmode); p += 4;
1721 q = p; p += 4; /* q is placeholder for name length. */
1723 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1724 SIVAL(p,0,ea_size); /* Extended attributes */
1727 len = srvstr_push(base_data, flags2, p,
1728 fname, PTR_DIFF(end_data, p),
1729 STR_TERMINATE_ASCII);
1733 SIVAL(p,0,0); /* Ensure any padding is null. */
1734 len = PTR_DIFF(p, pdata);
1735 len = (len + 3) & ~3;
1740 case SMB_FIND_FILE_NAMES_INFO:
1741 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1743 SIVAL(p,0,reskey); p += 4;
1745 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1746 acl on a dir (tridge) */
1747 len = srvstr_push(base_data, flags2, p,
1748 fname, PTR_DIFF(end_data, p),
1749 STR_TERMINATE_ASCII);
1752 SIVAL(p,0,0); /* Ensure any padding is null. */
1753 len = PTR_DIFF(p, pdata);
1754 len = (len + 3) & ~3;
1759 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1760 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1762 SIVAL(p,0,reskey); p += 4;
1763 put_long_date_timespec(p,create_date_ts); p += 8;
1764 put_long_date_timespec(p,adate_ts); p += 8;
1765 put_long_date_timespec(p,mdate_ts); p += 8;
1766 put_long_date_timespec(p,mdate_ts); p += 8;
1767 SOFF_T(p,0,file_size); p += 8;
1768 SOFF_T(p,0,allocation_size); p += 8;
1769 SIVAL(p,0,nt_extmode); p += 4;
1770 q = p; p += 4; /* q is placeholder for name length. */
1772 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1773 SIVAL(p,0,ea_size); /* Extended attributes */
1776 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1777 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1778 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1779 len = srvstr_push(base_data, flags2, p,
1780 fname, PTR_DIFF(end_data, p),
1781 STR_TERMINATE_ASCII);
1784 SIVAL(p,0,0); /* Ensure any padding is null. */
1785 len = PTR_DIFF(p, pdata);
1786 len = (len + 3) & ~3;
1791 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1792 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1793 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1795 SIVAL(p,0,reskey); p += 4;
1796 put_long_date_timespec(p,create_date_ts); p += 8;
1797 put_long_date_timespec(p,adate_ts); p += 8;
1798 put_long_date_timespec(p,mdate_ts); p += 8;
1799 put_long_date_timespec(p,mdate_ts); p += 8;
1800 SOFF_T(p,0,file_size); p += 8;
1801 SOFF_T(p,0,allocation_size); p += 8;
1802 SIVAL(p,0,nt_extmode); p += 4;
1803 q = p; p += 4; /* q is placeholder for name length */
1805 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1806 SIVAL(p,0,ea_size); /* Extended attributes */
1809 /* Clear the short name buffer. This is
1810 * IMPORTANT as not doing so will trigger
1811 * a Win2k client bug. JRA.
1813 if (!was_8_3 && check_mangled_names) {
1814 if (!name_to_8_3(fname,mangled_name,True,
1816 /* Error - mangle failed ! */
1817 memset(mangled_name,'\0',12);
1819 mangled_name[12] = 0;
1820 len = srvstr_push(base_data, flags2,
1821 p+2, mangled_name, 24,
1822 STR_UPPER|STR_UNICODE);
1825 memset(p + 2 + len,'\0',24 - len);
1832 SSVAL(p,0,0); p += 2; /* Reserved ? */
1833 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1834 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1835 len = srvstr_push(base_data, flags2, p,
1836 fname, PTR_DIFF(end_data, p),
1837 STR_TERMINATE_ASCII);
1840 SIVAL(p,0,0); /* Ensure any padding is null. */
1841 len = PTR_DIFF(p, pdata);
1842 len = (len + 3) & ~3;
1847 /* CIFS UNIX Extension. */
1849 case SMB_FIND_FILE_UNIX:
1850 case SMB_FIND_FILE_UNIX_INFO2:
1852 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1854 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1856 if (info_level == SMB_FIND_FILE_UNIX) {
1857 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1858 p = store_file_unix_basic(conn, p,
1860 len = srvstr_push(base_data, flags2, p,
1861 fname, PTR_DIFF(end_data, p),
1864 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1865 p = store_file_unix_basic_info2(conn, p,
1869 len = srvstr_push(base_data, flags2, p, fname,
1870 PTR_DIFF(end_data, p), 0);
1871 SIVAL(nameptr, 0, len);
1875 SIVAL(p,0,0); /* Ensure any padding is null. */
1877 len = PTR_DIFF(p, pdata);
1878 len = (len + 3) & ~3;
1879 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1881 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1891 if (PTR_DIFF(p,pdata) > space_remaining) {
1892 /* Move the dirptr back to prev_dirpos */
1893 dptr_SeekDir(conn->dirptr, prev_dirpos);
1894 *out_of_space = True;
1895 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1896 return False; /* Not finished - just out of space */
1899 /* Setup the last entry pointer, as an offset from base_data */
1900 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1901 /* Advance the data pointer to the next slot */
1907 /****************************************************************************
1908 Reply to a TRANS2_FINDFIRST.
1909 ****************************************************************************/
1911 static void call_trans2findfirst(connection_struct *conn,
1912 struct smb_request *req,
1913 char **pparams, int total_params,
1914 char **ppdata, int total_data,
1915 unsigned int max_data_bytes)
1917 /* We must be careful here that we don't return more than the
1918 allowed number of data bytes. If this means returning fewer than
1919 maxentries then so be it. We assume that the redirector has
1920 enough room for the fixed number of parameter bytes it has
1922 struct smb_filename *smb_dname = NULL;
1923 char *params = *pparams;
1924 char *pdata = *ppdata;
1928 uint16 findfirst_flags;
1929 bool close_after_first;
1931 bool requires_resume_key;
1933 char *directory = NULL;
1936 int last_entry_off=0;
1940 bool finished = False;
1941 bool dont_descend = False;
1942 bool out_of_space = False;
1943 int space_remaining;
1944 bool mask_contains_wcard = False;
1945 struct ea_list *ea_list = NULL;
1946 NTSTATUS ntstatus = NT_STATUS_OK;
1947 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1948 TALLOC_CTX *ctx = talloc_tos();
1950 if (total_params < 13) {
1951 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1955 dirtype = SVAL(params,0);
1956 maxentries = SVAL(params,2);
1957 findfirst_flags = SVAL(params,4);
1958 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1959 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1960 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1961 info_level = SVAL(params,6);
1963 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1964 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1965 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1966 info_level, max_data_bytes));
1969 /* W2K3 seems to treat zero as 1. */
1973 switch (info_level) {
1974 case SMB_FIND_INFO_STANDARD:
1975 case SMB_FIND_EA_SIZE:
1976 case SMB_FIND_EA_LIST:
1977 case SMB_FIND_FILE_DIRECTORY_INFO:
1978 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1979 case SMB_FIND_FILE_NAMES_INFO:
1980 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1981 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1982 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1984 case SMB_FIND_FILE_UNIX:
1985 case SMB_FIND_FILE_UNIX_INFO2:
1986 /* Always use filesystem for UNIX mtime query. */
1987 ask_sharemode = false;
1988 if (!lp_unix_extensions()) {
1989 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1994 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1998 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1999 params+12, total_params - 12,
2000 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2001 if (!NT_STATUS_IS_OK(ntstatus)) {
2002 reply_nterror(req, ntstatus);
2006 ntstatus = resolve_dfspath_wcard(ctx, conn,
2007 req->flags2 & FLAGS2_DFS_PATHNAMES,
2010 &mask_contains_wcard);
2011 if (!NT_STATUS_IS_OK(ntstatus)) {
2012 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2013 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2014 ERRSRV, ERRbadpath);
2017 reply_nterror(req, ntstatus);
2021 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2022 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2023 if (!NT_STATUS_IS_OK(ntstatus)) {
2024 reply_nterror(req, ntstatus);
2028 mask = smb_dname->original_lcomp;
2030 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2031 TALLOC_FREE(smb_dname);
2032 if (!NT_STATUS_IS_OK(ntstatus)) {
2033 reply_nterror(req, ntstatus);
2037 ntstatus = check_name(conn, directory);
2038 if (!NT_STATUS_IS_OK(ntstatus)) {
2039 reply_nterror(req, ntstatus);
2043 p = strrchr_m(directory,'/');
2045 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2046 if((directory[0] == '.') && (directory[1] == '\0')) {
2047 mask = talloc_strdup(ctx,"*");
2049 reply_nterror(req, NT_STATUS_NO_MEMORY);
2052 mask_contains_wcard = True;
2054 directory = talloc_strdup(talloc_tos(), "./");
2056 reply_nterror(req, NT_STATUS_NO_MEMORY);
2063 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2065 if (info_level == SMB_FIND_EA_LIST) {
2068 if (total_data < 4) {
2069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2073 ea_size = IVAL(pdata,0);
2074 if (ea_size != total_data) {
2075 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2076 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2081 if (!lp_ea_support(SNUM(conn))) {
2082 reply_doserror(req, ERRDOS, ERReasnotsupported);
2086 /* Pull out the list of names. */
2087 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2089 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2094 *ppdata = (char *)SMB_REALLOC(
2095 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2096 if(*ppdata == NULL ) {
2097 reply_nterror(req, NT_STATUS_NO_MEMORY);
2101 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2103 /* Realloc the params space */
2104 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2105 if (*pparams == NULL) {
2106 reply_nterror(req, NT_STATUS_NO_MEMORY);
2111 /* Save the wildcard match and attribs we are using on this directory -
2112 needed as lanman2 assumes these are being saved between calls */
2114 ntstatus = dptr_create(conn,
2120 mask_contains_wcard,
2124 if (!NT_STATUS_IS_OK(ntstatus)) {
2125 reply_nterror(req, ntstatus);
2129 dptr_num = dptr_dnum(conn->dirptr);
2130 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2132 /* Initialize per TRANS2_FIND_FIRST operation data */
2133 dptr_init_search_op(conn->dirptr);
2135 /* We don't need to check for VOL here as this is returned by
2136 a different TRANS2 call. */
2138 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2139 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2140 dont_descend = True;
2143 space_remaining = max_data_bytes;
2144 out_of_space = False;
2146 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2147 bool got_exact_match = False;
2149 /* this is a heuristic to avoid seeking the dirptr except when
2150 absolutely necessary. It allows for a filename of about 40 chars */
2151 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2152 out_of_space = True;
2155 finished = !get_lanman2_dir_entry(ctx,
2158 mask,dirtype,info_level,
2159 requires_resume_key,dont_descend,
2162 space_remaining, &out_of_space,
2164 &last_entry_off, ea_list);
2167 if (finished && out_of_space)
2170 if (!finished && !out_of_space)
2174 * As an optimisation if we know we aren't looking
2175 * for a wildcard name (ie. the name matches the wildcard exactly)
2176 * then we can finish on any (first) match.
2177 * This speeds up large directory searches. JRA.
2183 /* Ensure space_remaining never goes -ve. */
2184 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2185 space_remaining = 0;
2186 out_of_space = true;
2188 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2192 /* Check if we can close the dirptr */
2193 if(close_after_first || (finished && close_if_end)) {
2194 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2195 dptr_close(&dptr_num);
2199 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2200 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2201 * the protocol level is less than NT1. Tested with smbclient. JRA.
2202 * This should fix the OS/2 client bug #2335.
2205 if(numentries == 0) {
2206 dptr_close(&dptr_num);
2207 if (Protocol < PROTOCOL_NT1) {
2208 reply_doserror(req, ERRDOS, ERRnofiles);
2211 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2212 ERRDOS, ERRbadfile);
2217 /* At this point pdata points to numentries directory entries. */
2219 /* Set up the return parameter block */
2220 SSVAL(params,0,dptr_num);
2221 SSVAL(params,2,numentries);
2222 SSVAL(params,4,finished);
2223 SSVAL(params,6,0); /* Never an EA error */
2224 SSVAL(params,8,last_entry_off);
2226 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2229 if ((! *directory) && dptr_path(dptr_num)) {
2230 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2232 reply_nterror(req, NT_STATUS_NO_MEMORY);
2236 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2237 smb_fn_name(req->cmd),
2238 mask, directory, dirtype, numentries ) );
2241 * Force a name mangle here to ensure that the
2242 * mask as an 8.3 name is top of the mangled cache.
2243 * The reasons for this are subtle. Don't remove
2244 * this code unless you know what you are doing
2245 * (see PR#13758). JRA.
2248 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2249 char mangled_name[13];
2250 name_to_8_3(mask, mangled_name, True, conn->params);
2256 /****************************************************************************
2257 Reply to a TRANS2_FINDNEXT.
2258 ****************************************************************************/
2260 static void call_trans2findnext(connection_struct *conn,
2261 struct smb_request *req,
2262 char **pparams, int total_params,
2263 char **ppdata, int total_data,
2264 unsigned int max_data_bytes)
2266 /* We must be careful here that we don't return more than the
2267 allowed number of data bytes. If this means returning fewer than
2268 maxentries then so be it. We assume that the redirector has
2269 enough room for the fixed number of parameter bytes it has
2271 char *params = *pparams;
2272 char *pdata = *ppdata;
2278 uint16 findnext_flags;
2279 bool close_after_request;
2281 bool requires_resume_key;
2283 bool mask_contains_wcard = False;
2284 char *resume_name = NULL;
2285 const char *mask = NULL;
2286 const char *directory = NULL;
2290 int i, last_entry_off=0;
2291 bool finished = False;
2292 bool dont_descend = False;
2293 bool out_of_space = False;
2294 int space_remaining;
2295 struct ea_list *ea_list = NULL;
2296 NTSTATUS ntstatus = NT_STATUS_OK;
2297 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2298 TALLOC_CTX *ctx = talloc_tos();
2300 if (total_params < 13) {
2301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2305 dptr_num = SVAL(params,0);
2306 maxentries = SVAL(params,2);
2307 info_level = SVAL(params,4);
2308 resume_key = IVAL(params,6);
2309 findnext_flags = SVAL(params,10);
2310 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2311 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2312 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2313 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2315 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2317 total_params - 12, STR_TERMINATE, &ntstatus,
2318 &mask_contains_wcard);
2319 if (!NT_STATUS_IS_OK(ntstatus)) {
2320 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2321 complain (it thinks we're asking for the directory above the shared
2322 path or an invalid name). Catch this as the resume name is only compared, never used in
2323 a file access. JRA. */
2324 srvstr_pull_talloc(ctx, params, req->flags2,
2325 &resume_name, params+12,
2329 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2330 reply_nterror(req, ntstatus);
2335 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2336 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2337 resume_key = %d resume name = %s continue=%d level = %d\n",
2338 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2339 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2342 /* W2K3 seems to treat zero as 1. */
2346 switch (info_level) {
2347 case SMB_FIND_INFO_STANDARD:
2348 case SMB_FIND_EA_SIZE:
2349 case SMB_FIND_EA_LIST:
2350 case SMB_FIND_FILE_DIRECTORY_INFO:
2351 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2352 case SMB_FIND_FILE_NAMES_INFO:
2353 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2354 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2355 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2357 case SMB_FIND_FILE_UNIX:
2358 case SMB_FIND_FILE_UNIX_INFO2:
2359 /* Always use filesystem for UNIX mtime query. */
2360 ask_sharemode = false;
2361 if (!lp_unix_extensions()) {
2362 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2367 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2371 if (info_level == SMB_FIND_EA_LIST) {
2374 if (total_data < 4) {
2375 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2379 ea_size = IVAL(pdata,0);
2380 if (ea_size != total_data) {
2381 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2382 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2383 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2387 if (!lp_ea_support(SNUM(conn))) {
2388 reply_doserror(req, ERRDOS, ERReasnotsupported);
2392 /* Pull out the list of names. */
2393 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2400 *ppdata = (char *)SMB_REALLOC(
2401 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2402 if(*ppdata == NULL) {
2403 reply_nterror(req, NT_STATUS_NO_MEMORY);
2408 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2410 /* Realloc the params space */
2411 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2412 if(*pparams == NULL ) {
2413 reply_nterror(req, NT_STATUS_NO_MEMORY);
2419 /* Check that the dptr is valid */
2420 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2421 reply_doserror(req, ERRDOS, ERRnofiles);
2425 string_set(&conn->dirpath,dptr_path(dptr_num));
2427 /* Get the wildcard mask from the dptr */
2428 if((p = dptr_wcard(dptr_num))== NULL) {
2429 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2430 reply_doserror(req, ERRDOS, ERRnofiles);
2435 directory = conn->dirpath;
2437 /* Get the attr mask from the dptr */
2438 dirtype = dptr_attr(dptr_num);
2440 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2441 dptr_num, mask, dirtype,
2443 dptr_TellDir(conn->dirptr)));
2445 /* Initialize per TRANS2_FIND_NEXT operation data */
2446 dptr_init_search_op(conn->dirptr);
2448 /* We don't need to check for VOL here as this is returned by
2449 a different TRANS2 call. */
2451 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2452 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2453 dont_descend = True;
2456 space_remaining = max_data_bytes;
2457 out_of_space = False;
2460 * Seek to the correct position. We no longer use the resume key but
2461 * depend on the last file name instead.
2464 if(*resume_name && !continue_bit) {
2467 long current_pos = 0;
2469 * Remember, name_to_8_3 is called by
2470 * get_lanman2_dir_entry(), so the resume name
2471 * could be mangled. Ensure we check the unmangled name.
2474 if (mangle_is_mangled(resume_name, conn->params)) {
2475 char *new_resume_name = NULL;
2476 mangle_lookup_name_from_8_3(ctx,
2480 if (new_resume_name) {
2481 resume_name = new_resume_name;
2486 * Fix for NT redirector problem triggered by resume key indexes
2487 * changing between directory scans. We now return a resume key of 0
2488 * and instead look for the filename to continue from (also given
2489 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2490 * findfirst/findnext (as is usual) then the directory pointer
2491 * should already be at the correct place.
2494 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2495 } /* end if resume_name && !continue_bit */
2497 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2498 bool got_exact_match = False;
2500 /* this is a heuristic to avoid seeking the dirptr except when
2501 absolutely necessary. It allows for a filename of about 40 chars */
2502 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2503 out_of_space = True;
2506 finished = !get_lanman2_dir_entry(ctx,
2509 mask,dirtype,info_level,
2510 requires_resume_key,dont_descend,
2513 space_remaining, &out_of_space,
2515 &last_entry_off, ea_list);
2518 if (finished && out_of_space)
2521 if (!finished && !out_of_space)
2525 * As an optimisation if we know we aren't looking
2526 * for a wildcard name (ie. the name matches the wildcard exactly)
2527 * then we can finish on any (first) match.
2528 * This speeds up large directory searches. JRA.
2534 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2537 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2538 smb_fn_name(req->cmd),
2539 mask, directory, dirtype, numentries ) );
2541 /* Check if we can close the dirptr */
2542 if(close_after_request || (finished && close_if_end)) {
2543 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2544 dptr_close(&dptr_num); /* This frees up the saved mask */
2547 /* Set up the return parameter block */
2548 SSVAL(params,0,numentries);
2549 SSVAL(params,2,finished);
2550 SSVAL(params,4,0); /* Never an EA error */
2551 SSVAL(params,6,last_entry_off);
2553 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2559 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2561 E_md4hash(lp_servicename(SNUM(conn)),objid);
2565 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2567 SMB_ASSERT(extended_info != NULL);
2569 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2570 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2571 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2572 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2573 #ifdef SAMBA_VERSION_REVISION
2574 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2576 extended_info->samba_subversion = 0;
2577 #ifdef SAMBA_VERSION_RC_RELEASE
2578 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2580 #ifdef SAMBA_VERSION_PRE_RELEASE
2581 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2584 #ifdef SAMBA_VERSION_VENDOR_PATCH
2585 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2587 extended_info->samba_gitcommitdate = 0;
2588 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2589 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2592 memset(extended_info->samba_version_string, 0,
2593 sizeof(extended_info->samba_version_string));
2595 snprintf (extended_info->samba_version_string,
2596 sizeof(extended_info->samba_version_string),
2597 "%s", samba_version_string());
2600 /****************************************************************************
2601 Reply to a TRANS2_QFSINFO (query filesystem info).
2602 ****************************************************************************/
2604 static void call_trans2qfsinfo(connection_struct *conn,
2605 struct smb_request *req,
2606 char **pparams, int total_params,
2607 char **ppdata, int total_data,
2608 unsigned int max_data_bytes)
2610 char *pdata, *end_data;
2611 char *params = *pparams;
2615 const char *vname = volume_label(SNUM(conn));
2616 int snum = SNUM(conn);
2617 char *fstype = lp_fstype(SNUM(conn));
2618 uint32 additional_flags = 0;
2620 if (total_params < 2) {
2621 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2625 info_level = SVAL(params,0);
2628 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2629 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2630 "info level (0x%x) on IPC$.\n",
2631 (unsigned int)info_level));
2632 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2637 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2638 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2639 DEBUG(0,("call_trans2qfsinfo: encryption required "
2640 "and info level 0x%x sent.\n",
2641 (unsigned int)info_level));
2642 exit_server_cleanly("encryption required "
2648 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2650 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
2651 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2652 reply_doserror(req, ERRSRV, ERRinvdevice);
2656 *ppdata = (char *)SMB_REALLOC(
2657 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2658 if (*ppdata == NULL ) {
2659 reply_nterror(req, NT_STATUS_NO_MEMORY);
2664 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2665 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2667 switch (info_level) {
2668 case SMB_INFO_ALLOCATION:
2670 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2672 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2673 reply_unixerror(req, ERRHRD, ERRgeneral);
2677 block_size = lp_block_size(snum);
2678 if (bsize < block_size) {
2679 uint64_t factor = block_size/bsize;
2684 if (bsize > block_size) {
2685 uint64_t factor = bsize/block_size;
2690 bytes_per_sector = 512;
2691 sectors_per_unit = bsize/bytes_per_sector;
2693 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2694 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2695 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2697 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2698 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2699 SIVAL(pdata,l1_cUnit,dsize);
2700 SIVAL(pdata,l1_cUnitAvail,dfree);
2701 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2705 case SMB_INFO_VOLUME:
2706 /* Return volume name */
2708 * Add volume serial number - hash of a combination of
2709 * the called hostname and the service name.
2711 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2713 * Win2k3 and previous mess this up by sending a name length
2714 * one byte short. I believe only older clients (OS/2 Win9x) use
2715 * this call so try fixing this by adding a terminating null to
2716 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2720 pdata+l2_vol_szVolLabel, vname,
2721 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2722 STR_NOALIGN|STR_TERMINATE);
2723 SCVAL(pdata,l2_vol_cch,len);
2724 data_len = l2_vol_szVolLabel + len;
2725 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2726 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2730 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2731 case SMB_FS_ATTRIBUTE_INFORMATION:
2733 additional_flags = 0;
2734 #if defined(HAVE_SYS_QUOTAS)
2735 additional_flags |= FILE_VOLUME_QUOTAS;
2738 if(lp_nt_acl_support(SNUM(conn))) {
2739 additional_flags |= FILE_PERSISTENT_ACLS;
2742 /* Capabilities are filled in at connection time through STATVFS call */
2743 additional_flags |= conn->fs_capabilities;
2745 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2746 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2747 additional_flags); /* FS ATTRIBUTES */
2749 SIVAL(pdata,4,255); /* Max filename component length */
2750 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2751 and will think we can't do long filenames */
2752 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2753 PTR_DIFF(end_data, pdata+12),
2756 data_len = 12 + len;
2759 case SMB_QUERY_FS_LABEL_INFO:
2760 case SMB_FS_LABEL_INFORMATION:
2761 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2762 PTR_DIFF(end_data, pdata+4), 0);
2767 case SMB_QUERY_FS_VOLUME_INFO:
2768 case SMB_FS_VOLUME_INFORMATION:
2771 * Add volume serial number - hash of a combination of
2772 * the called hostname and the service name.
2774 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2775 (str_checksum(get_local_machine_name())<<16));
2777 /* Max label len is 32 characters. */
2778 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2779 PTR_DIFF(end_data, pdata+18),
2781 SIVAL(pdata,12,len);
2784 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2785 (int)strlen(vname),vname, lp_servicename(snum)));
2788 case SMB_QUERY_FS_SIZE_INFO:
2789 case SMB_FS_SIZE_INFORMATION:
2791 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2793 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2794 reply_unixerror(req, ERRHRD, ERRgeneral);
2797 block_size = lp_block_size(snum);
2798 if (bsize < block_size) {
2799 uint64_t factor = block_size/bsize;
2804 if (bsize > block_size) {
2805 uint64_t factor = bsize/block_size;
2810 bytes_per_sector = 512;
2811 sectors_per_unit = bsize/bytes_per_sector;
2812 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2813 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2814 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2815 SBIG_UINT(pdata,0,dsize);
2816 SBIG_UINT(pdata,8,dfree);
2817 SIVAL(pdata,16,sectors_per_unit);
2818 SIVAL(pdata,20,bytes_per_sector);
2822 case SMB_FS_FULL_SIZE_INFORMATION:
2824 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2826 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2827 reply_unixerror(req, ERRHRD, ERRgeneral);
2830 block_size = lp_block_size(snum);
2831 if (bsize < block_size) {
2832 uint64_t factor = block_size/bsize;
2837 if (bsize > block_size) {
2838 uint64_t factor = bsize/block_size;
2843 bytes_per_sector = 512;
2844 sectors_per_unit = bsize/bytes_per_sector;
2845 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2846 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2847 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2848 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2849 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2850 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2851 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2852 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2856 case SMB_QUERY_FS_DEVICE_INFO:
2857 case SMB_FS_DEVICE_INFORMATION:
2859 SIVAL(pdata,0,0); /* dev type */
2860 SIVAL(pdata,4,0); /* characteristics */
2863 #ifdef HAVE_SYS_QUOTAS
2864 case SMB_FS_QUOTA_INFORMATION:
2866 * what we have to send --metze:
2868 * Unknown1: 24 NULL bytes
2869 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2870 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2871 * Quota Flags: 2 byte :
2872 * Unknown3: 6 NULL bytes
2876 * details for Quota Flags:
2878 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2879 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2880 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2881 * 0x0001 Enable Quotas: enable quota for this fs
2885 /* we need to fake up a fsp here,
2886 * because its not send in this call
2889 SMB_NTQUOTA_STRUCT quotas;
2892 ZERO_STRUCT(quotas);
2898 if (conn->server_info->utok.uid != 0) {
2899 DEBUG(0,("set_user_quota: access_denied "
2900 "service [%s] user [%s]\n",
2901 lp_servicename(SNUM(conn)),
2902 conn->server_info->unix_name));
2903 reply_doserror(req, ERRDOS, ERRnoaccess);
2907 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2908 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2909 reply_doserror(req, ERRSRV, ERRerror);
2915 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2917 /* Unknown1 24 NULL bytes*/
2918 SBIG_UINT(pdata,0,(uint64_t)0);
2919 SBIG_UINT(pdata,8,(uint64_t)0);
2920 SBIG_UINT(pdata,16,(uint64_t)0);
2922 /* Default Soft Quota 8 bytes */
2923 SBIG_UINT(pdata,24,quotas.softlim);
2925 /* Default Hard Quota 8 bytes */
2926 SBIG_UINT(pdata,32,quotas.hardlim);
2928 /* Quota flag 2 bytes */
2929 SSVAL(pdata,40,quotas.qflags);
2931 /* Unknown3 6 NULL bytes */
2937 #endif /* HAVE_SYS_QUOTAS */
2938 case SMB_FS_OBJECTID_INFORMATION:
2940 unsigned char objid[16];
2941 struct smb_extended_info extended_info;
2942 memcpy(pdata,create_volume_objectid(conn, objid),16);
2943 samba_extended_info_version (&extended_info);
2944 SIVAL(pdata,16,extended_info.samba_magic);
2945 SIVAL(pdata,20,extended_info.samba_version);
2946 SIVAL(pdata,24,extended_info.samba_subversion);
2947 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2948 memcpy(pdata+36,extended_info.samba_version_string,28);
2954 * Query the version and capabilities of the CIFS UNIX extensions
2958 case SMB_QUERY_CIFS_UNIX_INFO:
2960 bool large_write = lp_min_receive_file_size() &&
2961 !srv_is_signing_active(smbd_server_conn);
2962 bool large_read = !srv_is_signing_active(smbd_server_conn);
2963 int encrypt_caps = 0;
2965 if (!lp_unix_extensions()) {
2966 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2970 switch (conn->encrypt_level) {
2976 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2979 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2980 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2981 large_write = false;
2987 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2988 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2990 /* We have POSIX ACLs, pathname, encryption,
2991 * large read/write, and locking capability. */
2993 SBIG_UINT(pdata,4,((uint64_t)(
2994 CIFS_UNIX_POSIX_ACLS_CAP|
2995 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2996 CIFS_UNIX_FCNTL_LOCKS_CAP|
2997 CIFS_UNIX_EXTATTR_CAP|
2998 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3000 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3002 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3006 case SMB_QUERY_POSIX_FS_INFO:
3009 vfs_statvfs_struct svfs;
3011 if (!lp_unix_extensions()) {
3012 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3016 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3020 SIVAL(pdata,0,svfs.OptimalTransferSize);
3021 SIVAL(pdata,4,svfs.BlockSize);
3022 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3023 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3024 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3025 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3026 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3027 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3028 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3030 } else if (rc == EOPNOTSUPP) {
3031 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3033 #endif /* EOPNOTSUPP */
3035 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3036 reply_doserror(req, ERRSRV, ERRerror);
3042 case SMB_QUERY_POSIX_WHOAMI:
3048 if (!lp_unix_extensions()) {
3049 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3053 if (max_data_bytes < 40) {
3054 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3058 /* We ARE guest if global_sid_Builtin_Guests is
3059 * in our list of SIDs.
3061 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3062 conn->server_info->ptok)) {
3063 flags |= SMB_WHOAMI_GUEST;
3066 /* We are NOT guest if global_sid_Authenticated_Users
3067 * is in our list of SIDs.
3069 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3070 conn->server_info->ptok)) {
3071 flags &= ~SMB_WHOAMI_GUEST;
3074 /* NOTE: 8 bytes for UID/GID, irrespective of native
3075 * platform size. This matches
3076 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3078 data_len = 4 /* flags */
3085 + 4 /* pad/reserved */
3086 + (conn->server_info->utok.ngroups * 8)
3088 + (conn->server_info->ptok->num_sids *
3092 SIVAL(pdata, 0, flags);
3093 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3095 (uint64_t)conn->server_info->utok.uid);
3096 SBIG_UINT(pdata, 16,
3097 (uint64_t)conn->server_info->utok.gid);
3100 if (data_len >= max_data_bytes) {
3101 /* Potential overflow, skip the GIDs and SIDs. */
3103 SIVAL(pdata, 24, 0); /* num_groups */
3104 SIVAL(pdata, 28, 0); /* num_sids */
3105 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3106 SIVAL(pdata, 36, 0); /* reserved */
3112 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3113 SIVAL(pdata, 28, conn->server_info->num_sids);
3115 /* We walk the SID list twice, but this call is fairly
3116 * infrequent, and I don't expect that it's performance
3117 * sensitive -- jpeach
3119 for (i = 0, sid_bytes = 0;
3120 i < conn->server_info->ptok->num_sids; ++i) {
3121 sid_bytes += ndr_size_dom_sid(
3122 &conn->server_info->ptok->user_sids[i],
3127 /* SID list byte count */
3128 SIVAL(pdata, 32, sid_bytes);
3130 /* 4 bytes pad/reserved - must be zero */
3131 SIVAL(pdata, 36, 0);
3135 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3136 SBIG_UINT(pdata, data_len,
3137 (uint64_t)conn->server_info->utok.groups[i]);
3143 i < conn->server_info->ptok->num_sids; ++i) {
3144 int sid_len = ndr_size_dom_sid(
3145 &conn->server_info->ptok->user_sids[i],
3149 sid_linearize(pdata + data_len, sid_len,
3150 &conn->server_info->ptok->user_sids[i]);
3151 data_len += sid_len;
3157 case SMB_MAC_QUERY_FS_INFO:
3159 * Thursby MAC extension... ONLY on NTFS filesystems
3160 * once we do streams then we don't need this
3162 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3164 SIVAL(pdata,84,0x100); /* Don't support mac... */
3169 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3174 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3177 DEBUG( 4, ( "%s info_level = %d\n",
3178 smb_fn_name(req->cmd), info_level) );
3183 /****************************************************************************
3184 Reply to a TRANS2_SETFSINFO (set filesystem info).
3185 ****************************************************************************/
3187 static void call_trans2setfsinfo(connection_struct *conn,
3188 struct smb_request *req,
3189 char **pparams, int total_params,
3190 char **ppdata, int total_data,
3191 unsigned int max_data_bytes)
3193 char *pdata = *ppdata;
3194 char *params = *pparams;
3197 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3200 if (total_params < 4) {
3201 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3207 info_level = SVAL(params,2);
3210 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3211 info_level != SMB_SET_CIFS_UNIX_INFO) {
3212 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3213 "info level (0x%x) on IPC$.\n",
3214 (unsigned int)info_level));
3215 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3220 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3221 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3222 DEBUG(0,("call_trans2setfsinfo: encryption required "
3223 "and info level 0x%x sent.\n",
3224 (unsigned int)info_level));
3225 exit_server_cleanly("encryption required "
3231 switch(info_level) {
3232 case SMB_SET_CIFS_UNIX_INFO:
3234 uint16 client_unix_major;
3235 uint16 client_unix_minor;
3236 uint32 client_unix_cap_low;
3237 uint32 client_unix_cap_high;
3239 if (!lp_unix_extensions()) {
3241 NT_STATUS_INVALID_LEVEL);
3245 /* There should be 12 bytes of capabilities set. */
3246 if (total_data < 8) {
3249 NT_STATUS_INVALID_PARAMETER);
3252 client_unix_major = SVAL(pdata,0);
3253 client_unix_minor = SVAL(pdata,2);
3254 client_unix_cap_low = IVAL(pdata,4);
3255 client_unix_cap_high = IVAL(pdata,8);
3256 /* Just print these values for now. */
3257 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3258 cap_low = 0x%x, cap_high = 0x%x\n",
3259 (unsigned int)client_unix_major,
3260 (unsigned int)client_unix_minor,
3261 (unsigned int)client_unix_cap_low,
3262 (unsigned int)client_unix_cap_high ));
3264 /* Here is where we must switch to posix pathname processing... */
3265 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3266 lp_set_posix_pathnames();
3267 mangle_change_to_posix();
3270 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3271 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3272 /* Client that knows how to do posix locks,
3273 * but not posix open/mkdir operations. Set a
3274 * default type for read/write checks. */
3276 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3282 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3285 size_t param_len = 0;
3286 size_t data_len = total_data;
3288 if (!lp_unix_extensions()) {
3291 NT_STATUS_INVALID_LEVEL);
3295 if (lp_smb_encrypt(SNUM(conn)) == false) {
3298 NT_STATUS_NOT_SUPPORTED);
3302 DEBUG( 4,("call_trans2setfsinfo: "
3303 "request transport encryption.\n"));
3305 status = srv_request_encryption_setup(conn,
3306 (unsigned char **)ppdata,
3308 (unsigned char **)pparams,
3311 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3312 !NT_STATUS_IS_OK(status)) {
3313 reply_nterror(req, status);
3317 send_trans2_replies(conn, req,
3324 if (NT_STATUS_IS_OK(status)) {
3325 /* Server-side transport
3326 * encryption is now *on*. */
3327 status = srv_encryption_start(conn);
3328 if (!NT_STATUS_IS_OK(status)) {
3329 exit_server_cleanly(
3330 "Failure in setting "
3331 "up encrypted transport");
3337 case SMB_FS_QUOTA_INFORMATION:
3339 files_struct *fsp = NULL;
3340 SMB_NTQUOTA_STRUCT quotas;
3342 ZERO_STRUCT(quotas);
3345 if ((conn->server_info->utok.uid != 0)
3346 ||!CAN_WRITE(conn)) {
3347 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3348 lp_servicename(SNUM(conn)),
3349 conn->server_info->unix_name));
3350 reply_doserror(req, ERRSRV, ERRaccess);
3354 /* note: normaly there're 48 bytes,
3355 * but we didn't use the last 6 bytes for now
3358 fsp = file_fsp(req, SVAL(params,0));
3360 if (!check_fsp_ntquota_handle(conn, req,
3362 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3364 req, NT_STATUS_INVALID_HANDLE);
3368 if (total_data < 42) {
3369 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3373 NT_STATUS_INVALID_PARAMETER);
3377 /* unknown_1 24 NULL bytes in pdata*/
3379 /* the soft quotas 8 bytes (uint64_t)*/
3380 quotas.softlim = (uint64_t)IVAL(pdata,24);
3381 #ifdef LARGE_SMB_OFF_T
3382 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3383 #else /* LARGE_SMB_OFF_T */
3384 if ((IVAL(pdata,28) != 0)&&
3385 ((quotas.softlim != 0xFFFFFFFF)||
3386 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3387 /* more than 32 bits? */
3390 NT_STATUS_INVALID_PARAMETER);
3393 #endif /* LARGE_SMB_OFF_T */
3395 /* the hard quotas 8 bytes (uint64_t)*/
3396 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3397 #ifdef LARGE_SMB_OFF_T
3398 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3399 #else /* LARGE_SMB_OFF_T */
3400 if ((IVAL(pdata,36) != 0)&&
3401 ((quotas.hardlim != 0xFFFFFFFF)||
3402 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3403 /* more than 32 bits? */
3406 NT_STATUS_INVALID_PARAMETER);
3409 #endif /* LARGE_SMB_OFF_T */
3411 /* quota_flags 2 bytes **/
3412 quotas.qflags = SVAL(pdata,40);
3414 /* unknown_2 6 NULL bytes follow*/
3416 /* now set the quotas */
3417 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3418 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3419 reply_doserror(req, ERRSRV, ERRerror);
3426 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3428 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3434 * sending this reply works fine,
3435 * but I'm not sure it's the same
3436 * like windows do...
3439 reply_outbuf(req, 10, 0);
3442 #if defined(HAVE_POSIX_ACLS)
3443 /****************************************************************************
3444 Utility function to count the number of entries in a POSIX acl.
3445 ****************************************************************************/
3447 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3449 unsigned int ace_count = 0;
3450 int entry_id = SMB_ACL_FIRST_ENTRY;
3451 SMB_ACL_ENTRY_T entry;
3453 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3455 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3456 entry_id = SMB_ACL_NEXT_ENTRY;
3463 /****************************************************************************
3464 Utility function to marshall a POSIX acl into wire format.
3465 ****************************************************************************/
3467 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3469 int entry_id = SMB_ACL_FIRST_ENTRY;
3470 SMB_ACL_ENTRY_T entry;
3472 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3473 SMB_ACL_TAG_T tagtype;
3474 SMB_ACL_PERMSET_T permset;
3475 unsigned char perms = 0;
3476 unsigned int own_grp;
3479 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3480 entry_id = SMB_ACL_NEXT_ENTRY;
3483 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3484 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3488 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3489 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3493 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3494 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3495 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3497 SCVAL(pdata,1,perms);
3500 case SMB_ACL_USER_OBJ:
3501 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3502 own_grp = (unsigned int)pst->st_ex_uid;
3503 SIVAL(pdata,2,own_grp);
3508 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3510 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3513 own_grp = (unsigned int)*puid;
3514 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3515 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3516 SIVAL(pdata,2,own_grp);
3520 case SMB_ACL_GROUP_OBJ:
3521 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3522 own_grp = (unsigned int)pst->st_ex_gid;
3523 SIVAL(pdata,2,own_grp);
3528 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3530 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3533 own_grp = (unsigned int)*pgid;
3534 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3535 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3536 SIVAL(pdata,2,own_grp);
3541 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3542 SIVAL(pdata,2,0xFFFFFFFF);
3543 SIVAL(pdata,6,0xFFFFFFFF);
3546 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3547 SIVAL(pdata,2,0xFFFFFFFF);
3548 SIVAL(pdata,6,0xFFFFFFFF);
3551 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3554 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3561 /****************************************************************************
3562 Store the FILE_UNIX_BASIC info.
3563 ****************************************************************************/
3565 static char *store_file_unix_basic(connection_struct *conn,
3568 const SMB_STRUCT_STAT *psbuf)
3570 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3571 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3573 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3576 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3579 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3580 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3581 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3584 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3588 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3592 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3595 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3599 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3603 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3606 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3610 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3617 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3618 * the chflags(2) (or equivalent) flags.
3620 * XXX: this really should be behind the VFS interface. To do this, we would
3621 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3622 * Each VFS module could then implement its own mapping as appropriate for the
3623 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3625 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3629 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3633 { UF_IMMUTABLE, EXT_IMMUTABLE },
3637 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3641 { UF_HIDDEN, EXT_HIDDEN },
3644 /* Do not remove. We need to guarantee that this array has at least one
3645 * entry to build on HP-UX.
3651 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3652 uint32 *smb_fflags, uint32 *smb_fmask)
3656 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3657 *smb_fmask |= info2_flags_map[i].smb_fflag;
3658 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3659 *smb_fflags |= info2_flags_map[i].smb_fflag;
3664 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3665 const uint32 smb_fflags,
3666 const uint32 smb_fmask,
3669 uint32 max_fmask = 0;
3672 *stat_fflags = psbuf->st_ex_flags;
3674 /* For each flags requested in smb_fmask, check the state of the
3675 * corresponding flag in smb_fflags and set or clear the matching
3679 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3680 max_fmask |= info2_flags_map[i].smb_fflag;
3681 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3682 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3683 *stat_fflags |= info2_flags_map[i].stat_fflag;
3685 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3690 /* If smb_fmask is asking to set any bits that are not supported by
3691 * our flag mappings, we should fail.
3693 if ((smb_fmask & max_fmask) != smb_fmask) {
3701 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3702 * of file flags and birth (create) time.
3704 static char *store_file_unix_basic_info2(connection_struct *conn,
3707 const SMB_STRUCT_STAT *psbuf)
3709 uint32 file_flags = 0;
3710 uint32 flags_mask = 0;
3712 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3714 /* Create (birth) time 64 bit */
3715 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3718 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3719 SIVAL(pdata, 0, file_flags); /* flags */
3720 SIVAL(pdata, 4, flags_mask); /* mask */
3726 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3727 const struct stream_struct *streams,
3729 unsigned int max_data_bytes,
3730 unsigned int *data_size)
3733 unsigned int ofs = 0;
3735 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3736 unsigned int next_offset;
3738 smb_ucs2_t *namebuf;
3740 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3741 streams[i].name, &namelen) ||
3744 return NT_STATUS_INVALID_PARAMETER;
3748 * name_buf is now null-terminated, we need to marshall as not
3754 SIVAL(data, ofs+4, namelen);
3755 SOFF_T(data, ofs+8, streams[i].size);
3756 SOFF_T(data, ofs+16, streams[i].alloc_size);
3757 memcpy(data+ofs+24, namebuf, namelen);
3758 TALLOC_FREE(namebuf);
3760 next_offset = ofs + 24 + namelen;
3762 if (i == num_streams-1) {
3763 SIVAL(data, ofs, 0);
3766 unsigned int align = ndr_align_size(next_offset, 8);
3768 memset(data+next_offset, 0, align);
3769 next_offset += align;
3771 SIVAL(data, ofs, next_offset - ofs);
3780 return NT_STATUS_OK;
3783 /****************************************************************************
3784 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3785 ****************************************************************************/
3787 static void call_trans2qpipeinfo(connection_struct *conn,
3788 struct smb_request *req,
3789 unsigned int tran_call,
3790 char **pparams, int total_params,
3791 char **ppdata, int total_data,
3792 unsigned int max_data_bytes)
3794 char *params = *pparams;
3795 char *pdata = *ppdata;
3796 unsigned int data_size = 0;
3797 unsigned int param_size = 2;
3802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3806 if (total_params < 4) {
3807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3811 fsp = file_fsp(req, SVAL(params,0));
3812 if (!fsp_is_np(fsp)) {
3813 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3817 info_level = SVAL(params,2);
3819 *pparams = (char *)SMB_REALLOC(*pparams,2);
3820 if (*pparams == NULL) {
3821 reply_nterror(req, NT_STATUS_NO_MEMORY);
3826 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3827 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3828 if (*ppdata == NULL ) {
3829 reply_nterror(req, NT_STATUS_NO_MEMORY);
3834 switch (info_level) {
3835 case SMB_FILE_STANDARD_INFORMATION:
3837 SOFF_T(pdata,0,4096LL);
3844 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3848 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3854 /****************************************************************************
3855 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3856 file name or file id).
3857 ****************************************************************************/
3859 static void call_trans2qfilepathinfo(connection_struct *conn,
3860 struct smb_request *req,
3861 unsigned int tran_call,
3862 char **pparams, int total_params,
3863 char **ppdata, int total_data,
3864 unsigned int max_data_bytes)
3866 char *params = *pparams;
3867 char *pdata = *ppdata;
3868 char *dstart, *dend;
3872 SMB_OFF_T file_size=0;
3873 uint64_t allocation_size=0;
3874 unsigned int data_size = 0;
3875 unsigned int param_size = 2;
3876 SMB_STRUCT_STAT sbuf;
3877 char *dos_fname = NULL;
3879 struct smb_filename *smb_fname = NULL;
3884 bool delete_pending = False;
3886 time_t create_time, mtime, atime;
3887 struct timespec create_time_ts, mtime_ts, atime_ts;
3888 struct timespec write_time_ts;
3889 files_struct *fsp = NULL;
3890 struct file_id fileid;
3891 struct ea_list *ea_list = NULL;
3892 char *lock_data = NULL;
3893 bool ms_dfs_link = false;
3894 TALLOC_CTX *ctx = talloc_tos();
3895 NTSTATUS status = NT_STATUS_OK;
3898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3902 ZERO_STRUCT(write_time_ts);
3904 if (tran_call == TRANSACT2_QFILEINFO) {
3905 if (total_params < 4) {
3906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3911 call_trans2qpipeinfo(conn, req, tran_call,
3912 pparams, total_params,
3918 fsp = file_fsp(req, SVAL(params,0));
3919 info_level = SVAL(params,2);
3921 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3923 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3924 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3928 /* Initial check for valid fsp ptr. */
3929 if (!check_fsp_open(conn, req, fsp)) {
3933 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3935 reply_nterror(req, NT_STATUS_NO_MEMORY);
3939 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
3941 if (!NT_STATUS_IS_OK(status)) {
3942 reply_nterror(req, status);
3946 if(fsp->fake_file_handle) {
3948 * This is actually for the QUOTA_FAKE_FILE --metze
3951 /* We know this name is ok, it's already passed the checks. */
3953 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3955 * This is actually a QFILEINFO on a directory
3956 * handle (returned from an NT SMB). NT5.0 seems
3957 * to do this call. JRA.
3960 if (INFO_LEVEL_IS_UNIX(info_level)) {
3961 /* Always do lstat for UNIX calls. */
3962 if (SMB_VFS_LSTAT(conn, smb_fname)) {
3963 DEBUG(3,("call_trans2qfilepathinfo: "
3964 "SMB_VFS_LSTAT of %s failed "
3966 smb_fname_str_dbg(smb_fname),
3968 reply_unixerror(req,ERRDOS,ERRbadpath);
3971 } else if (SMB_VFS_STAT(conn, smb_fname)) {
3972 DEBUG(3,("call_trans2qfilepathinfo: "
3973 "SMB_VFS_STAT of %s failed (%s)\n",
3974 smb_fname_str_dbg(smb_fname),
3976 reply_unixerror(req, ERRDOS, ERRbadpath);
3980 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
3981 get_file_infos(fileid, &delete_pending, &write_time_ts);
3984 * Original code - this is an open file.
3986 if (!check_fsp(conn, req, fsp)) {
3990 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
3991 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
3992 fsp->fnum, strerror(errno)));
3993 reply_unixerror(req, ERRDOS, ERRbadfid);
3996 pos = fsp->fh->position_information;
3997 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
3998 get_file_infos(fileid, &delete_pending, &write_time_ts);
4003 if (total_params < 7) {
4004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4008 info_level = SVAL(params,0);
4010 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4012 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4013 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4017 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
4019 STR_TERMINATE, &status);
4020 if (!NT_STATUS_IS_OK(status)) {
4021 reply_nterror(req, status);
4025 status = filename_convert(ctx,
4027 req->flags2 & FLAGS2_DFS_PATHNAMES,
4031 if (!NT_STATUS_IS_OK(status)) {
4032 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4033 reply_botherror(req,
4034 NT_STATUS_PATH_NOT_COVERED,
4035 ERRSRV, ERRbadpath);
4038 reply_nterror(req, status);
4042 /* If this is a stream, check if there is a delete_pending. */
4043 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4044 && is_ntfs_stream_smb_fname(smb_fname)) {
4045 struct smb_filename *smb_fname_base = NULL;
4047 /* Create an smb_filename with stream_name == NULL. */
4049 create_synthetic_smb_fname(talloc_tos(),
4050 smb_fname->base_name,
4053 if (!NT_STATUS_IS_OK(status)) {
4054 reply_nterror(req, status);
4058 if (INFO_LEVEL_IS_UNIX(info_level)) {
4059 /* Always do lstat for UNIX calls. */
4060 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4061 DEBUG(3,("call_trans2qfilepathinfo: "
4062 "SMB_VFS_LSTAT of %s failed "
4064 smb_fname_str_dbg(smb_fname_base),
4066 TALLOC_FREE(smb_fname_base);
4067 reply_unixerror(req,ERRDOS,ERRbadpath);
4071 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4072 DEBUG(3,("call_trans2qfilepathinfo: "
4073 "fileinfo of %s failed "
4075 smb_fname_str_dbg(smb_fname_base),
4077 TALLOC_FREE(smb_fname_base);
4078 reply_unixerror(req,ERRDOS,ERRbadpath);
4083 fileid = vfs_file_id_from_sbuf(conn,
4084 &smb_fname_base->st);
4085 TALLOC_FREE(smb_fname_base);
4086 get_file_infos(fileid, &delete_pending, NULL);
4087 if (delete_pending) {
4088 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4093 if (INFO_LEVEL_IS_UNIX(info_level)) {
4094 /* Always do lstat for UNIX calls. */
4095 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4096 DEBUG(3,("call_trans2qfilepathinfo: "
4097 "SMB_VFS_LSTAT of %s failed (%s)\n",
4098 smb_fname_str_dbg(smb_fname),
4100 reply_unixerror(req, ERRDOS, ERRbadpath);
4104 } else if (!VALID_STAT(smb_fname->st) &&
4105 SMB_VFS_STAT(conn, smb_fname) &&
4106 (info_level != SMB_INFO_IS_NAME_VALID)) {
4107 ms_dfs_link = check_msdfs_link(conn, fname,
4111 DEBUG(3,("call_trans2qfilepathinfo: "
4112 "SMB_VFS_STAT of %s failed (%s)\n",
4113 smb_fname_str_dbg(smb_fname),
4115 reply_unixerror(req, ERRDOS, ERRbadpath);
4120 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4121 get_file_infos(fileid, &delete_pending, &write_time_ts);
4122 if (delete_pending) {
4123 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4128 /* Set sbuf for use below. */
4129 sbuf = smb_fname->st;
4131 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4132 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4136 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4137 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4139 p = strrchr_m(fname,'/');
4146 mode = dos_mode_msdfs(conn,fname,&sbuf);
4148 mode = dos_mode(conn,fname,&sbuf);
4151 mode = FILE_ATTRIBUTE_NORMAL;
4153 nlink = sbuf.st_ex_nlink;
4155 if (nlink && (mode&aDIR)) {
4159 if ((nlink > 0) && delete_pending) {
4163 fullpathname = fname;
4165 file_size = get_file_size_stat(&sbuf);
4167 /* Pull out any data sent here before we realloc. */
4168 switch (info_level) {
4169 case SMB_INFO_QUERY_EAS_FROM_LIST:
4171 /* Pull any EA list from the data portion. */
4174 if (total_data < 4) {
4176 req, NT_STATUS_INVALID_PARAMETER);
4179 ea_size = IVAL(pdata,0);
4181 if (total_data > 0 && ea_size != total_data) {
4182 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4183 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4185 req, NT_STATUS_INVALID_PARAMETER);
4189 if (!lp_ea_support(SNUM(conn))) {
4190 reply_doserror(req, ERRDOS,
4191 ERReasnotsupported);
4195 /* Pull out the list of names. */
4196 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4199 req, NT_STATUS_INVALID_PARAMETER);
4205 case SMB_QUERY_POSIX_LOCK:
4207 if (fsp == NULL || fsp->fh->fd == -1) {
4208 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4212 if (total_data != POSIX_LOCK_DATA_SIZE) {
4214 req, NT_STATUS_INVALID_PARAMETER);
4218 /* Copy the lock range data. */
4219 lock_data = (char *)TALLOC_MEMDUP(
4220 ctx, pdata, total_data);
4222 reply_nterror(req, NT_STATUS_NO_MEMORY);
4230 *pparams = (char *)SMB_REALLOC(*pparams,2);
4231 if (*pparams == NULL) {
4232 reply_nterror(req, NT_STATUS_NO_MEMORY);
4237 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4238 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4239 if (*ppdata == NULL ) {
4240 reply_nterror(req, NT_STATUS_NO_MEMORY);
4245 dend = dstart + data_size - 1;
4247 create_time_ts = sbuf.st_ex_btime;
4248 mtime_ts = sbuf.st_ex_mtime;
4249 atime_ts = sbuf.st_ex_atime;
4251 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4254 /* Do we have this path open ? */
4256 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4257 fsp1 = file_find_di_first(fileid);
4258 if (fsp1 && fsp1->initial_allocation_size) {
4259 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4263 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4264 mtime_ts = write_time_ts;
4267 if (lp_dos_filetime_resolution(SNUM(conn))) {
4268 dos_filetime_timespec(&create_time_ts);
4269 dos_filetime_timespec(&mtime_ts);
4270 dos_filetime_timespec(&atime_ts);
4273 create_time = convert_timespec_to_time_t(create_time_ts);
4274 mtime = convert_timespec_to_time_t(mtime_ts);
4275 atime = convert_timespec_to_time_t(atime_ts);
4277 /* NT expects the name to be in an exact form of the *full*
4278 filename. See the trans2 torture test */
4279 if (ISDOT(base_name)) {
4280 dos_fname = talloc_strdup(ctx, "\\");
4282 reply_nterror(req, NT_STATUS_NO_MEMORY);
4286 dos_fname = talloc_asprintf(ctx,
4290 reply_nterror(req, NT_STATUS_NO_MEMORY);
4293 string_replace(dos_fname, '/', '\\');
4296 switch (info_level) {
4297 case SMB_INFO_STANDARD:
4298 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4300 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4301 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4302 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4303 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4304 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4305 SSVAL(pdata,l1_attrFile,mode);
4308 case SMB_INFO_QUERY_EA_SIZE:
4310 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4311 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4313 srv_put_dos_date2(pdata,0,create_time);
4314 srv_put_dos_date2(pdata,4,atime);
4315 srv_put_dos_date2(pdata,8,mtime); /* write time */
4316 SIVAL(pdata,12,(uint32)file_size);
4317 SIVAL(pdata,16,(uint32)allocation_size);
4318 SSVAL(pdata,20,mode);
4319 SIVAL(pdata,22,ea_size);
4323 case SMB_INFO_IS_NAME_VALID:
4324 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4325 if (tran_call == TRANSACT2_QFILEINFO) {
4326 /* os/2 needs this ? really ?*/
4327 reply_doserror(req, ERRDOS, ERRbadfunc);
4334 case SMB_INFO_QUERY_EAS_FROM_LIST:
4336 size_t total_ea_len = 0;
4337 struct ea_list *ea_file_list = NULL;
4339 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4341 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4342 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4344 if (!ea_list || (total_ea_len > data_size)) {
4346 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4350 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4354 case SMB_INFO_QUERY_ALL_EAS:
4356 /* We have data_size bytes to put EA's into. */
4357 size_t total_ea_len = 0;
4359 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4361 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4362 if (!ea_list || (total_ea_len > data_size)) {
4364 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4368 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4372 case SMB_FILE_BASIC_INFORMATION:
4373 case SMB_QUERY_FILE_BASIC_INFO:
4375 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4376 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4377 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4379 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4383 put_long_date_timespec(pdata,create_time_ts);
4384 put_long_date_timespec(pdata+8,atime_ts);
4385 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4386 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4387 SIVAL(pdata,32,mode);
4389 DEBUG(5,("SMB_QFBI - "));
4390 DEBUG(5,("create: %s ", ctime(&create_time)));
4391 DEBUG(5,("access: %s ", ctime(&atime)));
4392 DEBUG(5,("write: %s ", ctime(&mtime)));
4393 DEBUG(5,("change: %s ", ctime(&mtime)));
4394 DEBUG(5,("mode: %x\n", mode));
4397 case SMB_FILE_STANDARD_INFORMATION:
4398 case SMB_QUERY_FILE_STANDARD_INFO:
4400 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4402 SOFF_T(pdata,0,allocation_size);
4403 SOFF_T(pdata,8,file_size);
4404 SIVAL(pdata,16,nlink);
4405 SCVAL(pdata,20,delete_pending?1:0);
4406 SCVAL(pdata,21,(mode&aDIR)?1:0);
4407 SSVAL(pdata,22,0); /* Padding. */
4410 case SMB_FILE_EA_INFORMATION:
4411 case SMB_QUERY_FILE_EA_INFO:
4413 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4414 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4416 SIVAL(pdata,0,ea_size);
4420 /* Get the 8.3 name - used if NT SMB was negotiated. */
4421 case SMB_QUERY_FILE_ALT_NAME_INFO:
4422 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4424 char mangled_name[13];
4425 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4426 if (!name_to_8_3(base_name,mangled_name,
4427 True,conn->params)) {
4430 NT_STATUS_NO_MEMORY);
4432 len = srvstr_push(dstart, req->flags2,
4433 pdata+4, mangled_name,
4434 PTR_DIFF(dend, pdata+4),
4436 data_size = 4 + len;
4441 case SMB_QUERY_FILE_NAME_INFO:
4443 this must be *exactly* right for ACLs on mapped drives to work
4445 len = srvstr_push(dstart, req->flags2,
4447 PTR_DIFF(dend, pdata+4),
4449 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4450 data_size = 4 + len;
4454 case SMB_FILE_ALLOCATION_INFORMATION:
4455 case SMB_QUERY_FILE_ALLOCATION_INFO:
4456 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4458 SOFF_T(pdata,0,allocation_size);
4461 case SMB_FILE_END_OF_FILE_INFORMATION:
4462 case SMB_QUERY_FILE_END_OF_FILEINFO:
4463 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4465 SOFF_T(pdata,0,file_size);
4468 case SMB_QUERY_FILE_ALL_INFO:
4469 case SMB_FILE_ALL_INFORMATION:
4471 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4472 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4473 put_long_date_timespec(pdata,create_time_ts);
4474 put_long_date_timespec(pdata+8,atime_ts);
4475 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4476 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4477 SIVAL(pdata,32,mode);
4478 SIVAL(pdata,36,0); /* padding. */
4480 SOFF_T(pdata,0,allocation_size);
4481 SOFF_T(pdata,8,file_size);
4482 SIVAL(pdata,16,nlink);
4483 SCVAL(pdata,20,delete_pending);
4484 SCVAL(pdata,21,(mode&aDIR)?1:0);
4487 SIVAL(pdata,0,ea_size);
4488 pdata += 4; /* EA info */
4489 len = srvstr_push(dstart, req->flags2,
4491 PTR_DIFF(dend, pdata+4),
4495 data_size = PTR_DIFF(pdata,(*ppdata));
4498 case SMB_FILE_INTERNAL_INFORMATION:
4499 /* This should be an index number - looks like
4502 I think this causes us to fail the IFSKIT
4503 BasicFileInformationTest. -tpot */
4505 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4506 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4507 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4511 case SMB_FILE_ACCESS_INFORMATION:
4512 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4514 SIVAL(pdata,0,fsp->access_mask);
4516 /* GENERIC_EXECUTE mapping from Windows */
4517 SIVAL(pdata,0,0x12019F);
4522 case SMB_FILE_NAME_INFORMATION:
4523 /* Pathname with leading '\'. */
4526 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4527 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4528 SIVAL(pdata,0,byte_len);
4529 data_size = 4 + byte_len;
4533 case SMB_FILE_DISPOSITION_INFORMATION:
4534 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4536 SCVAL(pdata,0,delete_pending);
4539 case SMB_FILE_POSITION_INFORMATION:
4540 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4542 SOFF_T(pdata,0,pos);
4545 case SMB_FILE_MODE_INFORMATION:
4546 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4547 SIVAL(pdata,0,mode);
4551 case SMB_FILE_ALIGNMENT_INFORMATION:
4552 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4553 SIVAL(pdata,0,0); /* No alignment needed. */
4558 * NT4 server just returns "invalid query" to this - if we try
4559 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4562 /* The first statement above is false - verified using Thursby
4563 * client against NT4 -- gcolley.
4565 case SMB_QUERY_FILE_STREAM_INFO:
4566 case SMB_FILE_STREAM_INFORMATION: {
4567 unsigned int num_streams;
4568 struct stream_struct *streams;
4570 DEBUG(10,("call_trans2qfilepathinfo: "
4571 "SMB_FILE_STREAM_INFORMATION\n"));
4573 status = SMB_VFS_STREAMINFO(
4574 conn, fsp, fname, talloc_tos(),
4575 &num_streams, &streams);
4577 if (!NT_STATUS_IS_OK(status)) {
4578 DEBUG(10, ("could not get stream info: %s\n",
4579 nt_errstr(status)));
4580 reply_nterror(req, status);
4584 status = marshall_stream_info(num_streams, streams,
4585 pdata, max_data_bytes,
4588 if (!NT_STATUS_IS_OK(status)) {
4589 DEBUG(10, ("marshall_stream_info failed: %s\n",
4590 nt_errstr(status)));
4591 reply_nterror(req, status);
4595 TALLOC_FREE(streams);
4599 case SMB_QUERY_COMPRESSION_INFO:
4600 case SMB_FILE_COMPRESSION_INFORMATION:
4601 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4602 SOFF_T(pdata,0,file_size);
4603 SIVAL(pdata,8,0); /* ??? */
4604 SIVAL(pdata,12,0); /* ??? */
4608 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4609 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4610 put_long_date_timespec(pdata,create_time_ts);
4611 put_long_date_timespec(pdata+8,atime_ts);
4612 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4613 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4614 SOFF_T(pdata,32,allocation_size);
4615 SOFF_T(pdata,40,file_size);
4616 SIVAL(pdata,48,mode);
4617 SIVAL(pdata,52,0); /* ??? */
4621 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4622 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4623 SIVAL(pdata,0,mode);
4629 * CIFS UNIX Extensions.
4632 case SMB_QUERY_FILE_UNIX_BASIC:
4634 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4635 data_size = PTR_DIFF(pdata,(*ppdata));
4639 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4641 for (i=0; i<100; i++)
4642 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4648 case SMB_QUERY_FILE_UNIX_INFO2:
4650 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4651 data_size = PTR_DIFF(pdata,(*ppdata));
4655 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4657 for (i=0; i<100; i++)
4658 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4664 case SMB_QUERY_FILE_UNIX_LINK:
4666 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4669 reply_nterror(req, NT_STATUS_NO_MEMORY);
4673 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4675 if(!S_ISLNK(sbuf.st_ex_mode)) {
4676 reply_unixerror(req, ERRSRV,
4681 reply_unixerror(req, ERRDOS, ERRbadlink);
4684 len = SMB_VFS_READLINK(conn,fullpathname,
4687 reply_unixerror(req, ERRDOS,
4692 len = srvstr_push(dstart, req->flags2,
4694 PTR_DIFF(dend, pdata),
4697 data_size = PTR_DIFF(pdata,(*ppdata));
4702 #if defined(HAVE_POSIX_ACLS)
4703 case SMB_QUERY_POSIX_ACL:
4705 SMB_ACL_T file_acl = NULL;
4706 SMB_ACL_T def_acl = NULL;
4707 uint16 num_file_acls = 0;
4708 uint16 num_def_acls = 0;
4710 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4711 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4713 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4716 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4717 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4721 NT_STATUS_NOT_IMPLEMENTED);
4725 if (S_ISDIR(sbuf.st_ex_mode)) {
4726 if (fsp && fsp->is_directory) {
4727 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4729 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4731 def_acl = free_empty_sys_acl(conn, def_acl);
4734 num_file_acls = count_acl_entries(conn, file_acl);
4735 num_def_acls = count_acl_entries(conn, def_acl);
4737 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4738 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4740 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4741 SMB_POSIX_ACL_HEADER_SIZE) ));
4743 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4746 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4750 NT_STATUS_BUFFER_TOO_SMALL);
4754 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4755 SSVAL(pdata,2,num_file_acls);
4756 SSVAL(pdata,4,num_def_acls);
4757 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4759 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4762 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4765 req, NT_STATUS_INTERNAL_ERROR);
4768 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4770 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4773 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4777 NT_STATUS_INTERNAL_ERROR);
4782 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4785 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4787 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4793 case SMB_QUERY_POSIX_LOCK:
4798 enum brl_type lock_type;
4800 if (total_data != POSIX_LOCK_DATA_SIZE) {
4802 req, NT_STATUS_INVALID_PARAMETER);
4806 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4807 case POSIX_LOCK_TYPE_READ:
4808 lock_type = READ_LOCK;
4810 case POSIX_LOCK_TYPE_WRITE:
4811 lock_type = WRITE_LOCK;
4813 case POSIX_LOCK_TYPE_UNLOCK:
4815 /* There's no point in asking for an unlock... */
4818 NT_STATUS_INVALID_PARAMETER);
4822 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4823 #if defined(HAVE_LONGLONG)
4824 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4825 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4826 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4827 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4828 #else /* HAVE_LONGLONG */
4829 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4830 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4831 #endif /* HAVE_LONGLONG */
4833 status = query_lock(fsp,
4840 if (ERROR_WAS_LOCK_DENIED(status)) {
4841 /* Here we need to report who has it locked... */
4842 data_size = POSIX_LOCK_DATA_SIZE;
4844 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4845 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4846 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4847 #if defined(HAVE_LONGLONG)
4848 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4849 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4850 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4851 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4852 #else /* HAVE_LONGLONG */
4853 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4854 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4855 #endif /* HAVE_LONGLONG */
4857 } else if (NT_STATUS_IS_OK(status)) {
4858 /* For success we just return a copy of what we sent
4859 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4860 data_size = POSIX_LOCK_DATA_SIZE;
4861 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4862 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4864 reply_nterror(req, status);
4871 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4875 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4881 /****************************************************************************
4882 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4884 ****************************************************************************/
4886 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4887 connection_struct *conn,
4888 const struct smb_filename *smb_fname_old,
4889 const struct smb_filename *smb_fname_new)
4891 char *oldname = NULL;
4892 char *newname = NULL;
4893 NTSTATUS status = NT_STATUS_OK;
4895 /* source must already exist. */
4896 if (!VALID_STAT(smb_fname_old->st)) {
4897 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4900 /* Disallow if newname already exists. */
4901 if (VALID_STAT(smb_fname_new->st)) {
4902 return NT_STATUS_OBJECT_NAME_COLLISION;
4905 /* No links from a directory. */
4906 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
4907 return NT_STATUS_FILE_IS_A_DIRECTORY;
4910 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
4911 if (!NT_STATUS_IS_OK(status)) {
4914 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
4915 if (!NT_STATUS_IS_OK(status)) {
4919 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4921 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4922 status = map_nt_error_from_unix(errno);
4923 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4924 nt_errstr(status), newname, oldname));
4927 TALLOC_FREE(newname);
4928 TALLOC_FREE(oldname);
4932 /****************************************************************************
4933 Deal with setting the time from any of the setfilepathinfo functions.
4934 ****************************************************************************/
4936 NTSTATUS smb_set_file_time(connection_struct *conn,
4938 const struct smb_filename *smb_fname,
4939 struct smb_file_time *ft,
4940 bool setting_write_time)
4942 struct smb_filename *smb_fname_base = NULL;
4944 FILE_NOTIFY_CHANGE_LAST_ACCESS
4945 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4948 if (!VALID_STAT(smb_fname->st)) {
4949 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4952 /* get some defaults (no modifications) if any info is zero or -1. */
4953 if (null_timespec(ft->atime)) {
4954 ft->atime= smb_fname->st.st_ex_atime;
4955 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4958 if (null_timespec(ft->mtime)) {
4959 ft->mtime = smb_fname->st.st_ex_mtime;
4960 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4963 if (!setting_write_time) {
4964 /* ft->mtime comes from change time, not write time. */
4965 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4968 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4969 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4970 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4971 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4972 if (!null_timespec(ft->create_time)) {
4973 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4974 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4978 * Try and set the times of this file if
4979 * they are different from the current values.
4983 struct timespec mts = smb_fname->st.st_ex_mtime;
4984 struct timespec ats = smb_fname->st.st_ex_atime;
4985 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4986 (timespec_compare(&ft->mtime, &mts) == 0)) {
4987 return NT_STATUS_OK;
4991 if (setting_write_time) {
4993 * This was a Windows setfileinfo on an open file.
4994 * NT does this a lot. We also need to
4995 * set the time here, as it can be read by
4996 * FindFirst/FindNext and with the patch for bug #2045
4997 * in smbd/fileio.c it ensures that this timestamp is
4998 * kept sticky even after a write. We save the request
4999 * away and will set it on file close and after a write. JRA.
5002 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5003 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5006 if (fsp->base_fsp) {
5007 set_sticky_write_time_fsp(fsp->base_fsp,
5010 set_sticky_write_time_fsp(fsp, ft->mtime);
5013 set_sticky_write_time_path(
5014 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5019 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5021 /* Always call ntimes on the base, even if a stream was passed in. */
5022 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5023 NULL, &smb_fname->st,
5025 if (!NT_STATUS_IS_OK(status)) {
5029 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5030 TALLOC_FREE(smb_fname_base);
5031 return map_nt_error_from_unix(errno);
5033 TALLOC_FREE(smb_fname_base);
5035 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5036 smb_fname->base_name);
5037 return NT_STATUS_OK;
5040 /****************************************************************************
5041 Deal with setting the dosmode from any of the setfilepathinfo functions.
5042 ****************************************************************************/
5044 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5045 const struct smb_filename *smb_fname,
5048 struct smb_filename *smb_fname_base = NULL;
5051 if (!VALID_STAT(smb_fname->st)) {
5052 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5055 /* Always operate on the base_name, even if a stream was passed in. */
5056 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5057 NULL, &smb_fname->st,
5059 if (!NT_STATUS_IS_OK(status)) {
5064 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5071 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5073 /* check the mode isn't different, before changing it */
5074 if ((dosmode != 0) && (dosmode != dos_mode(conn,
5075 smb_fname_base->base_name,
5076 &smb_fname_base->st))) {
5077 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5078 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5079 (unsigned int)dosmode));
5081 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5083 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5085 smb_fname_str_dbg(smb_fname_base),
5087 status = map_nt_error_from_unix(errno);
5091 status = NT_STATUS_OK;
5093 TALLOC_FREE(smb_fname_base);
5097 /****************************************************************************
5098 Deal with setting the size from any of the setfilepathinfo functions.
5099 ****************************************************************************/
5101 static NTSTATUS smb_set_file_size(connection_struct *conn,
5102 struct smb_request *req,
5104 const struct smb_filename *smb_fname,
5105 const SMB_STRUCT_STAT *psbuf,
5108 NTSTATUS status = NT_STATUS_OK;
5109 struct smb_filename *smb_fname_tmp = NULL;
5110 files_struct *new_fsp = NULL;
5112 if (!VALID_STAT(*psbuf)) {
5113 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5116 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5118 if (size == get_file_size_stat(psbuf)) {
5119 return NT_STATUS_OK;
5122 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5123 smb_fname_str_dbg(smb_fname), (double)size));
5125 if (fsp && fsp->fh->fd != -1) {
5126 /* Handle based call. */
5127 if (vfs_set_filelen(fsp, size) == -1) {
5128 return map_nt_error_from_unix(errno);
5130 trigger_write_time_update_immediate(fsp);
5131 return NT_STATUS_OK;
5134 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5135 if (!NT_STATUS_IS_OK(status)) {
5139 smb_fname_tmp->st = *psbuf;
5141 status = SMB_VFS_CREATE_FILE(
5144 0, /* root_dir_fid */
5145 smb_fname_tmp, /* fname */
5146 FILE_WRITE_ATTRIBUTES, /* access_mask */
5147 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5149 FILE_OPEN, /* create_disposition*/
5150 0, /* create_options */
5151 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5152 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5153 0, /* allocation_size */
5156 &new_fsp, /* result */
5159 TALLOC_FREE(smb_fname_tmp);
5161 if (!NT_STATUS_IS_OK(status)) {
5162 /* NB. We check for open_was_deferred in the caller. */
5166 if (vfs_set_filelen(new_fsp, size) == -1) {
5167 status = map_nt_error_from_unix(errno);
5168 close_file(req, new_fsp,NORMAL_CLOSE);
5172 trigger_write_time_update_immediate(new_fsp);
5173 close_file(req, new_fsp,NORMAL_CLOSE);
5174 return NT_STATUS_OK;
5177 /****************************************************************************
5178 Deal with SMB_INFO_SET_EA.
5179 ****************************************************************************/
5181 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5185 const struct smb_filename *smb_fname)
5187 struct ea_list *ea_list = NULL;
5188 TALLOC_CTX *ctx = NULL;
5189 NTSTATUS status = NT_STATUS_OK;
5191 if (total_data < 10) {
5193 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5194 length. They seem to have no effect. Bug #3212. JRA */
5196 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5197 /* We're done. We only get EA info in this call. */
5198 return NT_STATUS_OK;
5201 return NT_STATUS_INVALID_PARAMETER;
5204 if (IVAL(pdata,0) > total_data) {
5205 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5206 IVAL(pdata,0), (unsigned int)total_data));
5207 return NT_STATUS_INVALID_PARAMETER;
5211 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5213 return NT_STATUS_INVALID_PARAMETER;
5215 status = set_ea(conn, fsp, smb_fname, ea_list);
5220 /****************************************************************************
5221 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5222 ****************************************************************************/
5224 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5229 SMB_STRUCT_STAT *psbuf)
5231 NTSTATUS status = NT_STATUS_OK;
5232 bool delete_on_close;
5235 if (total_data < 1) {
5236 return NT_STATUS_INVALID_PARAMETER;
5240 return NT_STATUS_INVALID_HANDLE;
5243 delete_on_close = (CVAL(pdata,0) ? True : False);
5244 dosmode = dos_mode(conn, fname, psbuf);
5246 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5247 "delete_on_close = %u\n",
5249 (unsigned int)dosmode,
5250 (unsigned int)delete_on_close ));
5252 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5254 if (!NT_STATUS_IS_OK(status)) {
5258 /* The set is across all open files on this dev/inode pair. */
5259 if (!set_delete_on_close(fsp, delete_on_close,
5260 &conn->server_info->utok)) {
5261 return NT_STATUS_ACCESS_DENIED;
5263 return NT_STATUS_OK;
5266 /****************************************************************************
5267 Deal with SMB_FILE_POSITION_INFORMATION.
5268 ****************************************************************************/
5270 static NTSTATUS smb_file_position_information(connection_struct *conn,
5275 uint64_t position_information;
5277 if (total_data < 8) {
5278 return NT_STATUS_INVALID_PARAMETER;
5282 /* Ignore on pathname based set. */
5283 return NT_STATUS_OK;
5286 position_information = (uint64_t)IVAL(pdata,0);
5287 #ifdef LARGE_SMB_OFF_T
5288 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5289 #else /* LARGE_SMB_OFF_T */
5290 if (IVAL(pdata,4) != 0) {
5291 /* more than 32 bits? */
5292 return NT_STATUS_INVALID_PARAMETER;
5294 #endif /* LARGE_SMB_OFF_T */
5296 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5297 fsp->fsp_name, (double)position_information ));
5298 fsp->fh->position_information = position_information;
5299 return NT_STATUS_OK;
5302 /****************************************************************************
5303 Deal with SMB_FILE_MODE_INFORMATION.
5304 ****************************************************************************/
5306 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5312 if (total_data < 4) {
5313 return NT_STATUS_INVALID_PARAMETER;
5315 mode = IVAL(pdata,0);
5316 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5317 return NT_STATUS_INVALID_PARAMETER;
5319 return NT_STATUS_OK;
5322 /****************************************************************************
5323 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5324 ****************************************************************************/
5326 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5327 struct smb_request *req,
5332 char *link_target = NULL;
5333 const char *newname = fname;
5334 NTSTATUS status = NT_STATUS_OK;
5335 TALLOC_CTX *ctx = talloc_tos();
5337 /* Set a symbolic link. */
5338 /* Don't allow this if follow links is false. */
5340 if (total_data == 0) {
5341 return NT_STATUS_INVALID_PARAMETER;
5344 if (!lp_symlinks(SNUM(conn))) {
5345 return NT_STATUS_ACCESS_DENIED;
5348 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5349 total_data, STR_TERMINATE);
5352 return NT_STATUS_INVALID_PARAMETER;
5355 /* !widelinks forces the target path to be within the share. */
5356 /* This means we can interpret the target as a pathname. */
5357 if (!lp_widelinks(SNUM(conn))) {
5358 char *rel_name = NULL;
5359 char *last_dirp = NULL;
5361 if (*link_target == '/') {
5362 /* No absolute paths allowed. */
5363 return NT_STATUS_ACCESS_DENIED;
5365 rel_name = talloc_strdup(ctx,newname);
5367 return NT_STATUS_NO_MEMORY;
5369 last_dirp = strrchr_m(rel_name, '/');
5371 last_dirp[1] = '\0';
5373 rel_name = talloc_strdup(ctx,"./");
5375 return NT_STATUS_NO_MEMORY;
5378 rel_name = talloc_asprintf_append(rel_name,
5382 return NT_STATUS_NO_MEMORY;
5385 status = check_name(conn, rel_name);
5386 if (!NT_STATUS_IS_OK(status)) {
5391 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5392 newname, link_target ));
5394 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5395 return map_nt_error_from_unix(errno);
5398 return NT_STATUS_OK;
5401 /****************************************************************************
5402 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5403 ****************************************************************************/
5405 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5406 struct smb_request *req,
5407 const char *pdata, int total_data,
5408 const struct smb_filename *smb_fname_new)
5410 char *oldname = NULL;
5411 struct smb_filename *smb_fname_old = NULL;
5412 TALLOC_CTX *ctx = talloc_tos();
5413 NTSTATUS status = NT_STATUS_OK;
5415 /* Set a hard link. */
5416 if (total_data == 0) {
5417 return NT_STATUS_INVALID_PARAMETER;
5420 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5421 total_data, STR_TERMINATE, &status);
5422 if (!NT_STATUS_IS_OK(status)) {
5426 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5427 smb_fname_str_dbg(smb_fname_new), oldname));
5429 status = filename_convert(ctx,
5431 req->flags2 & FLAGS2_DFS_PATHNAMES,
5435 if (!NT_STATUS_IS_OK(status)) {
5439 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5442 /****************************************************************************
5443 Deal with SMB_FILE_RENAME_INFORMATION.
5444 ****************************************************************************/
5446 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5447 struct smb_request *req,
5456 char *newname = NULL;
5457 char *base_name = NULL;
5458 struct smb_filename *smb_fname = NULL;
5459 bool dest_has_wcard = False;
5460 NTSTATUS status = NT_STATUS_OK;
5462 TALLOC_CTX *ctx = talloc_tos();
5464 if (total_data < 13) {
5465 return NT_STATUS_INVALID_PARAMETER;
5468 overwrite = (CVAL(pdata,0) ? True : False);
5469 root_fid = IVAL(pdata,4);
5470 len = IVAL(pdata,8);
5472 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5473 return NT_STATUS_INVALID_PARAMETER;
5476 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5479 if (!NT_STATUS_IS_OK(status)) {
5483 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5486 status = resolve_dfspath_wcard(ctx, conn,
5487 req->flags2 & FLAGS2_DFS_PATHNAMES,
5491 if (!NT_STATUS_IS_OK(status)) {
5495 /* Check the new name has no '/' characters. */
5496 if (strchr_m(newname, '/')) {
5497 return NT_STATUS_NOT_SUPPORTED;
5500 if (fsp && fsp->base_fsp) {
5501 /* newname must be a stream name. */
5502 if (newname[0] != ':') {
5503 return NT_STATUS_NOT_SUPPORTED;
5506 /* Create an smb_fname to call rename_internals_fsp() with. */
5507 status = create_synthetic_smb_fname(talloc_tos(),
5508 fsp->base_fsp->fsp_name,
5509 newname, NULL, &smb_fname);
5510 if (!NT_STATUS_IS_OK(status)) {
5515 * Set the original last component, since
5516 * rename_internals_fsp() requires it.
5518 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5519 if (smb_fname->original_lcomp == NULL) {
5520 status = NT_STATUS_NO_MEMORY;
5524 /* Create a char * to call rename_internals() with. */
5525 base_name = talloc_asprintf(ctx, "%s%s",
5526 fsp->base_fsp->fsp_name,
5529 status = NT_STATUS_NO_MEMORY;
5533 /* newname must *not* be a stream name. */
5534 if (is_ntfs_stream_name(newname)) {
5535 return NT_STATUS_NOT_SUPPORTED;
5538 /* Create the base directory. */
5539 base_name = talloc_strdup(ctx, fname);
5541 return NT_STATUS_NO_MEMORY;
5543 p = strrchr_m(base_name, '/');
5547 base_name = talloc_strdup(ctx, "./");
5549 return NT_STATUS_NO_MEMORY;
5552 /* Append the new name. */
5553 base_name = talloc_asprintf_append(base_name,
5557 return NT_STATUS_NO_MEMORY;
5560 status = unix_convert(ctx, conn, base_name, &smb_fname,
5563 /* If an error we expect this to be
5564 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5566 if (!NT_STATUS_IS_OK(status)) {
5567 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5571 /* Create an smb_fname to call rename_internals_fsp() */
5572 status = create_synthetic_smb_fname(talloc_tos(),
5575 if (!NT_STATUS_IS_OK(status)) {
5583 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5584 fsp->fnum, fsp->fsp_name, base_name ));
5585 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5588 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5589 fname, base_name ));
5590 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5591 overwrite, False, dest_has_wcard,
5592 FILE_WRITE_ATTRIBUTES);
5595 TALLOC_FREE(smb_fname);
5599 /****************************************************************************
5600 Deal with SMB_SET_POSIX_ACL.
5601 ****************************************************************************/
5603 #if defined(HAVE_POSIX_ACLS)
5604 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5609 SMB_STRUCT_STAT *psbuf)
5611 uint16 posix_acl_version;
5612 uint16 num_file_acls;
5613 uint16 num_def_acls;
5614 bool valid_file_acls = True;
5615 bool valid_def_acls = True;
5617 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5618 return NT_STATUS_INVALID_PARAMETER;
5620 posix_acl_version = SVAL(pdata,0);
5621 num_file_acls = SVAL(pdata,2);
5622 num_def_acls = SVAL(pdata,4);
5624 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5625 valid_file_acls = False;
5629 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5630 valid_def_acls = False;
5634 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5635 return NT_STATUS_INVALID_PARAMETER;
5638 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5639 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5640 return NT_STATUS_INVALID_PARAMETER;
5643 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5644 fname ? fname : fsp->fsp_name,
5645 (unsigned int)num_file_acls,
5646 (unsigned int)num_def_acls));
5648 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5649 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5650 return map_nt_error_from_unix(errno);
5653 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5654 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5655 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5656 return map_nt_error_from_unix(errno);
5658 return NT_STATUS_OK;
5662 /****************************************************************************
5663 Deal with SMB_SET_POSIX_LOCK.
5664 ****************************************************************************/
5666 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5667 struct smb_request *req,
5675 bool blocking_lock = False;
5676 enum brl_type lock_type;
5678 NTSTATUS status = NT_STATUS_OK;
5680 if (fsp == NULL || fsp->fh->fd == -1) {
5681 return NT_STATUS_INVALID_HANDLE;
5684 if (total_data != POSIX_LOCK_DATA_SIZE) {
5685 return NT_STATUS_INVALID_PARAMETER;
5688 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5689 case POSIX_LOCK_TYPE_READ:
5690 lock_type = READ_LOCK;
5692 case POSIX_LOCK_TYPE_WRITE:
5693 /* Return the right POSIX-mappable error code for files opened read-only. */
5694 if (!fsp->can_write) {
5695 return NT_STATUS_INVALID_HANDLE;
5697 lock_type = WRITE_LOCK;
5699 case POSIX_LOCK_TYPE_UNLOCK:
5700 lock_type = UNLOCK_LOCK;
5703 return NT_STATUS_INVALID_PARAMETER;
5706 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5707 blocking_lock = False;
5708 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5709 blocking_lock = True;
5711 return NT_STATUS_INVALID_PARAMETER;
5714 if (!lp_blocking_locks(SNUM(conn))) {
5715 blocking_lock = False;
5718 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5719 #if defined(HAVE_LONGLONG)
5720 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5721 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5722 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5723 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5724 #else /* HAVE_LONGLONG */
5725 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5726 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5727 #endif /* HAVE_LONGLONG */
5729 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5730 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5732 (unsigned int)lock_type,
5733 (unsigned int)lock_pid,
5737 if (lock_type == UNLOCK_LOCK) {
5738 status = do_unlock(smbd_messaging_context(),
5745 uint32 block_smbpid;
5747 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5759 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5761 * A blocking lock was requested. Package up
5762 * this smb into a queued request and push it
5763 * onto the blocking lock queue.
5765 if(push_blocking_lock_request(br_lck,
5768 -1, /* infinite timeout. */
5776 TALLOC_FREE(br_lck);
5780 TALLOC_FREE(br_lck);
5786 /****************************************************************************
5787 Deal with SMB_INFO_STANDARD.
5788 ****************************************************************************/
5790 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5794 const struct smb_filename *smb_fname)
5796 struct smb_file_time ft;
5799 if (total_data < 12) {
5800 return NT_STATUS_INVALID_PARAMETER;
5804 ft.create_time = interpret_long_date(pdata);
5807 ft.atime = interpret_long_date(pdata + 8);
5810 ft.mtime = interpret_long_date(pdata + 16);
5812 DEBUG(10,("smb_set_info_standard: file %s\n",
5813 smb_fname_str_dbg(smb_fname)));
5815 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5818 /****************************************************************************
5819 Deal with SMB_SET_FILE_BASIC_INFO.
5820 ****************************************************************************/
5822 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5826 const struct smb_filename *smb_fname)
5828 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5829 struct timespec write_time;
5830 struct timespec changed_time;
5831 struct smb_file_time ft;
5833 NTSTATUS status = NT_STATUS_OK;
5834 bool setting_write_time = true;
5838 if (total_data < 36) {
5839 return NT_STATUS_INVALID_PARAMETER;
5842 /* Set the attributes */
5843 dosmode = IVAL(pdata,32);
5844 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
5845 if (!NT_STATUS_IS_OK(status)) {
5850 ft.atime = interpret_long_date(pdata+8);
5852 write_time = interpret_long_date(pdata+16);
5853 changed_time = interpret_long_date(pdata+24);
5856 ft.mtime = timespec_min(&write_time, &changed_time);
5859 ft.create_time = interpret_long_date(pdata);
5861 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5862 !null_timespec(write_time)) {
5863 ft.mtime = write_time;
5866 /* Prefer a defined time to an undefined one. */
5867 if (null_timespec(ft.mtime)) {
5868 if (null_timespec(write_time)) {
5869 ft.mtime = changed_time;
5870 setting_write_time = false;
5872 ft.mtime = write_time;
5876 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
5877 smb_fname_str_dbg(smb_fname)));
5879 return smb_set_file_time(conn, fsp, smb_fname, &ft,
5880 setting_write_time);
5883 /****************************************************************************
5884 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5885 ****************************************************************************/
5887 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5888 struct smb_request *req,
5893 SMB_STRUCT_STAT *psbuf)
5895 struct smb_filename *smb_fname = NULL;
5896 uint64_t allocation_size = 0;
5897 NTSTATUS status = NT_STATUS_OK;
5898 files_struct *new_fsp = NULL;
5900 if (!VALID_STAT(*psbuf)) {
5901 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5904 if (total_data < 8) {
5905 return NT_STATUS_INVALID_PARAMETER;
5908 allocation_size = (uint64_t)IVAL(pdata,0);
5909 #ifdef LARGE_SMB_OFF_T
5910 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5911 #else /* LARGE_SMB_OFF_T */
5912 if (IVAL(pdata,4) != 0) {
5913 /* more than 32 bits? */
5914 return NT_STATUS_INVALID_PARAMETER;
5916 #endif /* LARGE_SMB_OFF_T */
5918 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5919 fname, (double)allocation_size ));
5921 if (allocation_size) {
5922 allocation_size = smb_roundup(conn, allocation_size);
5925 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5926 fname, (double)allocation_size ));
5928 if (fsp && fsp->fh->fd != -1) {
5929 /* Open file handle. */
5930 /* Only change if needed. */
5931 if (allocation_size != get_file_size_stat(psbuf)) {
5932 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5933 return map_nt_error_from_unix(errno);
5936 /* But always update the time. */
5938 * This is equivalent to a write. Ensure it's seen immediately
5939 * if there are no pending writes.
5941 trigger_write_time_update_immediate(fsp);
5942 return NT_STATUS_OK;
5945 /* Pathname or stat or directory file. */
5947 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5949 if (!NT_STATUS_IS_OK(status)) {
5953 status = SMB_VFS_CREATE_FILE(
5956 0, /* root_dir_fid */
5957 smb_fname, /* fname */
5958 FILE_WRITE_DATA, /* access_mask */
5959 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5961 FILE_OPEN, /* create_disposition*/
5962 0, /* create_options */
5963 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5964 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5965 0, /* allocation_size */
5968 &new_fsp, /* result */
5971 *psbuf = smb_fname->st;
5972 TALLOC_FREE(smb_fname);
5974 if (!NT_STATUS_IS_OK(status)) {
5975 /* NB. We check for open_was_deferred in the caller. */
5979 /* Only change if needed. */
5980 if (allocation_size != get_file_size_stat(psbuf)) {
5981 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5982 status = map_nt_error_from_unix(errno);
5983 close_file(req, new_fsp, NORMAL_CLOSE);
5988 /* Changing the allocation size should set the last mod time. */
5990 * This is equivalent to a write. Ensure it's seen immediately
5991 * if there are no pending writes.
5993 trigger_write_time_update_immediate(new_fsp);
5995 close_file(req, new_fsp, NORMAL_CLOSE);
5996 return NT_STATUS_OK;
5999 /****************************************************************************
6000 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6001 ****************************************************************************/
6003 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6004 struct smb_request *req,
6008 const struct smb_filename *smb_fname)
6012 if (total_data < 8) {
6013 return NT_STATUS_INVALID_PARAMETER;
6016 size = IVAL(pdata,0);
6017 #ifdef LARGE_SMB_OFF_T
6018 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6019 #else /* LARGE_SMB_OFF_T */
6020 if (IVAL(pdata,4) != 0) {
6021 /* more than 32 bits? */
6022 return NT_STATUS_INVALID_PARAMETER;
6024 #endif /* LARGE_SMB_OFF_T */
6025 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6026 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6029 return smb_set_file_size(conn, req,
6036 /****************************************************************************
6037 Allow a UNIX info mknod.
6038 ****************************************************************************/
6040 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6043 const struct smb_filename *smb_fname)
6045 uint32 file_type = IVAL(pdata,56);
6046 #if defined(HAVE_MAKEDEV)
6047 uint32 dev_major = IVAL(pdata,60);
6048 uint32 dev_minor = IVAL(pdata,68);
6050 SMB_DEV_T dev = (SMB_DEV_T)0;
6051 uint32 raw_unixmode = IVAL(pdata,84);
6055 if (total_data < 100) {
6056 return NT_STATUS_INVALID_PARAMETER;
6059 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6060 PERM_NEW_FILE, &unixmode);
6061 if (!NT_STATUS_IS_OK(status)) {
6065 #if defined(HAVE_MAKEDEV)
6066 dev = makedev(dev_major, dev_minor);
6069 switch (file_type) {
6070 #if defined(S_IFIFO)
6071 case UNIX_TYPE_FIFO:
6072 unixmode |= S_IFIFO;
6075 #if defined(S_IFSOCK)
6076 case UNIX_TYPE_SOCKET:
6077 unixmode |= S_IFSOCK;
6080 #if defined(S_IFCHR)
6081 case UNIX_TYPE_CHARDEV:
6082 unixmode |= S_IFCHR;
6085 #if defined(S_IFBLK)
6086 case UNIX_TYPE_BLKDEV:
6087 unixmode |= S_IFBLK;
6091 return NT_STATUS_INVALID_PARAMETER;
6094 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6095 "%.0f mode 0%o for file %s\n", (double)dev,
6096 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6098 /* Ok - do the mknod. */
6099 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6100 return map_nt_error_from_unix(errno);
6103 /* If any of the other "set" calls fail we
6104 * don't want to end up with a half-constructed mknod.
6107 if (lp_inherit_perms(SNUM(conn))) {
6109 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6111 return NT_STATUS_NO_MEMORY;
6113 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6115 TALLOC_FREE(parent);
6118 return NT_STATUS_OK;
6121 /****************************************************************************
6122 Deal with SMB_SET_FILE_UNIX_BASIC.
6123 ****************************************************************************/
6125 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6126 struct smb_request *req,
6130 const struct smb_filename *smb_fname)
6132 struct smb_file_time ft;
6133 uint32 raw_unixmode;
6136 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6137 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6138 NTSTATUS status = NT_STATUS_OK;
6139 bool delete_on_fail = False;
6140 enum perm_type ptype;
6141 files_struct *all_fsps = NULL;
6142 bool modify_mtime = true;
6144 SMB_STRUCT_STAT sbuf;
6148 if (total_data < 100) {
6149 return NT_STATUS_INVALID_PARAMETER;
6152 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6153 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6154 size=IVAL(pdata,0); /* first 8 Bytes are size */
6155 #ifdef LARGE_SMB_OFF_T
6156 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6157 #else /* LARGE_SMB_OFF_T */
6158 if (IVAL(pdata,4) != 0) {
6159 /* more than 32 bits? */
6160 return NT_STATUS_INVALID_PARAMETER;
6162 #endif /* LARGE_SMB_OFF_T */
6165 ft.atime = interpret_long_date(pdata+24); /* access_time */
6166 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6167 set_owner = (uid_t)IVAL(pdata,40);
6168 set_grp = (gid_t)IVAL(pdata,48);
6169 raw_unixmode = IVAL(pdata,84);
6171 if (VALID_STAT(smb_fname->st)) {
6172 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6173 ptype = PERM_EXISTING_DIR;
6175 ptype = PERM_EXISTING_FILE;
6178 ptype = PERM_NEW_FILE;
6181 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6183 if (!NT_STATUS_IS_OK(status)) {
6187 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6188 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6189 smb_fname_str_dbg(smb_fname), (double)size,
6190 (unsigned int)set_owner, (unsigned int)set_grp,
6191 (int)raw_unixmode));
6193 sbuf = smb_fname->st;
6195 if (!VALID_STAT(sbuf)) {
6196 struct smb_filename *smb_fname_tmp = NULL;
6198 * The only valid use of this is to create character and block
6199 * devices, and named pipes. This is deprecated (IMHO) and
6200 * a new info level should be used for mknod. JRA.
6203 status = smb_unix_mknod(conn,
6207 if (!NT_STATUS_IS_OK(status)) {
6211 status = copy_smb_filename(talloc_tos(), smb_fname,
6213 if (!NT_STATUS_IS_OK(status)) {
6217 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6218 status = map_nt_error_from_unix(errno);
6219 TALLOC_FREE(smb_fname_tmp);
6220 SMB_VFS_UNLINK(conn, smb_fname);
6224 sbuf = smb_fname_tmp->st;
6225 TALLOC_FREE(smb_fname_tmp);
6227 /* Ensure we don't try and change anything else. */
6228 raw_unixmode = SMB_MODE_NO_CHANGE;
6229 size = get_file_size_stat(&sbuf);
6230 ft.atime = sbuf.st_ex_atime;
6231 ft.mtime = sbuf.st_ex_mtime;
6233 * We continue here as we might want to change the
6236 delete_on_fail = True;
6240 /* Horrible backwards compatibility hack as an old server bug
6241 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6245 size = get_file_size_stat(&sbuf);
6250 * Deal with the UNIX specific mode set.
6253 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6254 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6255 "setting mode 0%o for file %s\n",
6256 (unsigned int)unixmode,
6257 smb_fname_str_dbg(smb_fname)));
6258 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6259 return map_nt_error_from_unix(errno);
6264 * Deal with the UNIX specific uid set.
6267 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6268 (sbuf.st_ex_uid != set_owner)) {
6271 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6272 "changing owner %u for path %s\n",
6273 (unsigned int)set_owner,
6274 smb_fname_str_dbg(smb_fname)));
6276 if (S_ISLNK(sbuf.st_ex_mode)) {
6277 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6278 set_owner, (gid_t)-1);
6280 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6281 set_owner, (gid_t)-1);
6285 status = map_nt_error_from_unix(errno);
6286 if (delete_on_fail) {
6287 SMB_VFS_UNLINK(conn, smb_fname);
6294 * Deal with the UNIX specific gid set.
6297 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6298 (sbuf.st_ex_gid != set_grp)) {
6299 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6300 "changing group %u for file %s\n",
6301 (unsigned int)set_owner,
6302 smb_fname_str_dbg(smb_fname)));
6303 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6305 status = map_nt_error_from_unix(errno);
6306 if (delete_on_fail) {
6307 SMB_VFS_UNLINK(conn, smb_fname);
6313 /* Deal with any size changes. */
6315 status = smb_set_file_size(conn, req,
6320 if (!NT_STATUS_IS_OK(status)) {
6324 /* Deal with any time changes. */
6325 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6326 /* No change, don't cancel anything. */
6330 id = vfs_file_id_from_sbuf(conn, &sbuf);
6331 for(all_fsps = file_find_di_first(id); all_fsps;
6332 all_fsps = file_find_di_next(all_fsps)) {
6334 * We're setting the time explicitly for UNIX.
6335 * Cancel any pending changes over all handles.
6337 all_fsps->update_write_time_on_close = false;
6338 TALLOC_FREE(all_fsps->update_write_time_event);
6342 * Override the "setting_write_time"
6343 * parameter here as it almost does what
6344 * we need. Just remember if we modified
6345 * mtime and send the notify ourselves.
6347 if (null_timespec(ft.mtime)) {
6348 modify_mtime = false;
6351 status = smb_set_file_time(conn,
6357 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6358 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6363 /****************************************************************************
6364 Deal with SMB_SET_FILE_UNIX_INFO2.
6365 ****************************************************************************/
6367 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6368 struct smb_request *req,
6372 const struct smb_filename *smb_fname)
6378 if (total_data < 116) {
6379 return NT_STATUS_INVALID_PARAMETER;
6382 /* Start by setting all the fields that are common between UNIX_BASIC
6385 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6387 if (!NT_STATUS_IS_OK(status)) {
6391 smb_fflags = IVAL(pdata, 108);
6392 smb_fmask = IVAL(pdata, 112);
6394 /* NB: We should only attempt to alter the file flags if the client
6395 * sends a non-zero mask.
6397 if (smb_fmask != 0) {
6398 int stat_fflags = 0;
6400 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6401 smb_fmask, &stat_fflags)) {
6402 /* Client asked to alter a flag we don't understand. */
6403 return NT_STATUS_INVALID_PARAMETER;
6406 if (fsp && fsp->fh->fd != -1) {
6407 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6408 return NT_STATUS_NOT_SUPPORTED;
6410 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6411 stat_fflags) != 0) {
6412 return map_nt_error_from_unix(errno);
6417 /* XXX: need to add support for changing the create_time here. You
6418 * can do this for paths on Darwin with setattrlist(2). The right way
6419 * to hook this up is probably by extending the VFS utimes interface.
6422 return NT_STATUS_OK;
6425 /****************************************************************************
6426 Create a directory with POSIX semantics.
6427 ****************************************************************************/
6429 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6430 struct smb_request *req,
6434 SMB_STRUCT_STAT *psbuf,
6435 int *pdata_return_size)
6437 struct smb_filename *smb_fname;
6438 NTSTATUS status = NT_STATUS_OK;
6439 uint32 raw_unixmode = 0;
6440 uint32 mod_unixmode = 0;
6441 mode_t unixmode = (mode_t)0;
6442 files_struct *fsp = NULL;
6443 uint16 info_level_return = 0;
6445 char *pdata = *ppdata;
6447 if (total_data < 18) {
6448 return NT_STATUS_INVALID_PARAMETER;
6451 raw_unixmode = IVAL(pdata,8);
6452 /* Next 4 bytes are not yet defined. */
6454 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6455 if (!NT_STATUS_IS_OK(status)) {
6459 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6461 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6462 fname, (unsigned int)unixmode ));
6464 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6466 if (!NT_STATUS_IS_OK(status)) {
6470 status = SMB_VFS_CREATE_FILE(
6473 0, /* root_dir_fid */
6474 smb_fname, /* fname */
6475 FILE_READ_ATTRIBUTES, /* access_mask */
6476 FILE_SHARE_NONE, /* share_access */
6477 FILE_CREATE, /* create_disposition*/
6478 FILE_DIRECTORY_FILE, /* create_options */
6479 mod_unixmode, /* file_attributes */
6480 0, /* oplock_request */
6481 0, /* allocation_size */
6487 *psbuf = smb_fname->st;
6488 TALLOC_FREE(smb_fname);
6490 if (NT_STATUS_IS_OK(status)) {
6491 close_file(req, fsp, NORMAL_CLOSE);
6494 info_level_return = SVAL(pdata,16);
6496 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6497 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6498 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6499 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6501 *pdata_return_size = 12;
6504 /* Realloc the data size */
6505 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6506 if (*ppdata == NULL) {
6507 *pdata_return_size = 0;
6508 return NT_STATUS_NO_MEMORY;
6512 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6513 SSVAL(pdata,2,0); /* No fnum. */
6514 SIVAL(pdata,4,info); /* Was directory created. */
6516 switch (info_level_return) {
6517 case SMB_QUERY_FILE_UNIX_BASIC:
6518 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6519 SSVAL(pdata,10,0); /* Padding. */
6520 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6522 case SMB_QUERY_FILE_UNIX_INFO2:
6523 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6524 SSVAL(pdata,10,0); /* Padding. */
6525 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6528 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6529 SSVAL(pdata,10,0); /* Padding. */
6536 /****************************************************************************
6537 Open/Create a file with POSIX semantics.
6538 ****************************************************************************/
6540 static NTSTATUS smb_posix_open(connection_struct *conn,
6541 struct smb_request *req,
6545 SMB_STRUCT_STAT *psbuf,
6546 int *pdata_return_size)
6548 struct smb_filename *smb_fname = NULL;
6549 bool extended_oplock_granted = False;
6550 char *pdata = *ppdata;
6552 uint32 wire_open_mode = 0;
6553 uint32 raw_unixmode = 0;
6554 uint32 mod_unixmode = 0;
6555 uint32 create_disp = 0;
6556 uint32 access_mask = 0;
6557 uint32 create_options = 0;
6558 NTSTATUS status = NT_STATUS_OK;
6559 mode_t unixmode = (mode_t)0;
6560 files_struct *fsp = NULL;
6561 int oplock_request = 0;
6563 uint16 info_level_return = 0;
6565 if (total_data < 18) {
6566 return NT_STATUS_INVALID_PARAMETER;
6569 flags = IVAL(pdata,0);
6570 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6571 if (oplock_request) {
6572 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6575 wire_open_mode = IVAL(pdata,4);
6577 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6578 return smb_posix_mkdir(conn, req,
6586 switch (wire_open_mode & SMB_ACCMODE) {
6588 access_mask = FILE_READ_DATA;
6591 access_mask = FILE_WRITE_DATA;
6594 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6597 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6598 (unsigned int)wire_open_mode ));
6599 return NT_STATUS_INVALID_PARAMETER;
6602 wire_open_mode &= ~SMB_ACCMODE;
6604 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6605 create_disp = FILE_CREATE;
6606 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6607 create_disp = FILE_OVERWRITE_IF;
6608 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6609 create_disp = FILE_OPEN_IF;
6610 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6611 create_disp = FILE_OPEN;
6613 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6614 (unsigned int)wire_open_mode ));
6615 return NT_STATUS_INVALID_PARAMETER;
6618 raw_unixmode = IVAL(pdata,8);
6619 /* Next 4 bytes are not yet defined. */
6621 status = unix_perms_from_wire(conn,
6624 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6627 if (!NT_STATUS_IS_OK(status)) {
6631 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6633 if (wire_open_mode & SMB_O_SYNC) {
6634 create_options |= FILE_WRITE_THROUGH;
6636 if (wire_open_mode & SMB_O_APPEND) {
6637 access_mask |= FILE_APPEND_DATA;
6639 if (wire_open_mode & SMB_O_DIRECT) {
6640 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6643 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6645 (unsigned int)wire_open_mode,
6646 (unsigned int)unixmode ));
6648 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6650 if (!NT_STATUS_IS_OK(status)) {
6654 status = SMB_VFS_CREATE_FILE(
6657 0, /* root_dir_fid */
6658 smb_fname, /* fname */
6659 access_mask, /* access_mask */
6660 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6662 create_disp, /* create_disposition*/
6663 FILE_NON_DIRECTORY_FILE, /* create_options */
6664 mod_unixmode, /* file_attributes */
6665 oplock_request, /* oplock_request */
6666 0, /* allocation_size */
6672 *psbuf = smb_fname->st;
6673 TALLOC_FREE(smb_fname);
6675 if (!NT_STATUS_IS_OK(status)) {
6679 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6680 extended_oplock_granted = True;
6683 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6684 extended_oplock_granted = True;
6687 info_level_return = SVAL(pdata,16);
6689 /* Allocate the correct return size. */
6691 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6692 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6693 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6694 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6696 *pdata_return_size = 12;
6699 /* Realloc the data size */
6700 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6701 if (*ppdata == NULL) {
6702 close_file(req, fsp, ERROR_CLOSE);
6703 *pdata_return_size = 0;
6704 return NT_STATUS_NO_MEMORY;
6708 if (extended_oplock_granted) {
6709 if (flags & REQUEST_BATCH_OPLOCK) {
6710 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6712 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6714 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6715 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6717 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6720 SSVAL(pdata,2,fsp->fnum);
6721 SIVAL(pdata,4,info); /* Was file created etc. */
6723 switch (info_level_return) {
6724 case SMB_QUERY_FILE_UNIX_BASIC:
6725 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6726 SSVAL(pdata,10,0); /* padding. */
6727 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6729 case SMB_QUERY_FILE_UNIX_INFO2:
6730 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6731 SSVAL(pdata,10,0); /* padding. */
6732 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6735 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6736 SSVAL(pdata,10,0); /* padding. */
6739 return NT_STATUS_OK;
6742 /****************************************************************************
6743 Delete a file with POSIX semantics.
6744 ****************************************************************************/
6746 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6747 struct smb_request *req,
6751 SMB_STRUCT_STAT *psbuf)
6753 struct smb_filename *smb_fname = NULL;
6754 NTSTATUS status = NT_STATUS_OK;
6755 files_struct *fsp = NULL;
6759 int create_options = 0;
6761 struct share_mode_lock *lck = NULL;
6763 if (total_data < 2) {
6764 return NT_STATUS_INVALID_PARAMETER;
6767 flags = SVAL(pdata,0);
6769 if (!VALID_STAT(*psbuf)) {
6770 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6773 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6774 !VALID_STAT_OF_DIR(*psbuf)) {
6775 return NT_STATUS_NOT_A_DIRECTORY;
6778 DEBUG(10,("smb_posix_unlink: %s %s\n",
6779 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6782 if (VALID_STAT_OF_DIR(*psbuf)) {
6783 create_options |= FILE_DIRECTORY_FILE;
6786 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6788 if (!NT_STATUS_IS_OK(status)) {
6792 status = SMB_VFS_CREATE_FILE(
6795 0, /* root_dir_fid */
6796 smb_fname, /* fname */
6797 DELETE_ACCESS, /* access_mask */
6798 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6800 FILE_OPEN, /* create_disposition*/
6801 create_options, /* create_options */
6802 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6803 0, /* oplock_request */
6804 0, /* allocation_size */
6810 *psbuf = smb_fname->st;
6811 TALLOC_FREE(smb_fname);
6813 if (!NT_STATUS_IS_OK(status)) {
6818 * Don't lie to client. If we can't really delete due to
6819 * non-POSIX opens return SHARING_VIOLATION.
6822 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6825 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6826 "lock for file %s\n", fsp->fsp_name));
6827 close_file(req, fsp, NORMAL_CLOSE);
6828 return NT_STATUS_INVALID_PARAMETER;
6832 * See if others still have the file open. If this is the case, then
6833 * don't delete. If all opens are POSIX delete we can set the delete
6834 * on close disposition.
6836 for (i=0; i<lck->num_share_modes; i++) {
6837 struct share_mode_entry *e = &lck->share_modes[i];
6838 if (is_valid_share_mode_entry(e)) {
6839 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6842 /* Fail with sharing violation. */
6843 close_file(req, fsp, NORMAL_CLOSE);
6845 return NT_STATUS_SHARING_VIOLATION;
6850 * Set the delete on close.
6852 status = smb_set_file_disposition_info(conn,
6859 if (!NT_STATUS_IS_OK(status)) {
6860 close_file(req, fsp, NORMAL_CLOSE);
6865 return close_file(req, fsp, NORMAL_CLOSE);
6868 /****************************************************************************
6869 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6870 ****************************************************************************/
6872 static void call_trans2setfilepathinfo(connection_struct *conn,
6873 struct smb_request *req,
6874 unsigned int tran_call,
6875 char **pparams, int total_params,
6876 char **ppdata, int total_data,
6877 unsigned int max_data_bytes)
6879 char *params = *pparams;
6880 char *pdata = *ppdata;
6882 SMB_STRUCT_STAT sbuf;
6884 struct smb_filename *smb_fname = NULL;
6885 files_struct *fsp = NULL;
6886 NTSTATUS status = NT_STATUS_OK;
6887 int data_return_size = 0;
6888 TALLOC_CTX *ctx = talloc_tos();
6891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6895 if (tran_call == TRANSACT2_SETFILEINFO) {
6896 if (total_params < 4) {
6897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6901 fsp = file_fsp(req, SVAL(params,0));
6902 /* Basic check for non-null fsp. */
6903 if (!check_fsp_open(conn, req, fsp)) {
6906 info_level = SVAL(params,2);
6908 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6910 reply_nterror(req, NT_STATUS_NO_MEMORY);
6914 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
6916 if (!NT_STATUS_IS_OK(status)) {
6917 reply_nterror(req, status);
6921 if(fsp->is_directory || fsp->fh->fd == -1) {
6923 * This is actually a SETFILEINFO on a directory
6924 * handle (returned from an NT SMB). NT5.0 seems
6925 * to do this call. JRA.
6927 if (INFO_LEVEL_IS_UNIX(info_level)) {
6928 /* Always do lstat for UNIX calls. */
6929 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6930 DEBUG(3,("call_trans2setfilepathinfo: "
6931 "SMB_VFS_LSTAT of %s failed "
6933 smb_fname_str_dbg(smb_fname),
6935 reply_unixerror(req,ERRDOS,ERRbadpath);
6939 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6940 DEBUG(3,("call_trans2setfilepathinfo: "
6941 "fileinfo of %s failed (%s)\n",
6942 smb_fname_str_dbg(smb_fname),
6944 reply_unixerror(req,ERRDOS,ERRbadpath);
6948 } else if (fsp->print_file) {
6950 * Doing a DELETE_ON_CLOSE should cancel a print job.
6952 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6953 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6955 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6958 send_trans2_replies(conn, req, params, 2,
6963 reply_unixerror(req, ERRDOS, ERRbadpath);
6968 * Original code - this is an open file.
6970 if (!check_fsp(conn, req, fsp)) {
6974 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6975 DEBUG(3,("call_trans2setfilepathinfo: fstat "
6976 "of fnum %d failed (%s)\n", fsp->fnum,
6978 reply_unixerror(req, ERRDOS, ERRbadfid);
6984 if (total_params < 7) {
6985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6989 info_level = SVAL(params,0);
6990 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6991 total_params - 6, STR_TERMINATE,
6993 if (!NT_STATUS_IS_OK(status)) {
6994 reply_nterror(req, status);
6998 status = filename_convert(ctx, conn,
6999 req->flags2 & FLAGS2_DFS_PATHNAMES,
7003 if (!NT_STATUS_IS_OK(status)) {
7004 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7005 reply_botherror(req,
7006 NT_STATUS_PATH_NOT_COVERED,
7007 ERRSRV, ERRbadpath);
7010 reply_nterror(req, status);
7014 if (INFO_LEVEL_IS_UNIX(info_level)) {
7016 * For CIFS UNIX extensions the target name may not exist.
7019 /* Always do lstat for UNIX calls. */
7020 SMB_VFS_LSTAT(conn, smb_fname);
7022 } else if (!VALID_STAT(smb_fname->st) &&
7023 SMB_VFS_STAT(conn, smb_fname)) {
7024 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7026 smb_fname_str_dbg(smb_fname),
7028 reply_unixerror(req, ERRDOS, ERRbadpath);
7033 /* Set sbuf for use below. */
7034 sbuf = smb_fname->st;
7036 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7037 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7041 if (!CAN_WRITE(conn)) {
7042 /* Allow POSIX opens. The open path will deny
7043 * any non-readonly opens. */
7044 if (info_level != SMB_POSIX_PATH_OPEN) {
7045 reply_doserror(req, ERRSRV, ERRaccess);
7050 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
7051 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
7053 /* Realloc the parameter size */
7054 *pparams = (char *)SMB_REALLOC(*pparams,2);
7055 if (*pparams == NULL) {
7056 reply_nterror(req, NT_STATUS_NO_MEMORY);
7063 switch (info_level) {
7065 case SMB_INFO_STANDARD:
7067 status = smb_set_info_standard(conn,
7075 case SMB_INFO_SET_EA:
7077 status = smb_info_set_ea(conn,
7085 case SMB_SET_FILE_BASIC_INFO:
7086 case SMB_FILE_BASIC_INFORMATION:
7088 status = smb_set_file_basic_info(conn,
7096 case SMB_FILE_ALLOCATION_INFORMATION:
7097 case SMB_SET_FILE_ALLOCATION_INFO:
7099 status = smb_set_file_allocation_info(conn, req,
7108 case SMB_FILE_END_OF_FILE_INFORMATION:
7109 case SMB_SET_FILE_END_OF_FILE_INFO:
7111 status = smb_set_file_end_of_file_info(conn, req,
7119 case SMB_FILE_DISPOSITION_INFORMATION:
7120 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7123 /* JRA - We used to just ignore this on a path ?
7124 * Shouldn't this be invalid level on a pathname
7127 if (tran_call != TRANSACT2_SETFILEINFO) {
7128 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7131 status = smb_set_file_disposition_info(conn,
7140 case SMB_FILE_POSITION_INFORMATION:
7142 status = smb_file_position_information(conn,
7149 /* From tridge Samba4 :
7150 * MODE_INFORMATION in setfileinfo (I have no
7151 * idea what "mode information" on a file is - it takes a value of 0,
7152 * 2, 4 or 6. What could it be?).
7155 case SMB_FILE_MODE_INFORMATION:
7157 status = smb_file_mode_information(conn,
7164 * CIFS UNIX extensions.
7167 case SMB_SET_FILE_UNIX_BASIC:
7169 status = smb_set_file_unix_basic(conn, req,
7177 case SMB_SET_FILE_UNIX_INFO2:
7179 status = smb_set_file_unix_info2(conn, req,
7187 case SMB_SET_FILE_UNIX_LINK:
7189 if (tran_call != TRANSACT2_SETPATHINFO) {
7190 /* We must have a pathname for this. */
7191 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7194 status = smb_set_file_unix_link(conn, req, pdata,
7199 case SMB_SET_FILE_UNIX_HLINK:
7201 if (tran_call != TRANSACT2_SETPATHINFO || smb_fname == NULL) {
7202 /* We must have a pathname for this. */
7203 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7206 status = smb_set_file_unix_hlink(conn, req,
7212 case SMB_FILE_RENAME_INFORMATION:
7214 status = smb_file_rename_information(conn, req,
7220 #if defined(HAVE_POSIX_ACLS)
7221 case SMB_SET_POSIX_ACL:
7223 status = smb_set_posix_acl(conn,
7233 case SMB_SET_POSIX_LOCK:
7235 if (tran_call != TRANSACT2_SETFILEINFO) {
7236 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7239 status = smb_set_posix_lock(conn, req,
7240 pdata, total_data, fsp);
7244 case SMB_POSIX_PATH_OPEN:
7246 if (tran_call != TRANSACT2_SETPATHINFO) {
7247 /* We must have a pathname for this. */
7248 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7252 status = smb_posix_open(conn, req,
7261 case SMB_POSIX_PATH_UNLINK:
7263 if (tran_call != TRANSACT2_SETPATHINFO) {
7264 /* We must have a pathname for this. */
7265 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7269 status = smb_posix_unlink(conn, req,
7278 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7282 if (!NT_STATUS_IS_OK(status)) {
7283 if (open_was_deferred(req->mid)) {
7284 /* We have re-scheduled this call. */
7287 if (blocking_lock_was_deferred(req->mid)) {
7288 /* We have re-scheduled this call. */
7291 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7292 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7293 ERRSRV, ERRbadpath);
7296 if (info_level == SMB_POSIX_PATH_OPEN) {
7297 reply_openerror(req, status);
7301 reply_nterror(req, status);
7306 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7312 /****************************************************************************
7313 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7314 ****************************************************************************/
7316 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7317 char **pparams, int total_params,
7318 char **ppdata, int total_data,
7319 unsigned int max_data_bytes)
7321 struct smb_filename *smb_dname = NULL;
7322 char *params = *pparams;
7323 char *pdata = *ppdata;
7324 char *directory = NULL;
7325 NTSTATUS status = NT_STATUS_OK;
7326 struct ea_list *ea_list = NULL;
7327 TALLOC_CTX *ctx = talloc_tos();
7329 if (!CAN_WRITE(conn)) {
7330 reply_doserror(req, ERRSRV, ERRaccess);
7334 if (total_params < 5) {
7335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7339 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7340 total_params - 4, STR_TERMINATE,
7342 if (!NT_STATUS_IS_OK(status)) {
7343 reply_nterror(req, status);
7347 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7349 status = filename_convert(ctx,
7351 req->flags2 & FLAGS2_DFS_PATHNAMES,
7356 if (!NT_STATUS_IS_OK(status)) {
7357 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7358 reply_botherror(req,
7359 NT_STATUS_PATH_NOT_COVERED,
7360 ERRSRV, ERRbadpath);
7363 reply_nterror(req, status);
7367 /* Any data in this call is an EA list. */
7368 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7369 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7374 * OS/2 workplace shell seems to send SET_EA requests of "null"
7375 * length (4 bytes containing IVAL 4).
7376 * They seem to have no effect. Bug #3212. JRA.
7379 if (total_data != 4) {
7380 if (total_data < 10) {
7381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7385 if (IVAL(pdata,0) > total_data) {
7386 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7387 IVAL(pdata,0), (unsigned int)total_data));
7388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7392 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7399 /* If total_data == 4 Windows doesn't care what values
7400 * are placed in that field, it just ignores them.
7401 * The System i QNTC IBM SMB client puts bad values here,
7402 * so ignore them. */
7404 status = create_directory(conn, req, smb_dname);
7406 if (!NT_STATUS_IS_OK(status)) {
7407 reply_nterror(req, status);
7411 /* Try and set any given EA. */
7413 status = set_ea(conn, NULL, smb_dname, ea_list);
7414 if (!NT_STATUS_IS_OK(status)) {
7415 reply_nterror(req, status);
7420 /* Realloc the parameter and data sizes */
7421 *pparams = (char *)SMB_REALLOC(*pparams,2);
7422 if(*pparams == NULL) {
7423 reply_nterror(req, NT_STATUS_NO_MEMORY);
7430 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7433 TALLOC_FREE(smb_dname);
7437 /****************************************************************************
7438 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7439 We don't actually do this - we just send a null response.
7440 ****************************************************************************/
7442 static void call_trans2findnotifyfirst(connection_struct *conn,
7443 struct smb_request *req,
7444 char **pparams, int total_params,
7445 char **ppdata, int total_data,
7446 unsigned int max_data_bytes)
7448 char *params = *pparams;
7451 if (total_params < 6) {
7452 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7456 info_level = SVAL(params,4);
7457 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7459 switch (info_level) {
7464 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7468 /* Realloc the parameter and data sizes */
7469 *pparams = (char *)SMB_REALLOC(*pparams,6);
7470 if (*pparams == NULL) {
7471 reply_nterror(req, NT_STATUS_NO_MEMORY);
7476 SSVAL(params,0,fnf_handle);
7477 SSVAL(params,2,0); /* No changes */
7478 SSVAL(params,4,0); /* No EA errors */
7485 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7490 /****************************************************************************
7491 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7492 changes). Currently this does nothing.
7493 ****************************************************************************/
7495 static void call_trans2findnotifynext(connection_struct *conn,
7496 struct smb_request *req,
7497 char **pparams, int total_params,
7498 char **ppdata, int total_data,
7499 unsigned int max_data_bytes)
7501 char *params = *pparams;
7503 DEBUG(3,("call_trans2findnotifynext\n"));
7505 /* Realloc the parameter and data sizes */
7506 *pparams = (char *)SMB_REALLOC(*pparams,4);
7507 if (*pparams == NULL) {
7508 reply_nterror(req, NT_STATUS_NO_MEMORY);
7513 SSVAL(params,0,0); /* No changes */
7514 SSVAL(params,2,0); /* No EA errors */
7516 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7521 /****************************************************************************
7522 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7523 ****************************************************************************/
7525 static void call_trans2getdfsreferral(connection_struct *conn,
7526 struct smb_request *req,
7527 char **pparams, int total_params,
7528 char **ppdata, int total_data,
7529 unsigned int max_data_bytes)
7531 char *params = *pparams;
7532 char *pathname = NULL;
7534 int max_referral_level;
7535 NTSTATUS status = NT_STATUS_OK;
7536 TALLOC_CTX *ctx = talloc_tos();
7538 DEBUG(10,("call_trans2getdfsreferral\n"));
7540 if (total_params < 3) {
7541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7545 max_referral_level = SVAL(params,0);
7547 if(!lp_host_msdfs()) {
7548 reply_doserror(req, ERRDOS, ERRbadfunc);
7552 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7553 total_params - 2, STR_TERMINATE);
7555 reply_nterror(req, NT_STATUS_NOT_FOUND);
7558 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7559 ppdata,&status)) < 0) {
7560 reply_nterror(req, status);
7564 SSVAL(req->inbuf, smb_flg2,
7565 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7566 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7571 #define LMCAT_SPL 0x53
7572 #define LMFUNC_GETJOBID 0x60
7574 /****************************************************************************
7575 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7576 ****************************************************************************/
7578 static void call_trans2ioctl(connection_struct *conn,
7579 struct smb_request *req,
7580 char **pparams, int total_params,
7581 char **ppdata, int total_data,
7582 unsigned int max_data_bytes)
7584 char *pdata = *ppdata;
7585 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7587 /* check for an invalid fid before proceeding */
7590 reply_doserror(req, ERRDOS, ERRbadfid);
7594 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7595 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7596 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7597 if (*ppdata == NULL) {
7598 reply_nterror(req, NT_STATUS_NO_MEMORY);
7603 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7604 CAN ACCEPT THIS IN UNICODE. JRA. */
7606 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7607 srvstr_push(pdata, req->flags2, pdata + 2,
7608 global_myname(), 15,
7609 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7610 srvstr_push(pdata, req->flags2, pdata+18,
7611 lp_servicename(SNUM(conn)), 13,
7612 STR_ASCII|STR_TERMINATE); /* Service name */
7613 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7618 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7619 reply_doserror(req, ERRSRV, ERRerror);
7622 /****************************************************************************
7623 Reply to a SMBfindclose (stop trans2 directory search).
7624 ****************************************************************************/
7626 void reply_findclose(struct smb_request *req)
7630 START_PROFILE(SMBfindclose);
7633 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7634 END_PROFILE(SMBfindclose);
7638 dptr_num = SVALS(req->vwv+0, 0);
7640 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7642 dptr_close(&dptr_num);
7644 reply_outbuf(req, 0, 0);
7646 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7648 END_PROFILE(SMBfindclose);
7652 /****************************************************************************
7653 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7654 ****************************************************************************/
7656 void reply_findnclose(struct smb_request *req)
7660 START_PROFILE(SMBfindnclose);
7663 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7664 END_PROFILE(SMBfindnclose);
7668 dptr_num = SVAL(req->vwv+0, 0);
7670 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7672 /* We never give out valid handles for a
7673 findnotifyfirst - so any dptr_num is ok here.
7676 reply_outbuf(req, 0, 0);
7678 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7680 END_PROFILE(SMBfindnclose);
7684 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7685 struct trans_state *state)
7687 if (Protocol >= PROTOCOL_NT1) {
7688 req->flags2 |= 0x40; /* IS_LONG_NAME */
7689 SSVAL(req->inbuf,smb_flg2,req->flags2);
7692 if (conn->encrypt_level == Required && !req->encrypted) {
7693 if (state->call != TRANSACT2_QFSINFO &&
7694 state->call != TRANSACT2_SETFSINFO) {
7695 DEBUG(0,("handle_trans2: encryption required "
7697 (unsigned int)state->call));
7698 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7703 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7705 /* Now we must call the relevant TRANS2 function */
7706 switch(state->call) {
7707 case TRANSACT2_OPEN:
7709 START_PROFILE(Trans2_open);
7710 call_trans2open(conn, req,
7711 &state->param, state->total_param,
7712 &state->data, state->total_data,
7713 state->max_data_return);
7714 END_PROFILE(Trans2_open);
7718 case TRANSACT2_FINDFIRST:
7720 START_PROFILE(Trans2_findfirst);
7721 call_trans2findfirst(conn, req,
7722 &state->param, state->total_param,
7723 &state->data, state->total_data,
7724 state->max_data_return);
7725 END_PROFILE(Trans2_findfirst);
7729 case TRANSACT2_FINDNEXT:
7731 START_PROFILE(Trans2_findnext);
7732 call_trans2findnext(conn, req,
7733 &state->param, state->total_param,
7734 &state->data, state->total_data,
7735 state->max_data_return);
7736 END_PROFILE(Trans2_findnext);
7740 case TRANSACT2_QFSINFO:
7742 START_PROFILE(Trans2_qfsinfo);
7743 call_trans2qfsinfo(conn, req,
7744 &state->param, state->total_param,
7745 &state->data, state->total_data,
7746 state->max_data_return);
7747 END_PROFILE(Trans2_qfsinfo);
7751 case TRANSACT2_SETFSINFO:
7753 START_PROFILE(Trans2_setfsinfo);
7754 call_trans2setfsinfo(conn, req,
7755 &state->param, state->total_param,
7756 &state->data, state->total_data,
7757 state->max_data_return);
7758 END_PROFILE(Trans2_setfsinfo);
7762 case TRANSACT2_QPATHINFO:
7763 case TRANSACT2_QFILEINFO:
7765 START_PROFILE(Trans2_qpathinfo);
7766 call_trans2qfilepathinfo(conn, req, state->call,
7767 &state->param, state->total_param,
7768 &state->data, state->total_data,
7769 state->max_data_return);
7770 END_PROFILE(Trans2_qpathinfo);
7774 case TRANSACT2_SETPATHINFO:
7775 case TRANSACT2_SETFILEINFO:
7777 START_PROFILE(Trans2_setpathinfo);
7778 call_trans2setfilepathinfo(conn, req, state->call,
7779 &state->param, state->total_param,
7780 &state->data, state->total_data,
7781 state->max_data_return);
7782 END_PROFILE(Trans2_setpathinfo);
7786 case TRANSACT2_FINDNOTIFYFIRST:
7788 START_PROFILE(Trans2_findnotifyfirst);
7789 call_trans2findnotifyfirst(conn, req,
7790 &state->param, state->total_param,
7791 &state->data, state->total_data,
7792 state->max_data_return);
7793 END_PROFILE(Trans2_findnotifyfirst);
7797 case TRANSACT2_FINDNOTIFYNEXT:
7799 START_PROFILE(Trans2_findnotifynext);
7800 call_trans2findnotifynext(conn, req,
7801 &state->param, state->total_param,
7802 &state->data, state->total_data,
7803 state->max_data_return);
7804 END_PROFILE(Trans2_findnotifynext);
7808 case TRANSACT2_MKDIR:
7810 START_PROFILE(Trans2_mkdir);
7811 call_trans2mkdir(conn, req,
7812 &state->param, state->total_param,
7813 &state->data, state->total_data,
7814 state->max_data_return);
7815 END_PROFILE(Trans2_mkdir);
7819 case TRANSACT2_GET_DFS_REFERRAL:
7821 START_PROFILE(Trans2_get_dfs_referral);
7822 call_trans2getdfsreferral(conn, req,
7823 &state->param, state->total_param,
7824 &state->data, state->total_data,
7825 state->max_data_return);
7826 END_PROFILE(Trans2_get_dfs_referral);
7830 case TRANSACT2_IOCTL:
7832 START_PROFILE(Trans2_ioctl);
7833 call_trans2ioctl(conn, req,
7834 &state->param, state->total_param,
7835 &state->data, state->total_data,
7836 state->max_data_return);
7837 END_PROFILE(Trans2_ioctl);
7842 /* Error in request */
7843 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7844 reply_doserror(req, ERRSRV,ERRerror);
7848 /****************************************************************************
7849 Reply to a SMBtrans2.
7850 ****************************************************************************/
7852 void reply_trans2(struct smb_request *req)
7854 connection_struct *conn = req->conn;
7859 unsigned int tran_call;
7860 struct trans_state *state;
7863 START_PROFILE(SMBtrans2);
7865 if (req->wct < 14) {
7866 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7867 END_PROFILE(SMBtrans2);
7871 dsoff = SVAL(req->vwv+12, 0);
7872 dscnt = SVAL(req->vwv+11, 0);
7873 psoff = SVAL(req->vwv+10, 0);
7874 pscnt = SVAL(req->vwv+9, 0);
7875 tran_call = SVAL(req->vwv+14, 0);
7877 result = allow_new_trans(conn->pending_trans, req->mid);
7878 if (!NT_STATUS_IS_OK(result)) {
7879 DEBUG(2, ("Got invalid trans2 request: %s\n",
7880 nt_errstr(result)));
7881 reply_nterror(req, result);
7882 END_PROFILE(SMBtrans2);
7887 switch (tran_call) {
7888 /* List the allowed trans2 calls on IPC$ */
7889 case TRANSACT2_OPEN:
7890 case TRANSACT2_GET_DFS_REFERRAL:
7891 case TRANSACT2_QFILEINFO:
7892 case TRANSACT2_QFSINFO:
7893 case TRANSACT2_SETFSINFO:
7896 reply_doserror(req, ERRSRV, ERRaccess);
7897 END_PROFILE(SMBtrans2);
7902 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7903 DEBUG(0, ("talloc failed\n"));
7904 reply_nterror(req, NT_STATUS_NO_MEMORY);
7905 END_PROFILE(SMBtrans2);
7909 state->cmd = SMBtrans2;
7911 state->mid = req->mid;
7912 state->vuid = req->vuid;
7913 state->setup_count = SVAL(req->vwv+13, 0);
7914 state->setup = NULL;
7915 state->total_param = SVAL(req->vwv+0, 0);
7916 state->param = NULL;
7917 state->total_data = SVAL(req->vwv+1, 0);
7919 state->max_param_return = SVAL(req->vwv+2, 0);
7920 state->max_data_return = SVAL(req->vwv+3, 0);
7921 state->max_setup_return = SVAL(req->vwv+4, 0);
7922 state->close_on_completion = BITSETW(req->vwv+5, 0);
7923 state->one_way = BITSETW(req->vwv+5, 1);
7925 state->call = tran_call;
7927 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7928 is so as a sanity check */
7929 if (state->setup_count != 1) {
7931 * Need to have rc=0 for ioctl to get job id for OS/2.
7932 * Network printing will fail if function is not successful.
7933 * Similar function in reply.c will be used if protocol
7934 * is LANMAN1.0 instead of LM1.2X002.
7935 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7936 * outbuf doesn't have to be set(only job id is used).
7938 if ( (state->setup_count == 4)
7939 && (tran_call == TRANSACT2_IOCTL)
7940 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7941 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7942 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7944 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7945 DEBUG(2,("Transaction is %d\n",tran_call));
7947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7948 END_PROFILE(SMBtrans2);
7953 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7956 if (state->total_data) {
7958 if (trans_oob(state->total_data, 0, dscnt)
7959 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7963 /* Can't use talloc here, the core routines do realloc on the
7964 * params and data. */
7965 state->data = (char *)SMB_MALLOC(state->total_data);
7966 if (state->data == NULL) {
7967 DEBUG(0,("reply_trans2: data malloc fail for %u "
7968 "bytes !\n", (unsigned int)state->total_data));
7970 reply_nterror(req, NT_STATUS_NO_MEMORY);
7971 END_PROFILE(SMBtrans2);
7975 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7978 if (state->total_param) {
7980 if (trans_oob(state->total_param, 0, pscnt)
7981 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7985 /* Can't use talloc here, the core routines do realloc on the
7986 * params and data. */
7987 state->param = (char *)SMB_MALLOC(state->total_param);
7988 if (state->param == NULL) {
7989 DEBUG(0,("reply_trans: param malloc fail for %u "
7990 "bytes !\n", (unsigned int)state->total_param));
7991 SAFE_FREE(state->data);
7993 reply_nterror(req, NT_STATUS_NO_MEMORY);
7994 END_PROFILE(SMBtrans2);
7998 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8001 state->received_data = dscnt;
8002 state->received_param = pscnt;
8004 if ((state->received_param == state->total_param) &&
8005 (state->received_data == state->total_data)) {
8007 handle_trans2(conn, req, state);
8009 SAFE_FREE(state->data);
8010 SAFE_FREE(state->param);
8012 END_PROFILE(SMBtrans2);
8016 DLIST_ADD(conn->pending_trans, state);
8018 /* We need to send an interim response then receive the rest
8019 of the parameter/data bytes */
8020 reply_outbuf(req, 0, 0);
8021 show_msg((char *)req->outbuf);
8022 END_PROFILE(SMBtrans2);
8027 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8028 SAFE_FREE(state->data);
8029 SAFE_FREE(state->param);
8031 END_PROFILE(SMBtrans2);
8032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8036 /****************************************************************************
8037 Reply to a SMBtranss2
8038 ****************************************************************************/
8040 void reply_transs2(struct smb_request *req)
8042 connection_struct *conn = req->conn;
8043 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8044 struct trans_state *state;
8046 START_PROFILE(SMBtranss2);
8048 show_msg((char *)req->inbuf);
8051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8052 END_PROFILE(SMBtranss2);
8056 for (state = conn->pending_trans; state != NULL;
8057 state = state->next) {
8058 if (state->mid == req->mid) {
8063 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8064 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8065 END_PROFILE(SMBtranss2);
8069 /* Revise state->total_param and state->total_data in case they have
8070 changed downwards */
8072 if (SVAL(req->vwv+0, 0) < state->total_param)
8073 state->total_param = SVAL(req->vwv+0, 0);
8074 if (SVAL(req->vwv+1, 0) < state->total_data)
8075 state->total_data = SVAL(req->vwv+1, 0);
8077 pcnt = SVAL(req->vwv+2, 0);
8078 poff = SVAL(req->vwv+3, 0);
8079 pdisp = SVAL(req->vwv+4, 0);
8081 dcnt = SVAL(req->vwv+5, 0);
8082 doff = SVAL(req->vwv+6, 0);
8083 ddisp = SVAL(req->vwv+7, 0);
8085 state->received_param += pcnt;
8086 state->received_data += dcnt;
8088 if ((state->received_data > state->total_data) ||
8089 (state->received_param > state->total_param))
8093 if (trans_oob(state->total_param, pdisp, pcnt)
8094 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8097 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8101 if (trans_oob(state->total_data, ddisp, dcnt)
8102 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8105 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8108 if ((state->received_param < state->total_param) ||
8109 (state->received_data < state->total_data)) {
8110 END_PROFILE(SMBtranss2);
8114 handle_trans2(conn, req, state);
8116 DLIST_REMOVE(conn->pending_trans, state);
8117 SAFE_FREE(state->data);
8118 SAFE_FREE(state->param);
8121 END_PROFILE(SMBtranss2);
8126 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8127 DLIST_REMOVE(conn->pending_trans, state);
8128 SAFE_FREE(state->data);
8129 SAFE_FREE(state->param);
8131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8132 END_PROFILE(SMBtranss2);