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);
718 /* When sending params and data ensure that both are nicely aligned */
719 /* Only do this alignment when there is also data to send - else
720 can cause NT redirector problems. */
722 if (((params_to_send % 4) != 0) && (data_to_send != 0))
723 data_alignment_offset = 4 - (params_to_send % 4);
725 /* Space is bufsize minus Netbios over TCP header minus SMB header */
726 /* The alignment_offset is to align the param bytes on an even byte
727 boundary. NT 4.0 Beta needs this to work correctly. */
729 useable_space = max_send - (smb_size
732 + data_alignment_offset);
734 if (useable_space < 0) {
735 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
736 "= %d!!!", useable_space));
737 exit_server_cleanly("send_trans2_replies: Not enough space");
740 while (params_to_send || data_to_send) {
741 /* Calculate whether we will totally or partially fill this packet */
743 total_sent_thistime = params_to_send + data_to_send;
745 /* We can never send more than useable_space */
747 * Note that 'useable_space' does not include the alignment offsets,
748 * but we must include the alignment offsets in the calculation of
749 * the length of the data we send over the wire, as the alignment offsets
750 * are sent here. Fix from Marc_Jacobsen@hp.com.
753 total_sent_thistime = MIN(total_sent_thistime, useable_space);
755 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
756 + data_alignment_offset);
759 * We might have SMBtrans2s in req which was transferred to
760 * the outbuf, fix that.
762 SCVAL(req->outbuf, smb_com, SMBtrans2);
764 /* Set total params and data to be sent */
765 SSVAL(req->outbuf,smb_tprcnt,paramsize);
766 SSVAL(req->outbuf,smb_tdrcnt,datasize);
768 /* Calculate how many parameters and data we can fit into
769 * this packet. Parameters get precedence
772 params_sent_thistime = MIN(params_to_send,useable_space);
773 data_sent_thistime = useable_space - params_sent_thistime;
774 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
776 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
778 /* smb_proff is the offset from the start of the SMB header to the
779 parameter bytes, however the first 4 bytes of outbuf are
780 the Netbios over TCP header. Thus use smb_base() to subtract
781 them from the calculation */
783 SSVAL(req->outbuf,smb_proff,
784 ((smb_buf(req->outbuf)+alignment_offset)
785 - smb_base(req->outbuf)));
787 if(params_sent_thistime == 0)
788 SSVAL(req->outbuf,smb_prdisp,0);
790 /* Absolute displacement of param bytes sent in this packet */
791 SSVAL(req->outbuf,smb_prdisp,pp - params);
793 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
794 if(data_sent_thistime == 0) {
795 SSVAL(req->outbuf,smb_droff,0);
796 SSVAL(req->outbuf,smb_drdisp, 0);
798 /* The offset of the data bytes is the offset of the
799 parameter bytes plus the number of parameters being sent this time */
800 SSVAL(req->outbuf, smb_droff,
801 ((smb_buf(req->outbuf)+alignment_offset)
802 - smb_base(req->outbuf))
803 + params_sent_thistime + data_alignment_offset);
804 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
807 /* Initialize the padding for alignment */
809 if (alignment_offset != 0) {
810 memset(smb_buf(req->outbuf), 0, alignment_offset);
813 /* Copy the param bytes into the packet */
815 if(params_sent_thistime) {
816 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
817 params_sent_thistime);
820 /* Copy in the data bytes */
821 if(data_sent_thistime) {
822 if (data_alignment_offset != 0) {
823 memset((smb_buf(req->outbuf)+alignment_offset+
824 params_sent_thistime), 0,
825 data_alignment_offset);
827 memcpy(smb_buf(req->outbuf)+alignment_offset
828 +params_sent_thistime+data_alignment_offset,
829 pd,data_sent_thistime);
832 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
833 params_sent_thistime, data_sent_thistime, useable_space));
834 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
835 params_to_send, data_to_send, paramsize, datasize));
838 error_packet_set((char *)req->outbuf,
839 ERRDOS,ERRbufferoverflow,
840 STATUS_BUFFER_OVERFLOW,
844 /* Send the packet */
845 show_msg((char *)req->outbuf);
846 if (!srv_send_smb(smbd_server_fd(),
849 IS_CONN_ENCRYPTED(conn),
851 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
853 TALLOC_FREE(req->outbuf);
855 pp += params_sent_thistime;
856 pd += data_sent_thistime;
858 params_to_send -= params_sent_thistime;
859 data_to_send -= data_sent_thistime;
862 if(params_to_send < 0 || data_to_send < 0) {
863 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
864 params_to_send, data_to_send));
872 /****************************************************************************
873 Reply to a TRANSACT2_OPEN.
874 ****************************************************************************/
876 static void call_trans2open(connection_struct *conn,
877 struct smb_request *req,
878 char **pparams, int total_params,
879 char **ppdata, int total_data,
880 unsigned int max_data_bytes)
882 struct smb_filename *smb_fname = NULL;
883 char *params = *pparams;
884 char *pdata = *ppdata;
889 bool return_additional_info;
902 struct ea_list *ea_list = NULL;
907 uint32 create_disposition;
908 uint32 create_options = 0;
909 TALLOC_CTX *ctx = talloc_tos();
912 * Ensure we have enough parameters to perform the operation.
915 if (total_params < 29) {
916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
920 flags = SVAL(params, 0);
921 deny_mode = SVAL(params, 2);
922 open_attr = SVAL(params,6);
923 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
924 if (oplock_request) {
925 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
929 return_additional_info = BITSETW(params,0);
930 open_sattr = SVAL(params, 4);
931 open_time = make_unix_date3(params+8);
933 open_ofun = SVAL(params,12);
934 open_size = IVAL(params,14);
938 reply_doserror(req, ERRSRV, ERRaccess);
942 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
943 total_params - 28, STR_TERMINATE,
945 if (!NT_STATUS_IS_OK(status)) {
946 reply_nterror(req, status);
950 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
951 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
952 (unsigned int)open_ofun, open_size));
954 status = filename_convert(ctx,
956 req->flags2 & FLAGS2_DFS_PATHNAMES,
960 if (!NT_STATUS_IS_OK(status)) {
961 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
963 NT_STATUS_PATH_NOT_COVERED,
967 reply_nterror(req, status);
971 if (open_ofun == 0) {
972 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
976 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
981 reply_doserror(req, ERRDOS, ERRbadaccess);
985 /* Any data in this call is an EA list. */
986 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
987 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
991 if (total_data != 4) {
992 if (total_data < 10) {
993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
997 if (IVAL(pdata,0) > total_data) {
998 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
999 IVAL(pdata,0), (unsigned int)total_data));
1000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1004 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1007 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1010 } else if (IVAL(pdata,0) != 4) {
1011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1015 status = SMB_VFS_CREATE_FILE(
1018 0, /* root_dir_fid */
1019 smb_fname, /* fname */
1020 access_mask, /* access_mask */
1021 share_mode, /* share_access */
1022 create_disposition, /* create_disposition*/
1023 create_options, /* create_options */
1024 open_attr, /* file_attributes */
1025 oplock_request, /* oplock_request */
1026 open_size, /* allocation_size */
1028 ea_list, /* ea_list */
1030 &smb_action); /* psbuf */
1032 if (!NT_STATUS_IS_OK(status)) {
1033 if (open_was_deferred(req->mid)) {
1034 /* We have re-scheduled this call. */
1037 reply_openerror(req, status);
1041 size = get_file_size_stat(&smb_fname->st);
1042 fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st);
1043 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1044 inode = smb_fname->st.st_ex_ino;
1046 close_file(req, fsp, ERROR_CLOSE);
1047 reply_doserror(req, ERRDOS,ERRnoaccess);
1051 /* Realloc the size of parameters and data we will return */
1052 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1053 if(*pparams == NULL ) {
1054 reply_nterror(req, NT_STATUS_NO_MEMORY);
1059 SSVAL(params,0,fsp->fnum);
1060 SSVAL(params,2,fattr);
1061 srv_put_dos_date2(params,4, mtime);
1062 SIVAL(params,8, (uint32)size);
1063 SSVAL(params,12,deny_mode);
1064 SSVAL(params,14,0); /* open_type - file or directory. */
1065 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1067 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1068 smb_action |= EXTENDED_OPLOCK_GRANTED;
1071 SSVAL(params,18,smb_action);
1074 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1076 SIVAL(params,20,inode);
1077 SSVAL(params,24,0); /* Padding. */
1079 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1080 SIVAL(params, 26, ea_size);
1082 SIVAL(params, 26, 0);
1085 /* Send the required number of replies */
1086 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1088 TALLOC_FREE(smb_fname);
1091 /*********************************************************
1092 Routine to check if a given string matches exactly.
1093 as a special case a mask of "." does NOT match. That
1094 is required for correct wildcard semantics
1095 Case can be significant or not.
1096 **********************************************************/
1098 static bool exact_match(connection_struct *conn,
1102 if (mask[0] == '.' && mask[1] == 0)
1104 if (dptr_has_wild(conn->dirptr)) {
1107 if (conn->case_sensitive)
1108 return strcmp(str,mask)==0;
1110 return StrCaseCmp(str,mask) == 0;
1113 /****************************************************************************
1114 Return the filetype for UNIX extensions.
1115 ****************************************************************************/
1117 static uint32 unix_filetype(mode_t mode)
1120 return UNIX_TYPE_FILE;
1121 else if(S_ISDIR(mode))
1122 return UNIX_TYPE_DIR;
1124 else if(S_ISLNK(mode))
1125 return UNIX_TYPE_SYMLINK;
1128 else if(S_ISCHR(mode))
1129 return UNIX_TYPE_CHARDEV;
1132 else if(S_ISBLK(mode))
1133 return UNIX_TYPE_BLKDEV;
1136 else if(S_ISFIFO(mode))
1137 return UNIX_TYPE_FIFO;
1140 else if(S_ISSOCK(mode))
1141 return UNIX_TYPE_SOCKET;
1144 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1145 return UNIX_TYPE_UNKNOWN;
1148 /****************************************************************************
1149 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1150 ****************************************************************************/
1152 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1154 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1155 SMB_STRUCT_STAT *psbuf,
1157 enum perm_type ptype,
1162 if (perms == SMB_MODE_NO_CHANGE) {
1163 if (!VALID_STAT(*psbuf)) {
1164 return NT_STATUS_INVALID_PARAMETER;
1166 *ret_perms = psbuf->st_ex_mode;
1167 return NT_STATUS_OK;
1171 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1172 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1173 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1174 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1175 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1176 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1177 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1178 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1179 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1181 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1184 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1187 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1192 /* Apply mode mask */
1193 ret &= lp_create_mask(SNUM(conn));
1194 /* Add in force bits */
1195 ret |= lp_force_create_mode(SNUM(conn));
1198 ret &= lp_dir_mask(SNUM(conn));
1199 /* Add in force bits */
1200 ret |= lp_force_dir_mode(SNUM(conn));
1202 case PERM_EXISTING_FILE:
1203 /* Apply mode mask */
1204 ret &= lp_security_mask(SNUM(conn));
1205 /* Add in force bits */
1206 ret |= lp_force_security_mode(SNUM(conn));
1208 case PERM_EXISTING_DIR:
1209 /* Apply mode mask */
1210 ret &= lp_dir_security_mask(SNUM(conn));
1211 /* Add in force bits */
1212 ret |= lp_force_dir_security_mode(SNUM(conn));
1217 return NT_STATUS_OK;
1220 /****************************************************************************
1221 Needed to show the msdfs symlinks as directories. Modifies psbuf
1222 to be a directory if it's a msdfs link.
1223 ****************************************************************************/
1225 static bool check_msdfs_link(connection_struct *conn,
1226 const char *pathname,
1227 SMB_STRUCT_STAT *psbuf)
1229 int saved_errno = errno;
1230 if(lp_host_msdfs() &&
1231 lp_msdfs_root(SNUM(conn)) &&
1232 is_msdfs_link(conn, pathname, psbuf)) {
1234 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1237 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1238 errno = saved_errno;
1241 errno = saved_errno;
1246 /****************************************************************************
1247 Get a level dependent lanman2 dir entry.
1248 ****************************************************************************/
1250 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1251 connection_struct *conn,
1253 const char *path_mask,
1256 int requires_resume_key,
1262 int space_remaining,
1264 bool *got_exact_match,
1265 int *last_entry_off,
1266 struct ea_list *name_list)
1270 SMB_STRUCT_STAT sbuf;
1271 const char *mask = NULL;
1272 char *pathreal = NULL;
1274 char *p, *q, *pdata = *ppdata;
1278 SMB_OFF_T file_size = 0;
1279 uint64_t allocation_size = 0;
1281 struct timespec mdate_ts, adate_ts, create_date_ts;
1282 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1284 char *last_entry_ptr;
1286 uint32 nt_extmode; /* Used for NT connections instead of mode */
1287 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1288 bool check_mangled_names = lp_manglednames(conn->params);
1289 char mangled_name[13]; /* mangled 8.3 name. */
1291 *out_of_space = False;
1292 *got_exact_match = False;
1294 ZERO_STRUCT(mdate_ts);
1295 ZERO_STRUCT(adate_ts);
1296 ZERO_STRUCT(create_date_ts);
1298 if (!conn->dirptr) {
1302 p = strrchr_m(path_mask,'/');
1305 mask = talloc_strdup(ctx,"*.*");
1315 bool ms_dfs_link = False;
1317 /* Needed if we run out of space */
1318 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1319 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1322 * Due to bugs in NT client redirectors we are not using
1323 * resume keys any more - set them to zero.
1324 * Check out the related comments in findfirst/findnext.
1330 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1331 (long)conn->dirptr,curr_dirpos));
1338 * fname may get mangled, dname is never mangled.
1339 * Whenever we're accessing the filesystem we use
1340 * pathreal which is composed from dname.
1346 /* Mangle fname if it's an illegal name. */
1347 if (mangle_must_mangle(dname,conn->params)) {
1348 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1350 continue; /* Error - couldn't mangle. */
1352 fname = talloc_strdup(ctx, mangled_name);
1358 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1359 got_match = mask_match(fname, mask, conn->case_sensitive);
1362 if(!got_match && check_mangled_names &&
1363 !mangle_is_8_3(fname, False, conn->params)) {
1365 * It turns out that NT matches wildcards against
1366 * both long *and* short names. This may explain some
1367 * of the wildcard wierdness from old DOS clients
1368 * that some people have been seeing.... JRA.
1370 /* Force the mangling into 8.3. */
1371 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1373 continue; /* Error - couldn't mangle. */
1376 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1377 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1382 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1384 if (dont_descend && !isdots) {
1391 pathreal = talloc_asprintf(ctx,
1396 pathreal = talloc_asprintf(ctx,
1407 if (INFO_LEVEL_IS_UNIX(info_level)) {
1408 if (vfs_lstat_smb_fname(conn, pathreal,
1410 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1411 pathreal,strerror(errno)));
1412 TALLOC_FREE(pathreal);
1416 } else if (!VALID_STAT(sbuf) &&
1417 vfs_stat_smb_fname(conn, pathreal,
1419 /* Needed to show the msdfs symlinks as
1422 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1424 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1425 pathreal,strerror(errno)));
1426 TALLOC_FREE(pathreal);
1433 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1435 mode = dos_mode(conn,pathreal,&sbuf);
1438 if (!dir_check_ftype(conn,mode,dirtype)) {
1439 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1440 TALLOC_FREE(pathreal);
1445 if (!(mode & aDIR)) {
1446 file_size = get_file_size_stat(&sbuf);
1448 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1450 mdate_ts = sbuf.st_ex_mtime;
1451 adate_ts = sbuf.st_ex_atime;
1452 create_date_ts = sbuf.st_ex_btime;
1454 if (ask_sharemode) {
1455 struct timespec write_time_ts;
1456 struct file_id fileid;
1458 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1459 get_file_infos(fileid, NULL, &write_time_ts);
1460 if (!null_timespec(write_time_ts)) {
1461 mdate_ts = write_time_ts;
1465 if (lp_dos_filetime_resolution(SNUM(conn))) {
1466 dos_filetime_timespec(&create_date_ts);
1467 dos_filetime_timespec(&mdate_ts);
1468 dos_filetime_timespec(&adate_ts);
1471 create_date = convert_timespec_to_time_t(create_date_ts);
1472 mdate = convert_timespec_to_time_t(mdate_ts);
1473 adate = convert_timespec_to_time_t(adate_ts);
1475 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1480 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1490 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1492 switch (info_level) {
1493 case SMB_FIND_INFO_STANDARD:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1495 if(requires_resume_key) {
1499 srv_put_dos_date2(p,0,create_date);
1500 srv_put_dos_date2(p,4,adate);
1501 srv_put_dos_date2(p,8,mdate);
1502 SIVAL(p,12,(uint32)file_size);
1503 SIVAL(p,16,(uint32)allocation_size);
1507 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1508 p += ucs2_align(base_data, p, 0);
1510 len = srvstr_push(base_data, flags2, p,
1511 fname, PTR_DIFF(end_data, p),
1513 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1515 SCVAL(nameptr, -1, len - 2);
1517 SCVAL(nameptr, -1, 0);
1521 SCVAL(nameptr, -1, len - 1);
1523 SCVAL(nameptr, -1, 0);
1529 case SMB_FIND_EA_SIZE:
1530 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1531 if(requires_resume_key) {
1535 srv_put_dos_date2(p,0,create_date);
1536 srv_put_dos_date2(p,4,adate);
1537 srv_put_dos_date2(p,8,mdate);
1538 SIVAL(p,12,(uint32)file_size);
1539 SIVAL(p,16,(uint32)allocation_size);
1542 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1543 SIVAL(p,22,ea_size); /* Extended attributes */
1547 len = srvstr_push(base_data, flags2,
1548 p, fname, PTR_DIFF(end_data, p),
1549 STR_TERMINATE | STR_NOALIGN);
1550 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1563 SCVAL(nameptr,0,len);
1565 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1568 case SMB_FIND_EA_LIST:
1570 struct ea_list *file_list = NULL;
1573 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1577 if(requires_resume_key) {
1581 srv_put_dos_date2(p,0,create_date);
1582 srv_put_dos_date2(p,4,adate);
1583 srv_put_dos_date2(p,8,mdate);
1584 SIVAL(p,12,(uint32)file_size);
1585 SIVAL(p,16,(uint32)allocation_size);
1587 p += 22; /* p now points to the EA area. */
1589 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1590 name_list = ea_list_union(name_list, file_list, &ea_len);
1592 /* We need to determine if this entry will fit in the space available. */
1593 /* Max string size is 255 bytes. */
1594 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1595 /* Move the dirptr back to prev_dirpos */
1596 dptr_SeekDir(conn->dirptr, prev_dirpos);
1597 *out_of_space = True;
1598 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1599 return False; /* Not finished - just out of space */
1602 /* Push the ea_data followed by the name. */
1603 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1605 len = srvstr_push(base_data, flags2,
1606 p + 1, fname, PTR_DIFF(end_data, p+1),
1607 STR_TERMINATE | STR_NOALIGN);
1608 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1621 SCVAL(nameptr,0,len);
1623 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1627 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1628 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1629 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1631 SIVAL(p,0,reskey); p += 4;
1632 put_long_date_timespec(p,create_date_ts); p += 8;
1633 put_long_date_timespec(p,adate_ts); p += 8;
1634 put_long_date_timespec(p,mdate_ts); p += 8;
1635 put_long_date_timespec(p,mdate_ts); p += 8;
1636 SOFF_T(p,0,file_size); p += 8;
1637 SOFF_T(p,0,allocation_size); p += 8;
1638 SIVAL(p,0,nt_extmode); p += 4;
1639 q = p; p += 4; /* q is placeholder for name length. */
1641 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1642 SIVAL(p,0,ea_size); /* Extended attributes */
1645 /* Clear the short name buffer. This is
1646 * IMPORTANT as not doing so will trigger
1647 * a Win2k client bug. JRA.
1649 if (!was_8_3 && check_mangled_names) {
1650 if (!name_to_8_3(fname,mangled_name,True,
1652 /* Error - mangle failed ! */
1653 memset(mangled_name,'\0',12);
1655 mangled_name[12] = 0;
1656 len = srvstr_push(base_data, flags2,
1657 p+2, mangled_name, 24,
1658 STR_UPPER|STR_UNICODE);
1660 memset(p + 2 + len,'\0',24 - len);
1667 len = srvstr_push(base_data, flags2, p,
1668 fname, PTR_DIFF(end_data, p),
1669 STR_TERMINATE_ASCII);
1672 SIVAL(p,0,0); /* Ensure any padding is null. */
1673 len = PTR_DIFF(p, pdata);
1674 len = (len + 3) & ~3;
1679 case SMB_FIND_FILE_DIRECTORY_INFO:
1680 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1682 SIVAL(p,0,reskey); p += 4;
1683 put_long_date_timespec(p,create_date_ts); p += 8;
1684 put_long_date_timespec(p,adate_ts); p += 8;
1685 put_long_date_timespec(p,mdate_ts); p += 8;
1686 put_long_date_timespec(p,mdate_ts); p += 8;
1687 SOFF_T(p,0,file_size); p += 8;
1688 SOFF_T(p,0,allocation_size); p += 8;
1689 SIVAL(p,0,nt_extmode); p += 4;
1690 len = srvstr_push(base_data, flags2,
1691 p + 4, fname, PTR_DIFF(end_data, p+4),
1692 STR_TERMINATE_ASCII);
1695 SIVAL(p,0,0); /* Ensure any padding is null. */
1696 len = PTR_DIFF(p, pdata);
1697 len = (len + 3) & ~3;
1702 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1703 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1705 SIVAL(p,0,reskey); p += 4;
1706 put_long_date_timespec(p,create_date_ts); p += 8;
1707 put_long_date_timespec(p,adate_ts); p += 8;
1708 put_long_date_timespec(p,mdate_ts); p += 8;
1709 put_long_date_timespec(p,mdate_ts); p += 8;
1710 SOFF_T(p,0,file_size); p += 8;
1711 SOFF_T(p,0,allocation_size); p += 8;
1712 SIVAL(p,0,nt_extmode); p += 4;
1713 q = p; p += 4; /* q is placeholder for name length. */
1715 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1716 SIVAL(p,0,ea_size); /* Extended attributes */
1719 len = srvstr_push(base_data, flags2, p,
1720 fname, PTR_DIFF(end_data, p),
1721 STR_TERMINATE_ASCII);
1725 SIVAL(p,0,0); /* Ensure any padding is null. */
1726 len = PTR_DIFF(p, pdata);
1727 len = (len + 3) & ~3;
1732 case SMB_FIND_FILE_NAMES_INFO:
1733 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1735 SIVAL(p,0,reskey); p += 4;
1737 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1738 acl on a dir (tridge) */
1739 len = srvstr_push(base_data, flags2, p,
1740 fname, PTR_DIFF(end_data, p),
1741 STR_TERMINATE_ASCII);
1744 SIVAL(p,0,0); /* Ensure any padding is null. */
1745 len = PTR_DIFF(p, pdata);
1746 len = (len + 3) & ~3;
1751 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1752 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1754 SIVAL(p,0,reskey); p += 4;
1755 put_long_date_timespec(p,create_date_ts); p += 8;
1756 put_long_date_timespec(p,adate_ts); p += 8;
1757 put_long_date_timespec(p,mdate_ts); p += 8;
1758 put_long_date_timespec(p,mdate_ts); p += 8;
1759 SOFF_T(p,0,file_size); p += 8;
1760 SOFF_T(p,0,allocation_size); p += 8;
1761 SIVAL(p,0,nt_extmode); p += 4;
1762 q = p; p += 4; /* q is placeholder for name length. */
1764 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1765 SIVAL(p,0,ea_size); /* Extended attributes */
1768 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1769 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1770 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1771 len = srvstr_push(base_data, flags2, p,
1772 fname, PTR_DIFF(end_data, p),
1773 STR_TERMINATE_ASCII);
1776 SIVAL(p,0,0); /* Ensure any padding is null. */
1777 len = PTR_DIFF(p, pdata);
1778 len = (len + 3) & ~3;
1783 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1784 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1785 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1787 SIVAL(p,0,reskey); p += 4;
1788 put_long_date_timespec(p,create_date_ts); p += 8;
1789 put_long_date_timespec(p,adate_ts); p += 8;
1790 put_long_date_timespec(p,mdate_ts); p += 8;
1791 put_long_date_timespec(p,mdate_ts); p += 8;
1792 SOFF_T(p,0,file_size); p += 8;
1793 SOFF_T(p,0,allocation_size); p += 8;
1794 SIVAL(p,0,nt_extmode); p += 4;
1795 q = p; p += 4; /* q is placeholder for name length */
1797 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1798 SIVAL(p,0,ea_size); /* Extended attributes */
1801 /* Clear the short name buffer. This is
1802 * IMPORTANT as not doing so will trigger
1803 * a Win2k client bug. JRA.
1805 if (!was_8_3 && check_mangled_names) {
1806 if (!name_to_8_3(fname,mangled_name,True,
1808 /* Error - mangle failed ! */
1809 memset(mangled_name,'\0',12);
1811 mangled_name[12] = 0;
1812 len = srvstr_push(base_data, flags2,
1813 p+2, mangled_name, 24,
1814 STR_UPPER|STR_UNICODE);
1817 memset(p + 2 + len,'\0',24 - len);
1824 SSVAL(p,0,0); p += 2; /* Reserved ? */
1825 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1826 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1827 len = srvstr_push(base_data, flags2, p,
1828 fname, PTR_DIFF(end_data, p),
1829 STR_TERMINATE_ASCII);
1832 SIVAL(p,0,0); /* Ensure any padding is null. */
1833 len = PTR_DIFF(p, pdata);
1834 len = (len + 3) & ~3;
1839 /* CIFS UNIX Extension. */
1841 case SMB_FIND_FILE_UNIX:
1842 case SMB_FIND_FILE_UNIX_INFO2:
1844 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1846 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1848 if (info_level == SMB_FIND_FILE_UNIX) {
1849 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1850 p = store_file_unix_basic(conn, p,
1852 len = srvstr_push(base_data, flags2, p,
1853 fname, PTR_DIFF(end_data, p),
1856 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1857 p = store_file_unix_basic_info2(conn, p,
1861 len = srvstr_push(base_data, flags2, p, fname,
1862 PTR_DIFF(end_data, p), 0);
1863 SIVAL(nameptr, 0, len);
1867 SIVAL(p,0,0); /* Ensure any padding is null. */
1869 len = PTR_DIFF(p, pdata);
1870 len = (len + 3) & ~3;
1871 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1873 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1883 if (PTR_DIFF(p,pdata) > space_remaining) {
1884 /* Move the dirptr back to prev_dirpos */
1885 dptr_SeekDir(conn->dirptr, prev_dirpos);
1886 *out_of_space = True;
1887 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1888 return False; /* Not finished - just out of space */
1891 /* Setup the last entry pointer, as an offset from base_data */
1892 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1893 /* Advance the data pointer to the next slot */
1899 /****************************************************************************
1900 Reply to a TRANS2_FINDFIRST.
1901 ****************************************************************************/
1903 static void call_trans2findfirst(connection_struct *conn,
1904 struct smb_request *req,
1905 char **pparams, int total_params,
1906 char **ppdata, int total_data,
1907 unsigned int max_data_bytes)
1909 /* We must be careful here that we don't return more than the
1910 allowed number of data bytes. If this means returning fewer than
1911 maxentries then so be it. We assume that the redirector has
1912 enough room for the fixed number of parameter bytes it has
1914 struct smb_filename *smb_dname = NULL;
1915 char *params = *pparams;
1916 char *pdata = *ppdata;
1920 uint16 findfirst_flags;
1921 bool close_after_first;
1923 bool requires_resume_key;
1925 char *directory = NULL;
1928 int last_entry_off=0;
1932 bool finished = False;
1933 bool dont_descend = False;
1934 bool out_of_space = False;
1935 int space_remaining;
1936 bool mask_contains_wcard = False;
1937 struct ea_list *ea_list = NULL;
1938 NTSTATUS ntstatus = NT_STATUS_OK;
1939 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1940 TALLOC_CTX *ctx = talloc_tos();
1942 if (total_params < 13) {
1943 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1947 dirtype = SVAL(params,0);
1948 maxentries = SVAL(params,2);
1949 findfirst_flags = SVAL(params,4);
1950 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1951 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1952 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1953 info_level = SVAL(params,6);
1955 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1956 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1957 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1958 info_level, max_data_bytes));
1961 /* W2K3 seems to treat zero as 1. */
1965 switch (info_level) {
1966 case SMB_FIND_INFO_STANDARD:
1967 case SMB_FIND_EA_SIZE:
1968 case SMB_FIND_EA_LIST:
1969 case SMB_FIND_FILE_DIRECTORY_INFO:
1970 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1971 case SMB_FIND_FILE_NAMES_INFO:
1972 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1973 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1974 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1976 case SMB_FIND_FILE_UNIX:
1977 case SMB_FIND_FILE_UNIX_INFO2:
1978 /* Always use filesystem for UNIX mtime query. */
1979 ask_sharemode = false;
1980 if (!lp_unix_extensions()) {
1981 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1986 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1990 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1991 params+12, total_params - 12,
1992 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1993 if (!NT_STATUS_IS_OK(ntstatus)) {
1994 reply_nterror(req, ntstatus);
1998 ntstatus = resolve_dfspath_wcard(ctx, conn,
1999 req->flags2 & FLAGS2_DFS_PATHNAMES,
2002 &mask_contains_wcard);
2003 if (!NT_STATUS_IS_OK(ntstatus)) {
2004 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2005 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2006 ERRSRV, ERRbadpath);
2009 reply_nterror(req, ntstatus);
2013 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2014 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2015 if (!NT_STATUS_IS_OK(ntstatus)) {
2016 reply_nterror(req, ntstatus);
2020 mask = smb_dname->original_lcomp;
2022 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2023 TALLOC_FREE(smb_dname);
2024 if (!NT_STATUS_IS_OK(ntstatus)) {
2025 reply_nterror(req, ntstatus);
2029 ntstatus = check_name(conn, directory);
2030 if (!NT_STATUS_IS_OK(ntstatus)) {
2031 reply_nterror(req, ntstatus);
2035 p = strrchr_m(directory,'/');
2037 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2038 if((directory[0] == '.') && (directory[1] == '\0')) {
2039 mask = talloc_strdup(ctx,"*");
2041 reply_nterror(req, NT_STATUS_NO_MEMORY);
2044 mask_contains_wcard = True;
2046 directory = talloc_strdup(talloc_tos(), "./");
2048 reply_nterror(req, NT_STATUS_NO_MEMORY);
2055 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2057 if (info_level == SMB_FIND_EA_LIST) {
2060 if (total_data < 4) {
2061 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2065 ea_size = IVAL(pdata,0);
2066 if (ea_size != total_data) {
2067 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2068 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2073 if (!lp_ea_support(SNUM(conn))) {
2074 reply_doserror(req, ERRDOS, ERReasnotsupported);
2078 /* Pull out the list of names. */
2079 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2086 *ppdata = (char *)SMB_REALLOC(
2087 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2088 if(*ppdata == NULL ) {
2089 reply_nterror(req, NT_STATUS_NO_MEMORY);
2093 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2095 /* Realloc the params space */
2096 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2097 if (*pparams == NULL) {
2098 reply_nterror(req, NT_STATUS_NO_MEMORY);
2103 /* Save the wildcard match and attribs we are using on this directory -
2104 needed as lanman2 assumes these are being saved between calls */
2106 ntstatus = dptr_create(conn,
2112 mask_contains_wcard,
2116 if (!NT_STATUS_IS_OK(ntstatus)) {
2117 reply_nterror(req, ntstatus);
2121 dptr_num = dptr_dnum(conn->dirptr);
2122 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2124 /* Initialize per TRANS2_FIND_FIRST operation data */
2125 dptr_init_search_op(conn->dirptr);
2127 /* We don't need to check for VOL here as this is returned by
2128 a different TRANS2 call. */
2130 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2131 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2132 dont_descend = True;
2135 space_remaining = max_data_bytes;
2136 out_of_space = False;
2138 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2139 bool got_exact_match = False;
2141 /* this is a heuristic to avoid seeking the dirptr except when
2142 absolutely necessary. It allows for a filename of about 40 chars */
2143 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2144 out_of_space = True;
2147 finished = !get_lanman2_dir_entry(ctx,
2150 mask,dirtype,info_level,
2151 requires_resume_key,dont_descend,
2154 space_remaining, &out_of_space,
2156 &last_entry_off, ea_list);
2159 if (finished && out_of_space)
2162 if (!finished && !out_of_space)
2166 * As an optimisation if we know we aren't looking
2167 * for a wildcard name (ie. the name matches the wildcard exactly)
2168 * then we can finish on any (first) match.
2169 * This speeds up large directory searches. JRA.
2175 /* Ensure space_remaining never goes -ve. */
2176 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2177 space_remaining = 0;
2178 out_of_space = true;
2180 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2184 /* Check if we can close the dirptr */
2185 if(close_after_first || (finished && close_if_end)) {
2186 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2187 dptr_close(&dptr_num);
2191 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2192 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2193 * the protocol level is less than NT1. Tested with smbclient. JRA.
2194 * This should fix the OS/2 client bug #2335.
2197 if(numentries == 0) {
2198 dptr_close(&dptr_num);
2199 if (Protocol < PROTOCOL_NT1) {
2200 reply_doserror(req, ERRDOS, ERRnofiles);
2203 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2204 ERRDOS, ERRbadfile);
2209 /* At this point pdata points to numentries directory entries. */
2211 /* Set up the return parameter block */
2212 SSVAL(params,0,dptr_num);
2213 SSVAL(params,2,numentries);
2214 SSVAL(params,4,finished);
2215 SSVAL(params,6,0); /* Never an EA error */
2216 SSVAL(params,8,last_entry_off);
2218 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2221 if ((! *directory) && dptr_path(dptr_num)) {
2222 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2224 reply_nterror(req, NT_STATUS_NO_MEMORY);
2228 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2229 smb_fn_name(req->cmd),
2230 mask, directory, dirtype, numentries ) );
2233 * Force a name mangle here to ensure that the
2234 * mask as an 8.3 name is top of the mangled cache.
2235 * The reasons for this are subtle. Don't remove
2236 * this code unless you know what you are doing
2237 * (see PR#13758). JRA.
2240 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2241 char mangled_name[13];
2242 name_to_8_3(mask, mangled_name, True, conn->params);
2248 /****************************************************************************
2249 Reply to a TRANS2_FINDNEXT.
2250 ****************************************************************************/
2252 static void call_trans2findnext(connection_struct *conn,
2253 struct smb_request *req,
2254 char **pparams, int total_params,
2255 char **ppdata, int total_data,
2256 unsigned int max_data_bytes)
2258 /* We must be careful here that we don't return more than the
2259 allowed number of data bytes. If this means returning fewer than
2260 maxentries then so be it. We assume that the redirector has
2261 enough room for the fixed number of parameter bytes it has
2263 char *params = *pparams;
2264 char *pdata = *ppdata;
2270 uint16 findnext_flags;
2271 bool close_after_request;
2273 bool requires_resume_key;
2275 bool mask_contains_wcard = False;
2276 char *resume_name = NULL;
2277 const char *mask = NULL;
2278 const char *directory = NULL;
2282 int i, last_entry_off=0;
2283 bool finished = False;
2284 bool dont_descend = False;
2285 bool out_of_space = False;
2286 int space_remaining;
2287 struct ea_list *ea_list = NULL;
2288 NTSTATUS ntstatus = NT_STATUS_OK;
2289 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2290 TALLOC_CTX *ctx = talloc_tos();
2292 if (total_params < 13) {
2293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2297 dptr_num = SVAL(params,0);
2298 maxentries = SVAL(params,2);
2299 info_level = SVAL(params,4);
2300 resume_key = IVAL(params,6);
2301 findnext_flags = SVAL(params,10);
2302 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2303 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2304 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2305 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2307 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2309 total_params - 12, STR_TERMINATE, &ntstatus,
2310 &mask_contains_wcard);
2311 if (!NT_STATUS_IS_OK(ntstatus)) {
2312 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2313 complain (it thinks we're asking for the directory above the shared
2314 path or an invalid name). Catch this as the resume name is only compared, never used in
2315 a file access. JRA. */
2316 srvstr_pull_talloc(ctx, params, req->flags2,
2317 &resume_name, params+12,
2321 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2322 reply_nterror(req, ntstatus);
2327 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2328 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2329 resume_key = %d resume name = %s continue=%d level = %d\n",
2330 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2331 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2334 /* W2K3 seems to treat zero as 1. */
2338 switch (info_level) {
2339 case SMB_FIND_INFO_STANDARD:
2340 case SMB_FIND_EA_SIZE:
2341 case SMB_FIND_EA_LIST:
2342 case SMB_FIND_FILE_DIRECTORY_INFO:
2343 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2344 case SMB_FIND_FILE_NAMES_INFO:
2345 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2346 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2347 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2349 case SMB_FIND_FILE_UNIX:
2350 case SMB_FIND_FILE_UNIX_INFO2:
2351 /* Always use filesystem for UNIX mtime query. */
2352 ask_sharemode = false;
2353 if (!lp_unix_extensions()) {
2354 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2359 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2363 if (info_level == SMB_FIND_EA_LIST) {
2366 if (total_data < 4) {
2367 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2371 ea_size = IVAL(pdata,0);
2372 if (ea_size != total_data) {
2373 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2374 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2375 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2379 if (!lp_ea_support(SNUM(conn))) {
2380 reply_doserror(req, ERRDOS, ERReasnotsupported);
2384 /* Pull out the list of names. */
2385 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2387 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2392 *ppdata = (char *)SMB_REALLOC(
2393 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2394 if(*ppdata == NULL) {
2395 reply_nterror(req, NT_STATUS_NO_MEMORY);
2400 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2402 /* Realloc the params space */
2403 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2404 if(*pparams == NULL ) {
2405 reply_nterror(req, NT_STATUS_NO_MEMORY);
2411 /* Check that the dptr is valid */
2412 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2413 reply_doserror(req, ERRDOS, ERRnofiles);
2417 string_set(&conn->dirpath,dptr_path(dptr_num));
2419 /* Get the wildcard mask from the dptr */
2420 if((p = dptr_wcard(dptr_num))== NULL) {
2421 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2422 reply_doserror(req, ERRDOS, ERRnofiles);
2427 directory = conn->dirpath;
2429 /* Get the attr mask from the dptr */
2430 dirtype = dptr_attr(dptr_num);
2432 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2433 dptr_num, mask, dirtype,
2435 dptr_TellDir(conn->dirptr)));
2437 /* Initialize per TRANS2_FIND_NEXT operation data */
2438 dptr_init_search_op(conn->dirptr);
2440 /* We don't need to check for VOL here as this is returned by
2441 a different TRANS2 call. */
2443 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2444 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2445 dont_descend = True;
2448 space_remaining = max_data_bytes;
2449 out_of_space = False;
2452 * Seek to the correct position. We no longer use the resume key but
2453 * depend on the last file name instead.
2456 if(*resume_name && !continue_bit) {
2459 long current_pos = 0;
2461 * Remember, name_to_8_3 is called by
2462 * get_lanman2_dir_entry(), so the resume name
2463 * could be mangled. Ensure we check the unmangled name.
2466 if (mangle_is_mangled(resume_name, conn->params)) {
2467 char *new_resume_name = NULL;
2468 mangle_lookup_name_from_8_3(ctx,
2472 if (new_resume_name) {
2473 resume_name = new_resume_name;
2478 * Fix for NT redirector problem triggered by resume key indexes
2479 * changing between directory scans. We now return a resume key of 0
2480 * and instead look for the filename to continue from (also given
2481 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2482 * findfirst/findnext (as is usual) then the directory pointer
2483 * should already be at the correct place.
2486 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2487 } /* end if resume_name && !continue_bit */
2489 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2490 bool got_exact_match = False;
2492 /* this is a heuristic to avoid seeking the dirptr except when
2493 absolutely necessary. It allows for a filename of about 40 chars */
2494 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2495 out_of_space = True;
2498 finished = !get_lanman2_dir_entry(ctx,
2501 mask,dirtype,info_level,
2502 requires_resume_key,dont_descend,
2505 space_remaining, &out_of_space,
2507 &last_entry_off, ea_list);
2510 if (finished && out_of_space)
2513 if (!finished && !out_of_space)
2517 * As an optimisation if we know we aren't looking
2518 * for a wildcard name (ie. the name matches the wildcard exactly)
2519 * then we can finish on any (first) match.
2520 * This speeds up large directory searches. JRA.
2526 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2529 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2530 smb_fn_name(req->cmd),
2531 mask, directory, dirtype, numentries ) );
2533 /* Check if we can close the dirptr */
2534 if(close_after_request || (finished && close_if_end)) {
2535 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2536 dptr_close(&dptr_num); /* This frees up the saved mask */
2539 /* Set up the return parameter block */
2540 SSVAL(params,0,numentries);
2541 SSVAL(params,2,finished);
2542 SSVAL(params,4,0); /* Never an EA error */
2543 SSVAL(params,6,last_entry_off);
2545 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2551 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2553 E_md4hash(lp_servicename(SNUM(conn)),objid);
2557 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2559 SMB_ASSERT(extended_info != NULL);
2561 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2562 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2563 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2564 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2565 #ifdef SAMBA_VERSION_REVISION
2566 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2568 extended_info->samba_subversion = 0;
2569 #ifdef SAMBA_VERSION_RC_RELEASE
2570 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2572 #ifdef SAMBA_VERSION_PRE_RELEASE
2573 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2576 #ifdef SAMBA_VERSION_VENDOR_PATCH
2577 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2579 extended_info->samba_gitcommitdate = 0;
2580 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2581 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2584 memset(extended_info->samba_version_string, 0,
2585 sizeof(extended_info->samba_version_string));
2587 snprintf (extended_info->samba_version_string,
2588 sizeof(extended_info->samba_version_string),
2589 "%s", samba_version_string());
2592 /****************************************************************************
2593 Reply to a TRANS2_QFSINFO (query filesystem info).
2594 ****************************************************************************/
2596 static void call_trans2qfsinfo(connection_struct *conn,
2597 struct smb_request *req,
2598 char **pparams, int total_params,
2599 char **ppdata, int total_data,
2600 unsigned int max_data_bytes)
2602 char *pdata, *end_data;
2603 char *params = *pparams;
2607 const char *vname = volume_label(SNUM(conn));
2608 int snum = SNUM(conn);
2609 char *fstype = lp_fstype(SNUM(conn));
2610 uint32 additional_flags = 0;
2612 if (total_params < 2) {
2613 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2617 info_level = SVAL(params,0);
2620 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2621 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2622 "info level (0x%x) on IPC$.\n",
2623 (unsigned int)info_level));
2624 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2629 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2630 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2631 DEBUG(0,("call_trans2qfsinfo: encryption required "
2632 "and info level 0x%x sent.\n",
2633 (unsigned int)info_level));
2634 exit_server_cleanly("encryption required "
2640 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2642 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
2643 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2644 reply_doserror(req, ERRSRV, ERRinvdevice);
2648 *ppdata = (char *)SMB_REALLOC(
2649 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2650 if (*ppdata == NULL ) {
2651 reply_nterror(req, NT_STATUS_NO_MEMORY);
2656 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2657 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2659 switch (info_level) {
2660 case SMB_INFO_ALLOCATION:
2662 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2664 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2665 reply_unixerror(req, ERRHRD, ERRgeneral);
2669 block_size = lp_block_size(snum);
2670 if (bsize < block_size) {
2671 uint64_t factor = block_size/bsize;
2676 if (bsize > block_size) {
2677 uint64_t factor = bsize/block_size;
2682 bytes_per_sector = 512;
2683 sectors_per_unit = bsize/bytes_per_sector;
2685 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2686 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2687 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2689 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2690 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2691 SIVAL(pdata,l1_cUnit,dsize);
2692 SIVAL(pdata,l1_cUnitAvail,dfree);
2693 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2697 case SMB_INFO_VOLUME:
2698 /* Return volume name */
2700 * Add volume serial number - hash of a combination of
2701 * the called hostname and the service name.
2703 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2705 * Win2k3 and previous mess this up by sending a name length
2706 * one byte short. I believe only older clients (OS/2 Win9x) use
2707 * this call so try fixing this by adding a terminating null to
2708 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2712 pdata+l2_vol_szVolLabel, vname,
2713 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2714 STR_NOALIGN|STR_TERMINATE);
2715 SCVAL(pdata,l2_vol_cch,len);
2716 data_len = l2_vol_szVolLabel + len;
2717 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2718 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2722 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2723 case SMB_FS_ATTRIBUTE_INFORMATION:
2725 additional_flags = 0;
2726 #if defined(HAVE_SYS_QUOTAS)
2727 additional_flags |= FILE_VOLUME_QUOTAS;
2730 if(lp_nt_acl_support(SNUM(conn))) {
2731 additional_flags |= FILE_PERSISTENT_ACLS;
2734 /* Capabilities are filled in at connection time through STATVFS call */
2735 additional_flags |= conn->fs_capabilities;
2737 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2738 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2739 additional_flags); /* FS ATTRIBUTES */
2741 SIVAL(pdata,4,255); /* Max filename component length */
2742 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2743 and will think we can't do long filenames */
2744 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2745 PTR_DIFF(end_data, pdata+12),
2748 data_len = 12 + len;
2751 case SMB_QUERY_FS_LABEL_INFO:
2752 case SMB_FS_LABEL_INFORMATION:
2753 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2754 PTR_DIFF(end_data, pdata+4), 0);
2759 case SMB_QUERY_FS_VOLUME_INFO:
2760 case SMB_FS_VOLUME_INFORMATION:
2763 * Add volume serial number - hash of a combination of
2764 * the called hostname and the service name.
2766 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2767 (str_checksum(get_local_machine_name())<<16));
2769 /* Max label len is 32 characters. */
2770 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2771 PTR_DIFF(end_data, pdata+18),
2773 SIVAL(pdata,12,len);
2776 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2777 (int)strlen(vname),vname, lp_servicename(snum)));
2780 case SMB_QUERY_FS_SIZE_INFO:
2781 case SMB_FS_SIZE_INFORMATION:
2783 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2785 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2786 reply_unixerror(req, ERRHRD, ERRgeneral);
2789 block_size = lp_block_size(snum);
2790 if (bsize < block_size) {
2791 uint64_t factor = block_size/bsize;
2796 if (bsize > block_size) {
2797 uint64_t factor = bsize/block_size;
2802 bytes_per_sector = 512;
2803 sectors_per_unit = bsize/bytes_per_sector;
2804 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2805 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2806 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2807 SBIG_UINT(pdata,0,dsize);
2808 SBIG_UINT(pdata,8,dfree);
2809 SIVAL(pdata,16,sectors_per_unit);
2810 SIVAL(pdata,20,bytes_per_sector);
2814 case SMB_FS_FULL_SIZE_INFORMATION:
2816 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2818 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2819 reply_unixerror(req, ERRHRD, ERRgeneral);
2822 block_size = lp_block_size(snum);
2823 if (bsize < block_size) {
2824 uint64_t factor = block_size/bsize;
2829 if (bsize > block_size) {
2830 uint64_t factor = bsize/block_size;
2835 bytes_per_sector = 512;
2836 sectors_per_unit = bsize/bytes_per_sector;
2837 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2838 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2839 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2840 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2841 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2842 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2843 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2844 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2848 case SMB_QUERY_FS_DEVICE_INFO:
2849 case SMB_FS_DEVICE_INFORMATION:
2851 SIVAL(pdata,0,0); /* dev type */
2852 SIVAL(pdata,4,0); /* characteristics */
2855 #ifdef HAVE_SYS_QUOTAS
2856 case SMB_FS_QUOTA_INFORMATION:
2858 * what we have to send --metze:
2860 * Unknown1: 24 NULL bytes
2861 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2862 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2863 * Quota Flags: 2 byte :
2864 * Unknown3: 6 NULL bytes
2868 * details for Quota Flags:
2870 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2871 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2872 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2873 * 0x0001 Enable Quotas: enable quota for this fs
2877 /* we need to fake up a fsp here,
2878 * because its not send in this call
2881 SMB_NTQUOTA_STRUCT quotas;
2884 ZERO_STRUCT(quotas);
2890 if (conn->server_info->utok.uid != 0) {
2891 DEBUG(0,("set_user_quota: access_denied "
2892 "service [%s] user [%s]\n",
2893 lp_servicename(SNUM(conn)),
2894 conn->server_info->unix_name));
2895 reply_doserror(req, ERRDOS, ERRnoaccess);
2899 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2900 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2901 reply_doserror(req, ERRSRV, ERRerror);
2907 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2909 /* Unknown1 24 NULL bytes*/
2910 SBIG_UINT(pdata,0,(uint64_t)0);
2911 SBIG_UINT(pdata,8,(uint64_t)0);
2912 SBIG_UINT(pdata,16,(uint64_t)0);
2914 /* Default Soft Quota 8 bytes */
2915 SBIG_UINT(pdata,24,quotas.softlim);
2917 /* Default Hard Quota 8 bytes */
2918 SBIG_UINT(pdata,32,quotas.hardlim);
2920 /* Quota flag 2 bytes */
2921 SSVAL(pdata,40,quotas.qflags);
2923 /* Unknown3 6 NULL bytes */
2929 #endif /* HAVE_SYS_QUOTAS */
2930 case SMB_FS_OBJECTID_INFORMATION:
2932 unsigned char objid[16];
2933 struct smb_extended_info extended_info;
2934 memcpy(pdata,create_volume_objectid(conn, objid),16);
2935 samba_extended_info_version (&extended_info);
2936 SIVAL(pdata,16,extended_info.samba_magic);
2937 SIVAL(pdata,20,extended_info.samba_version);
2938 SIVAL(pdata,24,extended_info.samba_subversion);
2939 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2940 memcpy(pdata+36,extended_info.samba_version_string,28);
2946 * Query the version and capabilities of the CIFS UNIX extensions
2950 case SMB_QUERY_CIFS_UNIX_INFO:
2952 bool large_write = lp_min_receive_file_size() &&
2953 !srv_is_signing_active(smbd_server_conn);
2954 bool large_read = !srv_is_signing_active(smbd_server_conn);
2955 int encrypt_caps = 0;
2957 if (!lp_unix_extensions()) {
2958 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2962 switch (conn->encrypt_level) {
2968 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2971 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2972 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2973 large_write = false;
2979 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2980 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2982 /* We have POSIX ACLs, pathname, encryption,
2983 * large read/write, and locking capability. */
2985 SBIG_UINT(pdata,4,((uint64_t)(
2986 CIFS_UNIX_POSIX_ACLS_CAP|
2987 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2988 CIFS_UNIX_FCNTL_LOCKS_CAP|
2989 CIFS_UNIX_EXTATTR_CAP|
2990 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2992 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2994 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2998 case SMB_QUERY_POSIX_FS_INFO:
3001 vfs_statvfs_struct svfs;
3003 if (!lp_unix_extensions()) {
3004 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3008 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3012 SIVAL(pdata,0,svfs.OptimalTransferSize);
3013 SIVAL(pdata,4,svfs.BlockSize);
3014 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3015 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3016 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3017 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3018 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3019 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3020 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3022 } else if (rc == EOPNOTSUPP) {
3023 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3025 #endif /* EOPNOTSUPP */
3027 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3028 reply_doserror(req, ERRSRV, ERRerror);
3034 case SMB_QUERY_POSIX_WHOAMI:
3040 if (!lp_unix_extensions()) {
3041 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3045 if (max_data_bytes < 40) {
3046 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3050 /* We ARE guest if global_sid_Builtin_Guests is
3051 * in our list of SIDs.
3053 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3054 conn->server_info->ptok)) {
3055 flags |= SMB_WHOAMI_GUEST;
3058 /* We are NOT guest if global_sid_Authenticated_Users
3059 * is in our list of SIDs.
3061 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3062 conn->server_info->ptok)) {
3063 flags &= ~SMB_WHOAMI_GUEST;
3066 /* NOTE: 8 bytes for UID/GID, irrespective of native
3067 * platform size. This matches
3068 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3070 data_len = 4 /* flags */
3077 + 4 /* pad/reserved */
3078 + (conn->server_info->utok.ngroups * 8)
3080 + (conn->server_info->ptok->num_sids *
3084 SIVAL(pdata, 0, flags);
3085 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3087 (uint64_t)conn->server_info->utok.uid);
3088 SBIG_UINT(pdata, 16,
3089 (uint64_t)conn->server_info->utok.gid);
3092 if (data_len >= max_data_bytes) {
3093 /* Potential overflow, skip the GIDs and SIDs. */
3095 SIVAL(pdata, 24, 0); /* num_groups */
3096 SIVAL(pdata, 28, 0); /* num_sids */
3097 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3098 SIVAL(pdata, 36, 0); /* reserved */
3104 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3105 SIVAL(pdata, 28, conn->server_info->num_sids);
3107 /* We walk the SID list twice, but this call is fairly
3108 * infrequent, and I don't expect that it's performance
3109 * sensitive -- jpeach
3111 for (i = 0, sid_bytes = 0;
3112 i < conn->server_info->ptok->num_sids; ++i) {
3113 sid_bytes += ndr_size_dom_sid(
3114 &conn->server_info->ptok->user_sids[i],
3119 /* SID list byte count */
3120 SIVAL(pdata, 32, sid_bytes);
3122 /* 4 bytes pad/reserved - must be zero */
3123 SIVAL(pdata, 36, 0);
3127 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3128 SBIG_UINT(pdata, data_len,
3129 (uint64_t)conn->server_info->utok.groups[i]);
3135 i < conn->server_info->ptok->num_sids; ++i) {
3136 int sid_len = ndr_size_dom_sid(
3137 &conn->server_info->ptok->user_sids[i],
3141 sid_linearize(pdata + data_len, sid_len,
3142 &conn->server_info->ptok->user_sids[i]);
3143 data_len += sid_len;
3149 case SMB_MAC_QUERY_FS_INFO:
3151 * Thursby MAC extension... ONLY on NTFS filesystems
3152 * once we do streams then we don't need this
3154 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3156 SIVAL(pdata,84,0x100); /* Don't support mac... */
3161 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3166 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3169 DEBUG( 4, ( "%s info_level = %d\n",
3170 smb_fn_name(req->cmd), info_level) );
3175 /****************************************************************************
3176 Reply to a TRANS2_SETFSINFO (set filesystem info).
3177 ****************************************************************************/
3179 static void call_trans2setfsinfo(connection_struct *conn,
3180 struct smb_request *req,
3181 char **pparams, int total_params,
3182 char **ppdata, int total_data,
3183 unsigned int max_data_bytes)
3185 char *pdata = *ppdata;
3186 char *params = *pparams;
3189 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3192 if (total_params < 4) {
3193 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3199 info_level = SVAL(params,2);
3202 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3203 info_level != SMB_SET_CIFS_UNIX_INFO) {
3204 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3205 "info level (0x%x) on IPC$.\n",
3206 (unsigned int)info_level));
3207 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3212 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3213 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3214 DEBUG(0,("call_trans2setfsinfo: encryption required "
3215 "and info level 0x%x sent.\n",
3216 (unsigned int)info_level));
3217 exit_server_cleanly("encryption required "
3223 switch(info_level) {
3224 case SMB_SET_CIFS_UNIX_INFO:
3226 uint16 client_unix_major;
3227 uint16 client_unix_minor;
3228 uint32 client_unix_cap_low;
3229 uint32 client_unix_cap_high;
3231 if (!lp_unix_extensions()) {
3233 NT_STATUS_INVALID_LEVEL);
3237 /* There should be 12 bytes of capabilities set. */
3238 if (total_data < 8) {
3241 NT_STATUS_INVALID_PARAMETER);
3244 client_unix_major = SVAL(pdata,0);
3245 client_unix_minor = SVAL(pdata,2);
3246 client_unix_cap_low = IVAL(pdata,4);
3247 client_unix_cap_high = IVAL(pdata,8);
3248 /* Just print these values for now. */
3249 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3250 cap_low = 0x%x, cap_high = 0x%x\n",
3251 (unsigned int)client_unix_major,
3252 (unsigned int)client_unix_minor,
3253 (unsigned int)client_unix_cap_low,
3254 (unsigned int)client_unix_cap_high ));
3256 /* Here is where we must switch to posix pathname processing... */
3257 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3258 lp_set_posix_pathnames();
3259 mangle_change_to_posix();
3262 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3263 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3264 /* Client that knows how to do posix locks,
3265 * but not posix open/mkdir operations. Set a
3266 * default type for read/write checks. */
3268 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3274 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3277 size_t param_len = 0;
3278 size_t data_len = total_data;
3280 if (!lp_unix_extensions()) {
3283 NT_STATUS_INVALID_LEVEL);
3287 if (lp_smb_encrypt(SNUM(conn)) == false) {
3290 NT_STATUS_NOT_SUPPORTED);
3294 DEBUG( 4,("call_trans2setfsinfo: "
3295 "request transport encryption.\n"));
3297 status = srv_request_encryption_setup(conn,
3298 (unsigned char **)ppdata,
3300 (unsigned char **)pparams,
3303 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3304 !NT_STATUS_IS_OK(status)) {
3305 reply_nterror(req, status);
3309 send_trans2_replies(conn, req,
3316 if (NT_STATUS_IS_OK(status)) {
3317 /* Server-side transport
3318 * encryption is now *on*. */
3319 status = srv_encryption_start(conn);
3320 if (!NT_STATUS_IS_OK(status)) {
3321 exit_server_cleanly(
3322 "Failure in setting "
3323 "up encrypted transport");
3329 case SMB_FS_QUOTA_INFORMATION:
3331 files_struct *fsp = NULL;
3332 SMB_NTQUOTA_STRUCT quotas;
3334 ZERO_STRUCT(quotas);
3337 if ((conn->server_info->utok.uid != 0)
3338 ||!CAN_WRITE(conn)) {
3339 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3340 lp_servicename(SNUM(conn)),
3341 conn->server_info->unix_name));
3342 reply_doserror(req, ERRSRV, ERRaccess);
3346 /* note: normaly there're 48 bytes,
3347 * but we didn't use the last 6 bytes for now
3350 fsp = file_fsp(req, SVAL(params,0));
3352 if (!check_fsp_ntquota_handle(conn, req,
3354 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3356 req, NT_STATUS_INVALID_HANDLE);
3360 if (total_data < 42) {
3361 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3365 NT_STATUS_INVALID_PARAMETER);
3369 /* unknown_1 24 NULL bytes in pdata*/
3371 /* the soft quotas 8 bytes (uint64_t)*/
3372 quotas.softlim = (uint64_t)IVAL(pdata,24);
3373 #ifdef LARGE_SMB_OFF_T
3374 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3375 #else /* LARGE_SMB_OFF_T */
3376 if ((IVAL(pdata,28) != 0)&&
3377 ((quotas.softlim != 0xFFFFFFFF)||
3378 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3379 /* more than 32 bits? */
3382 NT_STATUS_INVALID_PARAMETER);
3385 #endif /* LARGE_SMB_OFF_T */
3387 /* the hard quotas 8 bytes (uint64_t)*/
3388 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3389 #ifdef LARGE_SMB_OFF_T
3390 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3391 #else /* LARGE_SMB_OFF_T */
3392 if ((IVAL(pdata,36) != 0)&&
3393 ((quotas.hardlim != 0xFFFFFFFF)||
3394 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3395 /* more than 32 bits? */
3398 NT_STATUS_INVALID_PARAMETER);
3401 #endif /* LARGE_SMB_OFF_T */
3403 /* quota_flags 2 bytes **/
3404 quotas.qflags = SVAL(pdata,40);
3406 /* unknown_2 6 NULL bytes follow*/
3408 /* now set the quotas */
3409 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3410 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3411 reply_doserror(req, ERRSRV, ERRerror);
3418 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3420 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3426 * sending this reply works fine,
3427 * but I'm not sure it's the same
3428 * like windows do...
3431 reply_outbuf(req, 10, 0);
3434 #if defined(HAVE_POSIX_ACLS)
3435 /****************************************************************************
3436 Utility function to count the number of entries in a POSIX acl.
3437 ****************************************************************************/
3439 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3441 unsigned int ace_count = 0;
3442 int entry_id = SMB_ACL_FIRST_ENTRY;
3443 SMB_ACL_ENTRY_T entry;
3445 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3447 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3448 entry_id = SMB_ACL_NEXT_ENTRY;
3455 /****************************************************************************
3456 Utility function to marshall a POSIX acl into wire format.
3457 ****************************************************************************/
3459 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3461 int entry_id = SMB_ACL_FIRST_ENTRY;
3462 SMB_ACL_ENTRY_T entry;
3464 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3465 SMB_ACL_TAG_T tagtype;
3466 SMB_ACL_PERMSET_T permset;
3467 unsigned char perms = 0;
3468 unsigned int own_grp;
3471 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3472 entry_id = SMB_ACL_NEXT_ENTRY;
3475 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3476 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3480 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3481 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3485 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3486 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3487 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3489 SCVAL(pdata,1,perms);
3492 case SMB_ACL_USER_OBJ:
3493 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3494 own_grp = (unsigned int)pst->st_ex_uid;
3495 SIVAL(pdata,2,own_grp);
3500 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3502 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3505 own_grp = (unsigned int)*puid;
3506 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3507 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3508 SIVAL(pdata,2,own_grp);
3512 case SMB_ACL_GROUP_OBJ:
3513 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3514 own_grp = (unsigned int)pst->st_ex_gid;
3515 SIVAL(pdata,2,own_grp);
3520 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3522 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3525 own_grp = (unsigned int)*pgid;
3526 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3527 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3528 SIVAL(pdata,2,own_grp);
3533 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3534 SIVAL(pdata,2,0xFFFFFFFF);
3535 SIVAL(pdata,6,0xFFFFFFFF);
3538 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3539 SIVAL(pdata,2,0xFFFFFFFF);
3540 SIVAL(pdata,6,0xFFFFFFFF);
3543 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3546 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3553 /****************************************************************************
3554 Store the FILE_UNIX_BASIC info.
3555 ****************************************************************************/
3557 static char *store_file_unix_basic(connection_struct *conn,
3560 const SMB_STRUCT_STAT *psbuf)
3562 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3563 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3565 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3568 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3571 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3572 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3573 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3576 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3580 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3584 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3587 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3591 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3595 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3598 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3602 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3609 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3610 * the chflags(2) (or equivalent) flags.
3612 * XXX: this really should be behind the VFS interface. To do this, we would
3613 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3614 * Each VFS module could then implement its own mapping as appropriate for the
3615 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3617 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3621 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3625 { UF_IMMUTABLE, EXT_IMMUTABLE },
3629 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3633 { UF_HIDDEN, EXT_HIDDEN },
3636 /* Do not remove. We need to guarantee that this array has at least one
3637 * entry to build on HP-UX.
3643 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3644 uint32 *smb_fflags, uint32 *smb_fmask)
3648 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3649 *smb_fmask |= info2_flags_map[i].smb_fflag;
3650 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3651 *smb_fflags |= info2_flags_map[i].smb_fflag;
3656 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3657 const uint32 smb_fflags,
3658 const uint32 smb_fmask,
3661 uint32 max_fmask = 0;
3664 *stat_fflags = psbuf->st_ex_flags;
3666 /* For each flags requested in smb_fmask, check the state of the
3667 * corresponding flag in smb_fflags and set or clear the matching
3671 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3672 max_fmask |= info2_flags_map[i].smb_fflag;
3673 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3674 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3675 *stat_fflags |= info2_flags_map[i].stat_fflag;
3677 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3682 /* If smb_fmask is asking to set any bits that are not supported by
3683 * our flag mappings, we should fail.
3685 if ((smb_fmask & max_fmask) != smb_fmask) {
3693 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3694 * of file flags and birth (create) time.
3696 static char *store_file_unix_basic_info2(connection_struct *conn,
3699 const SMB_STRUCT_STAT *psbuf)
3701 uint32 file_flags = 0;
3702 uint32 flags_mask = 0;
3704 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3706 /* Create (birth) time 64 bit */
3707 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3710 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3711 SIVAL(pdata, 0, file_flags); /* flags */
3712 SIVAL(pdata, 4, flags_mask); /* mask */
3718 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3719 const struct stream_struct *streams,
3721 unsigned int max_data_bytes,
3722 unsigned int *data_size)
3725 unsigned int ofs = 0;
3727 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3728 unsigned int next_offset;
3730 smb_ucs2_t *namebuf;
3732 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3733 streams[i].name, &namelen) ||
3736 return NT_STATUS_INVALID_PARAMETER;
3740 * name_buf is now null-terminated, we need to marshall as not
3746 SIVAL(data, ofs+4, namelen);
3747 SOFF_T(data, ofs+8, streams[i].size);
3748 SOFF_T(data, ofs+16, streams[i].alloc_size);
3749 memcpy(data+ofs+24, namebuf, namelen);
3750 TALLOC_FREE(namebuf);
3752 next_offset = ofs + 24 + namelen;
3754 if (i == num_streams-1) {
3755 SIVAL(data, ofs, 0);
3758 unsigned int align = ndr_align_size(next_offset, 8);
3760 memset(data+next_offset, 0, align);
3761 next_offset += align;
3763 SIVAL(data, ofs, next_offset - ofs);
3772 return NT_STATUS_OK;
3775 /****************************************************************************
3776 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3777 ****************************************************************************/
3779 static void call_trans2qpipeinfo(connection_struct *conn,
3780 struct smb_request *req,
3781 unsigned int tran_call,
3782 char **pparams, int total_params,
3783 char **ppdata, int total_data,
3784 unsigned int max_data_bytes)
3786 char *params = *pparams;
3787 char *pdata = *ppdata;
3788 unsigned int data_size = 0;
3789 unsigned int param_size = 2;
3794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3798 if (total_params < 4) {
3799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3803 fsp = file_fsp(req, SVAL(params,0));
3804 if (!fsp_is_np(fsp)) {
3805 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3809 info_level = SVAL(params,2);
3811 *pparams = (char *)SMB_REALLOC(*pparams,2);
3812 if (*pparams == NULL) {
3813 reply_nterror(req, NT_STATUS_NO_MEMORY);
3818 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3819 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3820 if (*ppdata == NULL ) {
3821 reply_nterror(req, NT_STATUS_NO_MEMORY);
3826 switch (info_level) {
3827 case SMB_FILE_STANDARD_INFORMATION:
3829 SOFF_T(pdata,0,4096LL);
3836 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3840 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3846 /****************************************************************************
3847 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3848 file name or file id).
3849 ****************************************************************************/
3851 static void call_trans2qfilepathinfo(connection_struct *conn,
3852 struct smb_request *req,
3853 unsigned int tran_call,
3854 char **pparams, int total_params,
3855 char **ppdata, int total_data,
3856 unsigned int max_data_bytes)
3858 char *params = *pparams;
3859 char *pdata = *ppdata;
3860 char *dstart, *dend;
3864 SMB_OFF_T file_size=0;
3865 uint64_t allocation_size=0;
3866 unsigned int data_size = 0;
3867 unsigned int param_size = 2;
3868 SMB_STRUCT_STAT sbuf;
3869 char *dos_fname = NULL;
3871 struct smb_filename *smb_fname = NULL;
3876 bool delete_pending = False;
3878 time_t create_time, mtime, atime;
3879 struct timespec create_time_ts, mtime_ts, atime_ts;
3880 struct timespec write_time_ts;
3881 files_struct *fsp = NULL;
3882 struct file_id fileid;
3883 struct ea_list *ea_list = NULL;
3884 char *lock_data = NULL;
3885 bool ms_dfs_link = false;
3886 TALLOC_CTX *ctx = talloc_tos();
3887 NTSTATUS status = NT_STATUS_OK;
3890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3894 ZERO_STRUCT(write_time_ts);
3896 if (tran_call == TRANSACT2_QFILEINFO) {
3897 if (total_params < 4) {
3898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3903 call_trans2qpipeinfo(conn, req, tran_call,
3904 pparams, total_params,
3910 fsp = file_fsp(req, SVAL(params,0));
3911 info_level = SVAL(params,2);
3913 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3915 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3916 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3920 /* Initial check for valid fsp ptr. */
3921 if (!check_fsp_open(conn, req, fsp)) {
3925 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3927 reply_nterror(req, NT_STATUS_NO_MEMORY);
3931 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
3933 if (!NT_STATUS_IS_OK(status)) {
3934 reply_nterror(req, status);
3938 if(fsp->fake_file_handle) {
3940 * This is actually for the QUOTA_FAKE_FILE --metze
3943 /* We know this name is ok, it's already passed the checks. */
3945 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3947 * This is actually a QFILEINFO on a directory
3948 * handle (returned from an NT SMB). NT5.0 seems
3949 * to do this call. JRA.
3952 if (INFO_LEVEL_IS_UNIX(info_level)) {
3953 /* Always do lstat for UNIX calls. */
3954 if (SMB_VFS_LSTAT(conn, smb_fname)) {
3955 DEBUG(3,("call_trans2qfilepathinfo: "
3956 "SMB_VFS_LSTAT of %s failed "
3958 smb_fname_str_dbg(smb_fname),
3960 reply_unixerror(req,ERRDOS,ERRbadpath);
3963 } else if (SMB_VFS_STAT(conn, smb_fname)) {
3964 DEBUG(3,("call_trans2qfilepathinfo: "
3965 "SMB_VFS_STAT of %s failed (%s)\n",
3966 smb_fname_str_dbg(smb_fname),
3968 reply_unixerror(req, ERRDOS, ERRbadpath);
3972 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
3973 get_file_infos(fileid, &delete_pending, &write_time_ts);
3976 * Original code - this is an open file.
3978 if (!check_fsp(conn, req, fsp)) {
3982 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
3983 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
3984 fsp->fnum, strerror(errno)));
3985 reply_unixerror(req, ERRDOS, ERRbadfid);
3988 pos = fsp->fh->position_information;
3989 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
3990 get_file_infos(fileid, &delete_pending, &write_time_ts);
3995 if (total_params < 7) {
3996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4000 info_level = SVAL(params,0);
4002 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4004 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4005 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4009 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
4011 STR_TERMINATE, &status);
4012 if (!NT_STATUS_IS_OK(status)) {
4013 reply_nterror(req, status);
4017 status = filename_convert(ctx,
4019 req->flags2 & FLAGS2_DFS_PATHNAMES,
4023 if (!NT_STATUS_IS_OK(status)) {
4024 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4025 reply_botherror(req,
4026 NT_STATUS_PATH_NOT_COVERED,
4027 ERRSRV, ERRbadpath);
4030 reply_nterror(req, status);
4034 /* If this is a stream, check if there is a delete_pending. */
4035 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4036 && is_ntfs_stream_smb_fname(smb_fname)) {
4037 struct smb_filename *smb_fname_base = NULL;
4039 /* Create an smb_filename with stream_name == NULL. */
4041 create_synthetic_smb_fname(talloc_tos(),
4042 smb_fname->base_name,
4045 if (!NT_STATUS_IS_OK(status)) {
4046 reply_nterror(req, status);
4050 if (INFO_LEVEL_IS_UNIX(info_level)) {
4051 /* Always do lstat for UNIX calls. */
4052 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4053 DEBUG(3,("call_trans2qfilepathinfo: "
4054 "SMB_VFS_LSTAT of %s failed "
4056 smb_fname_str_dbg(smb_fname_base),
4058 TALLOC_FREE(smb_fname_base);
4059 reply_unixerror(req,ERRDOS,ERRbadpath);
4063 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4064 DEBUG(3,("call_trans2qfilepathinfo: "
4065 "fileinfo of %s failed "
4067 smb_fname_str_dbg(smb_fname_base),
4069 TALLOC_FREE(smb_fname_base);
4070 reply_unixerror(req,ERRDOS,ERRbadpath);
4075 fileid = vfs_file_id_from_sbuf(conn,
4076 &smb_fname_base->st);
4077 TALLOC_FREE(smb_fname_base);
4078 get_file_infos(fileid, &delete_pending, NULL);
4079 if (delete_pending) {
4080 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4085 if (INFO_LEVEL_IS_UNIX(info_level)) {
4086 /* Always do lstat for UNIX calls. */
4087 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4088 DEBUG(3,("call_trans2qfilepathinfo: "
4089 "SMB_VFS_LSTAT of %s failed (%s)\n",
4090 smb_fname_str_dbg(smb_fname),
4092 reply_unixerror(req, ERRDOS, ERRbadpath);
4096 } else if (!VALID_STAT(smb_fname->st) &&
4097 SMB_VFS_STAT(conn, smb_fname) &&
4098 (info_level != SMB_INFO_IS_NAME_VALID)) {
4099 ms_dfs_link = check_msdfs_link(conn, fname,
4103 DEBUG(3,("call_trans2qfilepathinfo: "
4104 "SMB_VFS_STAT of %s failed (%s)\n",
4105 smb_fname_str_dbg(smb_fname),
4107 reply_unixerror(req, ERRDOS, ERRbadpath);
4112 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4113 get_file_infos(fileid, &delete_pending, &write_time_ts);
4114 if (delete_pending) {
4115 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4120 /* Set sbuf for use below. */
4121 sbuf = smb_fname->st;
4123 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4124 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4128 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4129 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4131 p = strrchr_m(fname,'/');
4138 mode = dos_mode_msdfs(conn,fname,&sbuf);
4140 mode = dos_mode(conn,fname,&sbuf);
4143 mode = FILE_ATTRIBUTE_NORMAL;
4145 nlink = sbuf.st_ex_nlink;
4147 if (nlink && (mode&aDIR)) {
4151 if ((nlink > 0) && delete_pending) {
4155 fullpathname = fname;
4157 file_size = get_file_size_stat(&sbuf);
4159 /* Pull out any data sent here before we realloc. */
4160 switch (info_level) {
4161 case SMB_INFO_QUERY_EAS_FROM_LIST:
4163 /* Pull any EA list from the data portion. */
4166 if (total_data < 4) {
4168 req, NT_STATUS_INVALID_PARAMETER);
4171 ea_size = IVAL(pdata,0);
4173 if (total_data > 0 && ea_size != total_data) {
4174 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4175 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4177 req, NT_STATUS_INVALID_PARAMETER);
4181 if (!lp_ea_support(SNUM(conn))) {
4182 reply_doserror(req, ERRDOS,
4183 ERReasnotsupported);
4187 /* Pull out the list of names. */
4188 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4191 req, NT_STATUS_INVALID_PARAMETER);
4197 case SMB_QUERY_POSIX_LOCK:
4199 if (fsp == NULL || fsp->fh->fd == -1) {
4200 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4204 if (total_data != POSIX_LOCK_DATA_SIZE) {
4206 req, NT_STATUS_INVALID_PARAMETER);
4210 /* Copy the lock range data. */
4211 lock_data = (char *)TALLOC_MEMDUP(
4212 ctx, pdata, total_data);
4214 reply_nterror(req, NT_STATUS_NO_MEMORY);
4222 *pparams = (char *)SMB_REALLOC(*pparams,2);
4223 if (*pparams == NULL) {
4224 reply_nterror(req, NT_STATUS_NO_MEMORY);
4229 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4230 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4231 if (*ppdata == NULL ) {
4232 reply_nterror(req, NT_STATUS_NO_MEMORY);
4237 dend = dstart + data_size - 1;
4239 create_time_ts = sbuf.st_ex_btime;
4240 mtime_ts = sbuf.st_ex_mtime;
4241 atime_ts = sbuf.st_ex_atime;
4243 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4246 /* Do we have this path open ? */
4248 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4249 fsp1 = file_find_di_first(fileid);
4250 if (fsp1 && fsp1->initial_allocation_size) {
4251 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4255 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4256 mtime_ts = write_time_ts;
4259 if (lp_dos_filetime_resolution(SNUM(conn))) {
4260 dos_filetime_timespec(&create_time_ts);
4261 dos_filetime_timespec(&mtime_ts);
4262 dos_filetime_timespec(&atime_ts);
4265 create_time = convert_timespec_to_time_t(create_time_ts);
4266 mtime = convert_timespec_to_time_t(mtime_ts);
4267 atime = convert_timespec_to_time_t(atime_ts);
4269 /* NT expects the name to be in an exact form of the *full*
4270 filename. See the trans2 torture test */
4271 if (ISDOT(base_name)) {
4272 dos_fname = talloc_strdup(ctx, "\\");
4274 reply_nterror(req, NT_STATUS_NO_MEMORY);
4278 dos_fname = talloc_asprintf(ctx,
4282 reply_nterror(req, NT_STATUS_NO_MEMORY);
4285 string_replace(dos_fname, '/', '\\');
4288 switch (info_level) {
4289 case SMB_INFO_STANDARD:
4290 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4292 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4293 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4294 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4295 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4296 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4297 SSVAL(pdata,l1_attrFile,mode);
4300 case SMB_INFO_QUERY_EA_SIZE:
4302 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4303 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4305 srv_put_dos_date2(pdata,0,create_time);
4306 srv_put_dos_date2(pdata,4,atime);
4307 srv_put_dos_date2(pdata,8,mtime); /* write time */
4308 SIVAL(pdata,12,(uint32)file_size);
4309 SIVAL(pdata,16,(uint32)allocation_size);
4310 SSVAL(pdata,20,mode);
4311 SIVAL(pdata,22,ea_size);
4315 case SMB_INFO_IS_NAME_VALID:
4316 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4317 if (tran_call == TRANSACT2_QFILEINFO) {
4318 /* os/2 needs this ? really ?*/
4319 reply_doserror(req, ERRDOS, ERRbadfunc);
4326 case SMB_INFO_QUERY_EAS_FROM_LIST:
4328 size_t total_ea_len = 0;
4329 struct ea_list *ea_file_list = NULL;
4331 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4333 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4334 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4336 if (!ea_list || (total_ea_len > data_size)) {
4338 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4342 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4346 case SMB_INFO_QUERY_ALL_EAS:
4348 /* We have data_size bytes to put EA's into. */
4349 size_t total_ea_len = 0;
4351 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4353 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4354 if (!ea_list || (total_ea_len > data_size)) {
4356 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4360 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4364 case SMB_FILE_BASIC_INFORMATION:
4365 case SMB_QUERY_FILE_BASIC_INFO:
4367 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4368 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4369 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4371 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4375 put_long_date_timespec(pdata,create_time_ts);
4376 put_long_date_timespec(pdata+8,atime_ts);
4377 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4378 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4379 SIVAL(pdata,32,mode);
4381 DEBUG(5,("SMB_QFBI - "));
4382 DEBUG(5,("create: %s ", ctime(&create_time)));
4383 DEBUG(5,("access: %s ", ctime(&atime)));
4384 DEBUG(5,("write: %s ", ctime(&mtime)));
4385 DEBUG(5,("change: %s ", ctime(&mtime)));
4386 DEBUG(5,("mode: %x\n", mode));
4389 case SMB_FILE_STANDARD_INFORMATION:
4390 case SMB_QUERY_FILE_STANDARD_INFO:
4392 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4394 SOFF_T(pdata,0,allocation_size);
4395 SOFF_T(pdata,8,file_size);
4396 SIVAL(pdata,16,nlink);
4397 SCVAL(pdata,20,delete_pending?1:0);
4398 SCVAL(pdata,21,(mode&aDIR)?1:0);
4399 SSVAL(pdata,22,0); /* Padding. */
4402 case SMB_FILE_EA_INFORMATION:
4403 case SMB_QUERY_FILE_EA_INFO:
4405 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4406 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4408 SIVAL(pdata,0,ea_size);
4412 /* Get the 8.3 name - used if NT SMB was negotiated. */
4413 case SMB_QUERY_FILE_ALT_NAME_INFO:
4414 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4416 char mangled_name[13];
4417 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4418 if (!name_to_8_3(base_name,mangled_name,
4419 True,conn->params)) {
4422 NT_STATUS_NO_MEMORY);
4424 len = srvstr_push(dstart, req->flags2,
4425 pdata+4, mangled_name,
4426 PTR_DIFF(dend, pdata+4),
4428 data_size = 4 + len;
4433 case SMB_QUERY_FILE_NAME_INFO:
4435 this must be *exactly* right for ACLs on mapped drives to work
4437 len = srvstr_push(dstart, req->flags2,
4439 PTR_DIFF(dend, pdata+4),
4441 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4442 data_size = 4 + len;
4446 case SMB_FILE_ALLOCATION_INFORMATION:
4447 case SMB_QUERY_FILE_ALLOCATION_INFO:
4448 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4450 SOFF_T(pdata,0,allocation_size);
4453 case SMB_FILE_END_OF_FILE_INFORMATION:
4454 case SMB_QUERY_FILE_END_OF_FILEINFO:
4455 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4457 SOFF_T(pdata,0,file_size);
4460 case SMB_QUERY_FILE_ALL_INFO:
4461 case SMB_FILE_ALL_INFORMATION:
4463 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4464 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4465 put_long_date_timespec(pdata,create_time_ts);
4466 put_long_date_timespec(pdata+8,atime_ts);
4467 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4468 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4469 SIVAL(pdata,32,mode);
4470 SIVAL(pdata,36,0); /* padding. */
4472 SOFF_T(pdata,0,allocation_size);
4473 SOFF_T(pdata,8,file_size);
4474 SIVAL(pdata,16,nlink);
4475 SCVAL(pdata,20,delete_pending);
4476 SCVAL(pdata,21,(mode&aDIR)?1:0);
4479 SIVAL(pdata,0,ea_size);
4480 pdata += 4; /* EA info */
4481 len = srvstr_push(dstart, req->flags2,
4483 PTR_DIFF(dend, pdata+4),
4487 data_size = PTR_DIFF(pdata,(*ppdata));
4490 case SMB_FILE_INTERNAL_INFORMATION:
4491 /* This should be an index number - looks like
4494 I think this causes us to fail the IFSKIT
4495 BasicFileInformationTest. -tpot */
4497 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4498 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4499 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4503 case SMB_FILE_ACCESS_INFORMATION:
4504 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4506 SIVAL(pdata,0,fsp->access_mask);
4508 /* GENERIC_EXECUTE mapping from Windows */
4509 SIVAL(pdata,0,0x12019F);
4514 case SMB_FILE_NAME_INFORMATION:
4515 /* Pathname with leading '\'. */
4518 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4519 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4520 SIVAL(pdata,0,byte_len);
4521 data_size = 4 + byte_len;
4525 case SMB_FILE_DISPOSITION_INFORMATION:
4526 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4528 SCVAL(pdata,0,delete_pending);
4531 case SMB_FILE_POSITION_INFORMATION:
4532 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4534 SOFF_T(pdata,0,pos);
4537 case SMB_FILE_MODE_INFORMATION:
4538 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4539 SIVAL(pdata,0,mode);
4543 case SMB_FILE_ALIGNMENT_INFORMATION:
4544 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4545 SIVAL(pdata,0,0); /* No alignment needed. */
4550 * NT4 server just returns "invalid query" to this - if we try
4551 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4554 /* The first statement above is false - verified using Thursby
4555 * client against NT4 -- gcolley.
4557 case SMB_QUERY_FILE_STREAM_INFO:
4558 case SMB_FILE_STREAM_INFORMATION: {
4559 unsigned int num_streams;
4560 struct stream_struct *streams;
4562 DEBUG(10,("call_trans2qfilepathinfo: "
4563 "SMB_FILE_STREAM_INFORMATION\n"));
4565 status = SMB_VFS_STREAMINFO(
4566 conn, fsp, fname, talloc_tos(),
4567 &num_streams, &streams);
4569 if (!NT_STATUS_IS_OK(status)) {
4570 DEBUG(10, ("could not get stream info: %s\n",
4571 nt_errstr(status)));
4572 reply_nterror(req, status);
4576 status = marshall_stream_info(num_streams, streams,
4577 pdata, max_data_bytes,
4580 if (!NT_STATUS_IS_OK(status)) {
4581 DEBUG(10, ("marshall_stream_info failed: %s\n",
4582 nt_errstr(status)));
4583 reply_nterror(req, status);
4587 TALLOC_FREE(streams);
4591 case SMB_QUERY_COMPRESSION_INFO:
4592 case SMB_FILE_COMPRESSION_INFORMATION:
4593 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4594 SOFF_T(pdata,0,file_size);
4595 SIVAL(pdata,8,0); /* ??? */
4596 SIVAL(pdata,12,0); /* ??? */
4600 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4601 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4602 put_long_date_timespec(pdata,create_time_ts);
4603 put_long_date_timespec(pdata+8,atime_ts);
4604 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4605 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4606 SOFF_T(pdata,32,allocation_size);
4607 SOFF_T(pdata,40,file_size);
4608 SIVAL(pdata,48,mode);
4609 SIVAL(pdata,52,0); /* ??? */
4613 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4614 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4615 SIVAL(pdata,0,mode);
4621 * CIFS UNIX Extensions.
4624 case SMB_QUERY_FILE_UNIX_BASIC:
4626 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4627 data_size = PTR_DIFF(pdata,(*ppdata));
4631 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4633 for (i=0; i<100; i++)
4634 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4640 case SMB_QUERY_FILE_UNIX_INFO2:
4642 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4643 data_size = PTR_DIFF(pdata,(*ppdata));
4647 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4649 for (i=0; i<100; i++)
4650 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4656 case SMB_QUERY_FILE_UNIX_LINK:
4658 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4661 reply_nterror(req, NT_STATUS_NO_MEMORY);
4665 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4667 if(!S_ISLNK(sbuf.st_ex_mode)) {
4668 reply_unixerror(req, ERRSRV,
4673 reply_unixerror(req, ERRDOS, ERRbadlink);
4676 len = SMB_VFS_READLINK(conn,fullpathname,
4679 reply_unixerror(req, ERRDOS,
4684 len = srvstr_push(dstart, req->flags2,
4686 PTR_DIFF(dend, pdata),
4689 data_size = PTR_DIFF(pdata,(*ppdata));
4694 #if defined(HAVE_POSIX_ACLS)
4695 case SMB_QUERY_POSIX_ACL:
4697 SMB_ACL_T file_acl = NULL;
4698 SMB_ACL_T def_acl = NULL;
4699 uint16 num_file_acls = 0;
4700 uint16 num_def_acls = 0;
4702 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4703 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4705 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4708 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4709 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4713 NT_STATUS_NOT_IMPLEMENTED);
4717 if (S_ISDIR(sbuf.st_ex_mode)) {
4718 if (fsp && fsp->is_directory) {
4719 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4721 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4723 def_acl = free_empty_sys_acl(conn, def_acl);
4726 num_file_acls = count_acl_entries(conn, file_acl);
4727 num_def_acls = count_acl_entries(conn, def_acl);
4729 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4730 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4732 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4733 SMB_POSIX_ACL_HEADER_SIZE) ));
4735 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4738 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4742 NT_STATUS_BUFFER_TOO_SMALL);
4746 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4747 SSVAL(pdata,2,num_file_acls);
4748 SSVAL(pdata,4,num_def_acls);
4749 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4751 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4754 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4757 req, NT_STATUS_INTERNAL_ERROR);
4760 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4762 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4765 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4769 NT_STATUS_INTERNAL_ERROR);
4774 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4777 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4779 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4785 case SMB_QUERY_POSIX_LOCK:
4790 enum brl_type lock_type;
4792 if (total_data != POSIX_LOCK_DATA_SIZE) {
4794 req, NT_STATUS_INVALID_PARAMETER);
4798 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4799 case POSIX_LOCK_TYPE_READ:
4800 lock_type = READ_LOCK;
4802 case POSIX_LOCK_TYPE_WRITE:
4803 lock_type = WRITE_LOCK;
4805 case POSIX_LOCK_TYPE_UNLOCK:
4807 /* There's no point in asking for an unlock... */
4810 NT_STATUS_INVALID_PARAMETER);
4814 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4815 #if defined(HAVE_LONGLONG)
4816 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4817 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4818 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4819 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4820 #else /* HAVE_LONGLONG */
4821 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4822 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4823 #endif /* HAVE_LONGLONG */
4825 status = query_lock(fsp,
4832 if (ERROR_WAS_LOCK_DENIED(status)) {
4833 /* Here we need to report who has it locked... */
4834 data_size = POSIX_LOCK_DATA_SIZE;
4836 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4837 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4838 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4839 #if defined(HAVE_LONGLONG)
4840 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4841 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4842 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4843 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4844 #else /* HAVE_LONGLONG */
4845 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4846 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4847 #endif /* HAVE_LONGLONG */
4849 } else if (NT_STATUS_IS_OK(status)) {
4850 /* For success we just return a copy of what we sent
4851 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4852 data_size = POSIX_LOCK_DATA_SIZE;
4853 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4854 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4856 reply_nterror(req, status);
4863 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4867 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4873 /****************************************************************************
4874 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4876 ****************************************************************************/
4878 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4879 connection_struct *conn,
4880 const struct smb_filename *smb_fname_old,
4881 const struct smb_filename *smb_fname_new)
4883 char *oldname = NULL;
4884 char *newname = NULL;
4885 NTSTATUS status = NT_STATUS_OK;
4887 /* source must already exist. */
4888 if (!VALID_STAT(smb_fname_old->st)) {
4889 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4892 /* Disallow if newname already exists. */
4893 if (VALID_STAT(smb_fname_new->st)) {
4894 return NT_STATUS_OBJECT_NAME_COLLISION;
4897 /* No links from a directory. */
4898 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
4899 return NT_STATUS_FILE_IS_A_DIRECTORY;
4902 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
4903 if (!NT_STATUS_IS_OK(status)) {
4906 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
4907 if (!NT_STATUS_IS_OK(status)) {
4911 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4913 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4914 status = map_nt_error_from_unix(errno);
4915 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4916 nt_errstr(status), newname, oldname));
4919 TALLOC_FREE(newname);
4920 TALLOC_FREE(oldname);
4924 /****************************************************************************
4925 Deal with setting the time from any of the setfilepathinfo functions.
4926 ****************************************************************************/
4928 NTSTATUS smb_set_file_time(connection_struct *conn,
4931 const SMB_STRUCT_STAT *psbuf,
4932 struct smb_file_time *ft,
4933 bool setting_write_time)
4936 FILE_NOTIFY_CHANGE_LAST_ACCESS
4937 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4939 if (!VALID_STAT(*psbuf)) {
4940 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4943 /* get some defaults (no modifications) if any info is zero or -1. */
4944 if (null_timespec(ft->atime)) {
4945 ft->atime= psbuf->st_ex_atime;
4946 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4949 if (null_timespec(ft->mtime)) {
4950 ft->mtime = psbuf->st_ex_mtime;
4951 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4954 if (!setting_write_time) {
4955 /* ft->mtime comes from change time, not write time. */
4956 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4959 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4960 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4961 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4962 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4963 if (!null_timespec(ft->create_time)) {
4964 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4965 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4969 * Try and set the times of this file if
4970 * they are different from the current values.
4974 struct timespec mts = psbuf->st_ex_mtime;
4975 struct timespec ats = psbuf->st_ex_atime;
4976 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4977 (timespec_compare(&ft->mtime, &mts) == 0)) {
4978 return NT_STATUS_OK;
4982 if (setting_write_time) {
4984 * This was a setfileinfo on an open file.
4985 * NT does this a lot. We also need to
4986 * set the time here, as it can be read by
4987 * FindFirst/FindNext and with the patch for bug #2045
4988 * in smbd/fileio.c it ensures that this timestamp is
4989 * kept sticky even after a write. We save the request
4990 * away and will set it on file close and after a write. JRA.
4993 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4994 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4997 if (fsp->base_fsp) {
4998 set_sticky_write_time_fsp(fsp->base_fsp,
5001 set_sticky_write_time_fsp(fsp, ft->mtime);
5004 set_sticky_write_time_path(conn, fname,
5005 vfs_file_id_from_sbuf(conn, psbuf),
5010 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5012 if (fsp && fsp->base_fsp) {
5013 fname = fsp->base_fsp->fsp_name;
5016 if(file_ntimes(conn, fname, ft, psbuf)!=0) {
5017 return map_nt_error_from_unix(errno);
5019 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
5021 return NT_STATUS_OK;
5024 /****************************************************************************
5025 Deal with setting the dosmode from any of the setfilepathinfo functions.
5026 ****************************************************************************/
5028 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5031 SMB_STRUCT_STAT *psbuf,
5034 if (!VALID_STAT(*psbuf)) {
5035 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5039 if (fsp->base_fsp) {
5040 fname = fsp->base_fsp->fsp_name;
5042 fname = fsp->fsp_name;
5047 if (S_ISDIR(psbuf->st_ex_mode)) {
5054 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5056 /* check the mode isn't different, before changing it */
5057 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5059 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5060 fname, (unsigned int)dosmode ));
5062 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5063 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5064 fname, strerror(errno)));
5065 return map_nt_error_from_unix(errno);
5068 return NT_STATUS_OK;
5071 /****************************************************************************
5072 Deal with setting the size from any of the setfilepathinfo functions.
5073 ****************************************************************************/
5075 static NTSTATUS smb_set_file_size(connection_struct *conn,
5076 struct smb_request *req,
5079 SMB_STRUCT_STAT *psbuf,
5082 struct smb_filename *smb_fname = NULL;
5083 NTSTATUS status = NT_STATUS_OK;
5084 files_struct *new_fsp = NULL;
5086 if (!VALID_STAT(*psbuf)) {
5087 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5090 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5092 if (size == get_file_size_stat(psbuf)) {
5093 return NT_STATUS_OK;
5096 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5097 fname, (double)size ));
5099 if (fsp && fsp->fh->fd != -1) {
5100 /* Handle based call. */
5101 if (vfs_set_filelen(fsp, size) == -1) {
5102 return map_nt_error_from_unix(errno);
5104 trigger_write_time_update_immediate(fsp);
5105 return NT_STATUS_OK;
5108 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5110 if (!NT_STATUS_IS_OK(status)) {
5114 status = SMB_VFS_CREATE_FILE(
5117 0, /* root_dir_fid */
5118 smb_fname, /* fname */
5119 FILE_WRITE_ATTRIBUTES, /* access_mask */
5120 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5122 FILE_OPEN, /* create_disposition*/
5123 0, /* create_options */
5124 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5125 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5126 0, /* allocation_size */
5129 &new_fsp, /* result */
5132 *psbuf = smb_fname->st;
5133 TALLOC_FREE(smb_fname);
5135 if (!NT_STATUS_IS_OK(status)) {
5136 /* NB. We check for open_was_deferred in the caller. */
5140 if (vfs_set_filelen(new_fsp, size) == -1) {
5141 status = map_nt_error_from_unix(errno);
5142 close_file(req, new_fsp,NORMAL_CLOSE);
5146 trigger_write_time_update_immediate(new_fsp);
5147 close_file(req, new_fsp,NORMAL_CLOSE);
5148 return NT_STATUS_OK;
5151 /****************************************************************************
5152 Deal with SMB_INFO_SET_EA.
5153 ****************************************************************************/
5155 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5159 const struct smb_filename *smb_fname)
5161 struct ea_list *ea_list = NULL;
5162 TALLOC_CTX *ctx = NULL;
5163 NTSTATUS status = NT_STATUS_OK;
5165 if (total_data < 10) {
5167 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5168 length. They seem to have no effect. Bug #3212. JRA */
5170 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5171 /* We're done. We only get EA info in this call. */
5172 return NT_STATUS_OK;
5175 return NT_STATUS_INVALID_PARAMETER;
5178 if (IVAL(pdata,0) > total_data) {
5179 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5180 IVAL(pdata,0), (unsigned int)total_data));
5181 return NT_STATUS_INVALID_PARAMETER;
5185 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5187 return NT_STATUS_INVALID_PARAMETER;
5189 status = set_ea(conn, fsp, smb_fname, ea_list);
5194 /****************************************************************************
5195 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5196 ****************************************************************************/
5198 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5203 SMB_STRUCT_STAT *psbuf)
5205 NTSTATUS status = NT_STATUS_OK;
5206 bool delete_on_close;
5209 if (total_data < 1) {
5210 return NT_STATUS_INVALID_PARAMETER;
5214 return NT_STATUS_INVALID_HANDLE;
5217 delete_on_close = (CVAL(pdata,0) ? True : False);
5218 dosmode = dos_mode(conn, fname, psbuf);
5220 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5221 "delete_on_close = %u\n",
5223 (unsigned int)dosmode,
5224 (unsigned int)delete_on_close ));
5226 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5228 if (!NT_STATUS_IS_OK(status)) {
5232 /* The set is across all open files on this dev/inode pair. */
5233 if (!set_delete_on_close(fsp, delete_on_close,
5234 &conn->server_info->utok)) {
5235 return NT_STATUS_ACCESS_DENIED;
5237 return NT_STATUS_OK;
5240 /****************************************************************************
5241 Deal with SMB_FILE_POSITION_INFORMATION.
5242 ****************************************************************************/
5244 static NTSTATUS smb_file_position_information(connection_struct *conn,
5249 uint64_t position_information;
5251 if (total_data < 8) {
5252 return NT_STATUS_INVALID_PARAMETER;
5256 /* Ignore on pathname based set. */
5257 return NT_STATUS_OK;
5260 position_information = (uint64_t)IVAL(pdata,0);
5261 #ifdef LARGE_SMB_OFF_T
5262 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5263 #else /* LARGE_SMB_OFF_T */
5264 if (IVAL(pdata,4) != 0) {
5265 /* more than 32 bits? */
5266 return NT_STATUS_INVALID_PARAMETER;
5268 #endif /* LARGE_SMB_OFF_T */
5270 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5271 fsp->fsp_name, (double)position_information ));
5272 fsp->fh->position_information = position_information;
5273 return NT_STATUS_OK;
5276 /****************************************************************************
5277 Deal with SMB_FILE_MODE_INFORMATION.
5278 ****************************************************************************/
5280 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5286 if (total_data < 4) {
5287 return NT_STATUS_INVALID_PARAMETER;
5289 mode = IVAL(pdata,0);
5290 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5291 return NT_STATUS_INVALID_PARAMETER;
5293 return NT_STATUS_OK;
5296 /****************************************************************************
5297 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5298 ****************************************************************************/
5300 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5301 struct smb_request *req,
5306 char *link_target = NULL;
5307 const char *newname = fname;
5308 NTSTATUS status = NT_STATUS_OK;
5309 TALLOC_CTX *ctx = talloc_tos();
5311 /* Set a symbolic link. */
5312 /* Don't allow this if follow links is false. */
5314 if (total_data == 0) {
5315 return NT_STATUS_INVALID_PARAMETER;
5318 if (!lp_symlinks(SNUM(conn))) {
5319 return NT_STATUS_ACCESS_DENIED;
5322 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5323 total_data, STR_TERMINATE);
5326 return NT_STATUS_INVALID_PARAMETER;
5329 /* !widelinks forces the target path to be within the share. */
5330 /* This means we can interpret the target as a pathname. */
5331 if (!lp_widelinks(SNUM(conn))) {
5332 char *rel_name = NULL;
5333 char *last_dirp = NULL;
5335 if (*link_target == '/') {
5336 /* No absolute paths allowed. */
5337 return NT_STATUS_ACCESS_DENIED;
5339 rel_name = talloc_strdup(ctx,newname);
5341 return NT_STATUS_NO_MEMORY;
5343 last_dirp = strrchr_m(rel_name, '/');
5345 last_dirp[1] = '\0';
5347 rel_name = talloc_strdup(ctx,"./");
5349 return NT_STATUS_NO_MEMORY;
5352 rel_name = talloc_asprintf_append(rel_name,
5356 return NT_STATUS_NO_MEMORY;
5359 status = check_name(conn, rel_name);
5360 if (!NT_STATUS_IS_OK(status)) {
5365 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5366 newname, link_target ));
5368 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5369 return map_nt_error_from_unix(errno);
5372 return NT_STATUS_OK;
5375 /****************************************************************************
5376 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5377 ****************************************************************************/
5379 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5380 struct smb_request *req,
5381 const char *pdata, int total_data,
5382 const struct smb_filename *smb_fname_new)
5384 char *oldname = NULL;
5385 struct smb_filename *smb_fname_old = NULL;
5386 TALLOC_CTX *ctx = talloc_tos();
5387 NTSTATUS status = NT_STATUS_OK;
5389 /* Set a hard link. */
5390 if (total_data == 0) {
5391 return NT_STATUS_INVALID_PARAMETER;
5394 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5395 total_data, STR_TERMINATE, &status);
5396 if (!NT_STATUS_IS_OK(status)) {
5400 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5401 smb_fname_str_dbg(smb_fname_new), oldname));
5403 status = filename_convert(ctx,
5405 req->flags2 & FLAGS2_DFS_PATHNAMES,
5409 if (!NT_STATUS_IS_OK(status)) {
5413 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5416 /****************************************************************************
5417 Deal with SMB_FILE_RENAME_INFORMATION.
5418 ****************************************************************************/
5420 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5421 struct smb_request *req,
5430 char *newname = NULL;
5431 char *base_name = NULL;
5432 struct smb_filename *smb_fname = NULL;
5433 bool dest_has_wcard = False;
5434 NTSTATUS status = NT_STATUS_OK;
5436 TALLOC_CTX *ctx = talloc_tos();
5438 if (total_data < 13) {
5439 return NT_STATUS_INVALID_PARAMETER;
5442 overwrite = (CVAL(pdata,0) ? True : False);
5443 root_fid = IVAL(pdata,4);
5444 len = IVAL(pdata,8);
5446 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5447 return NT_STATUS_INVALID_PARAMETER;
5450 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5453 if (!NT_STATUS_IS_OK(status)) {
5457 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5460 status = resolve_dfspath_wcard(ctx, conn,
5461 req->flags2 & FLAGS2_DFS_PATHNAMES,
5465 if (!NT_STATUS_IS_OK(status)) {
5469 /* Check the new name has no '/' characters. */
5470 if (strchr_m(newname, '/')) {
5471 return NT_STATUS_NOT_SUPPORTED;
5474 if (fsp && fsp->base_fsp) {
5475 /* newname must be a stream name. */
5476 if (newname[0] != ':') {
5477 return NT_STATUS_NOT_SUPPORTED;
5479 base_name = talloc_asprintf(ctx, "%s%s",
5480 fsp->base_fsp->fsp_name,
5483 return NT_STATUS_NO_MEMORY;
5486 /* newname must *not* be a stream name. */
5487 if (is_ntfs_stream_name(newname)) {
5488 return NT_STATUS_NOT_SUPPORTED;
5491 /* Create the base directory. */
5492 base_name = talloc_strdup(ctx, fname);
5494 return NT_STATUS_NO_MEMORY;
5496 p = strrchr_m(base_name, '/');
5500 base_name = talloc_strdup(ctx, "./");
5502 return NT_STATUS_NO_MEMORY;
5505 /* Append the new name. */
5506 base_name = talloc_asprintf_append(base_name,
5510 return NT_STATUS_NO_MEMORY;
5513 status = unix_convert(ctx, conn, newname, &smb_fname,
5516 /* If an error we expect this to be
5517 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5519 if (!NT_STATUS_IS_OK(status)
5520 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5527 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5528 fsp->fnum, fsp->fsp_name, base_name ));
5529 status = rename_internals_fsp(conn, fsp, base_name,
5531 smb_fname->original_lcomp : NULL,
5534 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5535 fname, base_name ));
5536 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5537 overwrite, False, dest_has_wcard,
5538 FILE_WRITE_ATTRIBUTES);
5541 TALLOC_FREE(smb_fname);
5545 /****************************************************************************
5546 Deal with SMB_SET_POSIX_ACL.
5547 ****************************************************************************/
5549 #if defined(HAVE_POSIX_ACLS)
5550 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5555 SMB_STRUCT_STAT *psbuf)
5557 uint16 posix_acl_version;
5558 uint16 num_file_acls;
5559 uint16 num_def_acls;
5560 bool valid_file_acls = True;
5561 bool valid_def_acls = True;
5563 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5564 return NT_STATUS_INVALID_PARAMETER;
5566 posix_acl_version = SVAL(pdata,0);
5567 num_file_acls = SVAL(pdata,2);
5568 num_def_acls = SVAL(pdata,4);
5570 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5571 valid_file_acls = False;
5575 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5576 valid_def_acls = False;
5580 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5581 return NT_STATUS_INVALID_PARAMETER;
5584 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5585 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5586 return NT_STATUS_INVALID_PARAMETER;
5589 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5590 fname ? fname : fsp->fsp_name,
5591 (unsigned int)num_file_acls,
5592 (unsigned int)num_def_acls));
5594 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5595 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5596 return map_nt_error_from_unix(errno);
5599 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5600 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5601 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5602 return map_nt_error_from_unix(errno);
5604 return NT_STATUS_OK;
5608 /****************************************************************************
5609 Deal with SMB_SET_POSIX_LOCK.
5610 ****************************************************************************/
5612 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5613 struct smb_request *req,
5621 bool blocking_lock = False;
5622 enum brl_type lock_type;
5624 NTSTATUS status = NT_STATUS_OK;
5626 if (fsp == NULL || fsp->fh->fd == -1) {
5627 return NT_STATUS_INVALID_HANDLE;
5630 if (total_data != POSIX_LOCK_DATA_SIZE) {
5631 return NT_STATUS_INVALID_PARAMETER;
5634 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5635 case POSIX_LOCK_TYPE_READ:
5636 lock_type = READ_LOCK;
5638 case POSIX_LOCK_TYPE_WRITE:
5639 /* Return the right POSIX-mappable error code for files opened read-only. */
5640 if (!fsp->can_write) {
5641 return NT_STATUS_INVALID_HANDLE;
5643 lock_type = WRITE_LOCK;
5645 case POSIX_LOCK_TYPE_UNLOCK:
5646 lock_type = UNLOCK_LOCK;
5649 return NT_STATUS_INVALID_PARAMETER;
5652 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5653 blocking_lock = False;
5654 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5655 blocking_lock = True;
5657 return NT_STATUS_INVALID_PARAMETER;
5660 if (!lp_blocking_locks(SNUM(conn))) {
5661 blocking_lock = False;
5664 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5665 #if defined(HAVE_LONGLONG)
5666 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5667 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5668 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5669 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5670 #else /* HAVE_LONGLONG */
5671 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5672 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5673 #endif /* HAVE_LONGLONG */
5675 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5676 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5678 (unsigned int)lock_type,
5679 (unsigned int)lock_pid,
5683 if (lock_type == UNLOCK_LOCK) {
5684 status = do_unlock(smbd_messaging_context(),
5691 uint32 block_smbpid;
5693 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5705 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5707 * A blocking lock was requested. Package up
5708 * this smb into a queued request and push it
5709 * onto the blocking lock queue.
5711 if(push_blocking_lock_request(br_lck,
5714 -1, /* infinite timeout. */
5722 TALLOC_FREE(br_lck);
5726 TALLOC_FREE(br_lck);
5732 /****************************************************************************
5733 Deal with SMB_INFO_STANDARD.
5734 ****************************************************************************/
5736 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5741 const SMB_STRUCT_STAT *psbuf)
5743 struct smb_file_time ft;
5746 if (total_data < 12) {
5747 return NT_STATUS_INVALID_PARAMETER;
5751 ft.create_time = interpret_long_date(pdata);
5754 ft.atime = interpret_long_date(pdata + 8);
5757 ft.mtime = interpret_long_date(pdata + 16);
5759 DEBUG(10,("smb_set_info_standard: file %s\n",
5760 fname ? fname : fsp->fsp_name ));
5762 return smb_set_file_time(conn,
5770 /****************************************************************************
5771 Deal with SMB_SET_FILE_BASIC_INFO.
5772 ****************************************************************************/
5774 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5779 SMB_STRUCT_STAT *psbuf)
5781 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5782 struct timespec write_time;
5783 struct timespec changed_time;
5784 struct smb_file_time ft;
5786 NTSTATUS status = NT_STATUS_OK;
5787 bool setting_write_time = true;
5791 if (total_data < 36) {
5792 return NT_STATUS_INVALID_PARAMETER;
5795 /* Set the attributes */
5796 dosmode = IVAL(pdata,32);
5797 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5798 if (!NT_STATUS_IS_OK(status)) {
5803 ft.atime = interpret_long_date(pdata+8);
5805 write_time = interpret_long_date(pdata+16);
5806 changed_time = interpret_long_date(pdata+24);
5809 ft.mtime = timespec_min(&write_time, &changed_time);
5812 ft.create_time = interpret_long_date(pdata);
5814 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5815 !null_timespec(write_time)) {
5816 ft.mtime = write_time;
5819 /* Prefer a defined time to an undefined one. */
5820 if (null_timespec(ft.mtime)) {
5821 if (null_timespec(write_time)) {
5822 ft.mtime = changed_time;
5823 setting_write_time = false;
5825 ft.mtime = write_time;
5829 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5830 fname ? fname : fsp->fsp_name ));
5832 return smb_set_file_time(conn,
5837 setting_write_time);
5840 /****************************************************************************
5841 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5842 ****************************************************************************/
5844 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5845 struct smb_request *req,
5850 SMB_STRUCT_STAT *psbuf)
5852 struct smb_filename *smb_fname = NULL;
5853 uint64_t allocation_size = 0;
5854 NTSTATUS status = NT_STATUS_OK;
5855 files_struct *new_fsp = NULL;
5857 if (!VALID_STAT(*psbuf)) {
5858 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5861 if (total_data < 8) {
5862 return NT_STATUS_INVALID_PARAMETER;
5865 allocation_size = (uint64_t)IVAL(pdata,0);
5866 #ifdef LARGE_SMB_OFF_T
5867 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5868 #else /* LARGE_SMB_OFF_T */
5869 if (IVAL(pdata,4) != 0) {
5870 /* more than 32 bits? */
5871 return NT_STATUS_INVALID_PARAMETER;
5873 #endif /* LARGE_SMB_OFF_T */
5875 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5876 fname, (double)allocation_size ));
5878 if (allocation_size) {
5879 allocation_size = smb_roundup(conn, allocation_size);
5882 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5883 fname, (double)allocation_size ));
5885 if (fsp && fsp->fh->fd != -1) {
5886 /* Open file handle. */
5887 /* Only change if needed. */
5888 if (allocation_size != get_file_size_stat(psbuf)) {
5889 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5890 return map_nt_error_from_unix(errno);
5893 /* But always update the time. */
5895 * This is equivalent to a write. Ensure it's seen immediately
5896 * if there are no pending writes.
5898 trigger_write_time_update_immediate(fsp);
5899 return NT_STATUS_OK;
5902 /* Pathname or stat or directory file. */
5904 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5906 if (!NT_STATUS_IS_OK(status)) {
5910 status = SMB_VFS_CREATE_FILE(
5913 0, /* root_dir_fid */
5914 smb_fname, /* fname */
5915 FILE_WRITE_DATA, /* access_mask */
5916 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5918 FILE_OPEN, /* create_disposition*/
5919 0, /* create_options */
5920 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5921 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5922 0, /* allocation_size */
5925 &new_fsp, /* result */
5928 *psbuf = smb_fname->st;
5929 TALLOC_FREE(smb_fname);
5931 if (!NT_STATUS_IS_OK(status)) {
5932 /* NB. We check for open_was_deferred in the caller. */
5936 /* Only change if needed. */
5937 if (allocation_size != get_file_size_stat(psbuf)) {
5938 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5939 status = map_nt_error_from_unix(errno);
5940 close_file(req, new_fsp, NORMAL_CLOSE);
5945 /* Changing the allocation size should set the last mod time. */
5947 * This is equivalent to a write. Ensure it's seen immediately
5948 * if there are no pending writes.
5950 trigger_write_time_update_immediate(new_fsp);
5952 close_file(req, new_fsp, NORMAL_CLOSE);
5953 return NT_STATUS_OK;
5956 /****************************************************************************
5957 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5958 ****************************************************************************/
5960 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5961 struct smb_request *req,
5966 SMB_STRUCT_STAT *psbuf)
5970 if (total_data < 8) {
5971 return NT_STATUS_INVALID_PARAMETER;
5974 size = IVAL(pdata,0);
5975 #ifdef LARGE_SMB_OFF_T
5976 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5977 #else /* LARGE_SMB_OFF_T */
5978 if (IVAL(pdata,4) != 0) {
5979 /* more than 32 bits? */
5980 return NT_STATUS_INVALID_PARAMETER;
5982 #endif /* LARGE_SMB_OFF_T */
5983 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5984 "file %s to %.0f\n", fname, (double)size ));
5986 return smb_set_file_size(conn, req,
5993 /****************************************************************************
5994 Allow a UNIX info mknod.
5995 ****************************************************************************/
5997 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6001 SMB_STRUCT_STAT *psbuf)
6003 uint32 file_type = IVAL(pdata,56);
6004 #if defined(HAVE_MAKEDEV)
6005 uint32 dev_major = IVAL(pdata,60);
6006 uint32 dev_minor = IVAL(pdata,68);
6008 SMB_DEV_T dev = (SMB_DEV_T)0;
6009 uint32 raw_unixmode = IVAL(pdata,84);
6013 if (total_data < 100) {
6014 return NT_STATUS_INVALID_PARAMETER;
6017 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
6018 if (!NT_STATUS_IS_OK(status)) {
6022 #if defined(HAVE_MAKEDEV)
6023 dev = makedev(dev_major, dev_minor);
6026 switch (file_type) {
6027 #if defined(S_IFIFO)
6028 case UNIX_TYPE_FIFO:
6029 unixmode |= S_IFIFO;
6032 #if defined(S_IFSOCK)
6033 case UNIX_TYPE_SOCKET:
6034 unixmode |= S_IFSOCK;
6037 #if defined(S_IFCHR)
6038 case UNIX_TYPE_CHARDEV:
6039 unixmode |= S_IFCHR;
6042 #if defined(S_IFBLK)
6043 case UNIX_TYPE_BLKDEV:
6044 unixmode |= S_IFBLK;
6048 return NT_STATUS_INVALID_PARAMETER;
6051 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6052 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6054 /* Ok - do the mknod. */
6055 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6056 return map_nt_error_from_unix(errno);
6059 /* If any of the other "set" calls fail we
6060 * don't want to end up with a half-constructed mknod.
6063 if (lp_inherit_perms(SNUM(conn))) {
6065 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6066 return NT_STATUS_NO_MEMORY;
6068 inherit_access_posix_acl(conn, parent, fname, unixmode);
6069 TALLOC_FREE(parent);
6072 if (vfs_stat_smb_fname(conn, fname, psbuf) != 0) {
6073 status = map_nt_error_from_unix(errno);
6074 SMB_VFS_UNLINK(conn,fname);
6077 return NT_STATUS_OK;
6080 /****************************************************************************
6081 Deal with SMB_SET_FILE_UNIX_BASIC.
6082 ****************************************************************************/
6084 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6085 struct smb_request *req,
6090 SMB_STRUCT_STAT *psbuf)
6092 struct smb_file_time ft;
6093 uint32 raw_unixmode;
6096 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6097 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6098 NTSTATUS status = NT_STATUS_OK;
6099 bool delete_on_fail = False;
6100 enum perm_type ptype;
6104 if (total_data < 100) {
6105 return NT_STATUS_INVALID_PARAMETER;
6108 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6109 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6110 size=IVAL(pdata,0); /* first 8 Bytes are size */
6111 #ifdef LARGE_SMB_OFF_T
6112 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6113 #else /* LARGE_SMB_OFF_T */
6114 if (IVAL(pdata,4) != 0) {
6115 /* more than 32 bits? */
6116 return NT_STATUS_INVALID_PARAMETER;
6118 #endif /* LARGE_SMB_OFF_T */
6121 ft.atime = interpret_long_date(pdata+24); /* access_time */
6122 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6123 set_owner = (uid_t)IVAL(pdata,40);
6124 set_grp = (gid_t)IVAL(pdata,48);
6125 raw_unixmode = IVAL(pdata,84);
6127 if (VALID_STAT(*psbuf)) {
6128 if (S_ISDIR(psbuf->st_ex_mode)) {
6129 ptype = PERM_EXISTING_DIR;
6131 ptype = PERM_EXISTING_FILE;
6134 ptype = PERM_NEW_FILE;
6137 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6138 if (!NT_STATUS_IS_OK(status)) {
6142 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6143 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6144 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6146 if (!VALID_STAT(*psbuf)) {
6148 * The only valid use of this is to create character and block
6149 * devices, and named pipes. This is deprecated (IMHO) and
6150 * a new info level should be used for mknod. JRA.
6153 status = smb_unix_mknod(conn,
6158 if (!NT_STATUS_IS_OK(status)) {
6162 /* Ensure we don't try and change anything else. */
6163 raw_unixmode = SMB_MODE_NO_CHANGE;
6164 size = get_file_size_stat(psbuf);
6165 ft.atime = psbuf->st_ex_atime;
6166 ft.mtime = psbuf->st_ex_mtime;
6168 * We continue here as we might want to change the
6171 delete_on_fail = True;
6175 /* Horrible backwards compatibility hack as an old server bug
6176 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6180 size = get_file_size_stat(psbuf);
6185 * Deal with the UNIX specific mode set.
6188 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6189 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6190 (unsigned int)unixmode, fname ));
6191 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6192 return map_nt_error_from_unix(errno);
6197 * Deal with the UNIX specific uid set.
6200 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_ex_uid != set_owner)) {
6203 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6204 (unsigned int)set_owner, fname ));
6206 if (S_ISLNK(psbuf->st_ex_mode)) {
6207 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6209 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6213 status = map_nt_error_from_unix(errno);
6214 if (delete_on_fail) {
6215 SMB_VFS_UNLINK(conn,fname);
6222 * Deal with the UNIX specific gid set.
6225 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_ex_gid != set_grp)) {
6226 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6227 (unsigned int)set_owner, fname ));
6228 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6229 status = map_nt_error_from_unix(errno);
6230 if (delete_on_fail) {
6231 SMB_VFS_UNLINK(conn,fname);
6237 /* Deal with any size changes. */
6239 status = smb_set_file_size(conn, req,
6244 if (!NT_STATUS_IS_OK(status)) {
6248 /* Deal with any time changes. */
6250 return smb_set_file_time(conn,
6258 /****************************************************************************
6259 Deal with SMB_SET_FILE_UNIX_INFO2.
6260 ****************************************************************************/
6262 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6263 struct smb_request *req,
6268 SMB_STRUCT_STAT *psbuf)
6274 if (total_data < 116) {
6275 return NT_STATUS_INVALID_PARAMETER;
6278 /* Start by setting all the fields that are common between UNIX_BASIC
6281 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6283 if (!NT_STATUS_IS_OK(status)) {
6287 smb_fflags = IVAL(pdata, 108);
6288 smb_fmask = IVAL(pdata, 112);
6290 /* NB: We should only attempt to alter the file flags if the client
6291 * sends a non-zero mask.
6293 if (smb_fmask != 0) {
6294 int stat_fflags = 0;
6296 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6298 /* Client asked to alter a flag we don't understand. */
6299 return NT_STATUS_INVALID_PARAMETER;
6302 if (fsp && fsp->fh->fd != -1) {
6303 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6304 return NT_STATUS_NOT_SUPPORTED;
6306 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6307 return map_nt_error_from_unix(errno);
6312 /* XXX: need to add support for changing the create_time here. You
6313 * can do this for paths on Darwin with setattrlist(2). The right way
6314 * to hook this up is probably by extending the VFS utimes interface.
6317 return NT_STATUS_OK;
6320 /****************************************************************************
6321 Create a directory with POSIX semantics.
6322 ****************************************************************************/
6324 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6325 struct smb_request *req,
6329 SMB_STRUCT_STAT *psbuf,
6330 int *pdata_return_size)
6332 struct smb_filename *smb_fname;
6333 NTSTATUS status = NT_STATUS_OK;
6334 uint32 raw_unixmode = 0;
6335 uint32 mod_unixmode = 0;
6336 mode_t unixmode = (mode_t)0;
6337 files_struct *fsp = NULL;
6338 uint16 info_level_return = 0;
6340 char *pdata = *ppdata;
6342 if (total_data < 18) {
6343 return NT_STATUS_INVALID_PARAMETER;
6346 raw_unixmode = IVAL(pdata,8);
6347 /* Next 4 bytes are not yet defined. */
6349 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6350 if (!NT_STATUS_IS_OK(status)) {
6354 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6356 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6357 fname, (unsigned int)unixmode ));
6359 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6361 if (!NT_STATUS_IS_OK(status)) {
6365 status = SMB_VFS_CREATE_FILE(
6368 0, /* root_dir_fid */
6369 smb_fname, /* fname */
6370 FILE_READ_ATTRIBUTES, /* access_mask */
6371 FILE_SHARE_NONE, /* share_access */
6372 FILE_CREATE, /* create_disposition*/
6373 FILE_DIRECTORY_FILE, /* create_options */
6374 mod_unixmode, /* file_attributes */
6375 0, /* oplock_request */
6376 0, /* allocation_size */
6382 *psbuf = smb_fname->st;
6383 TALLOC_FREE(smb_fname);
6385 if (NT_STATUS_IS_OK(status)) {
6386 close_file(req, fsp, NORMAL_CLOSE);
6389 info_level_return = SVAL(pdata,16);
6391 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6392 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6393 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6394 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6396 *pdata_return_size = 12;
6399 /* Realloc the data size */
6400 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6401 if (*ppdata == NULL) {
6402 *pdata_return_size = 0;
6403 return NT_STATUS_NO_MEMORY;
6407 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6408 SSVAL(pdata,2,0); /* No fnum. */
6409 SIVAL(pdata,4,info); /* Was directory created. */
6411 switch (info_level_return) {
6412 case SMB_QUERY_FILE_UNIX_BASIC:
6413 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6414 SSVAL(pdata,10,0); /* Padding. */
6415 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6417 case SMB_QUERY_FILE_UNIX_INFO2:
6418 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6419 SSVAL(pdata,10,0); /* Padding. */
6420 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6423 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6424 SSVAL(pdata,10,0); /* Padding. */
6431 /****************************************************************************
6432 Open/Create a file with POSIX semantics.
6433 ****************************************************************************/
6435 static NTSTATUS smb_posix_open(connection_struct *conn,
6436 struct smb_request *req,
6440 SMB_STRUCT_STAT *psbuf,
6441 int *pdata_return_size)
6443 struct smb_filename *smb_fname = NULL;
6444 bool extended_oplock_granted = False;
6445 char *pdata = *ppdata;
6447 uint32 wire_open_mode = 0;
6448 uint32 raw_unixmode = 0;
6449 uint32 mod_unixmode = 0;
6450 uint32 create_disp = 0;
6451 uint32 access_mask = 0;
6452 uint32 create_options = 0;
6453 NTSTATUS status = NT_STATUS_OK;
6454 mode_t unixmode = (mode_t)0;
6455 files_struct *fsp = NULL;
6456 int oplock_request = 0;
6458 uint16 info_level_return = 0;
6460 if (total_data < 18) {
6461 return NT_STATUS_INVALID_PARAMETER;
6464 flags = IVAL(pdata,0);
6465 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6466 if (oplock_request) {
6467 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6470 wire_open_mode = IVAL(pdata,4);
6472 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6473 return smb_posix_mkdir(conn, req,
6481 switch (wire_open_mode & SMB_ACCMODE) {
6483 access_mask = FILE_READ_DATA;
6486 access_mask = FILE_WRITE_DATA;
6489 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6492 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6493 (unsigned int)wire_open_mode ));
6494 return NT_STATUS_INVALID_PARAMETER;
6497 wire_open_mode &= ~SMB_ACCMODE;
6499 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6500 create_disp = FILE_CREATE;
6501 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6502 create_disp = FILE_OVERWRITE_IF;
6503 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6504 create_disp = FILE_OPEN_IF;
6505 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6506 create_disp = FILE_OPEN;
6508 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6509 (unsigned int)wire_open_mode ));
6510 return NT_STATUS_INVALID_PARAMETER;
6513 raw_unixmode = IVAL(pdata,8);
6514 /* Next 4 bytes are not yet defined. */
6516 status = unix_perms_from_wire(conn,
6519 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6522 if (!NT_STATUS_IS_OK(status)) {
6526 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6528 if (wire_open_mode & SMB_O_SYNC) {
6529 create_options |= FILE_WRITE_THROUGH;
6531 if (wire_open_mode & SMB_O_APPEND) {
6532 access_mask |= FILE_APPEND_DATA;
6534 if (wire_open_mode & SMB_O_DIRECT) {
6535 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6538 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6540 (unsigned int)wire_open_mode,
6541 (unsigned int)unixmode ));
6543 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6545 if (!NT_STATUS_IS_OK(status)) {
6549 status = SMB_VFS_CREATE_FILE(
6552 0, /* root_dir_fid */
6553 smb_fname, /* fname */
6554 access_mask, /* access_mask */
6555 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6557 create_disp, /* create_disposition*/
6558 FILE_NON_DIRECTORY_FILE, /* create_options */
6559 mod_unixmode, /* file_attributes */
6560 oplock_request, /* oplock_request */
6561 0, /* allocation_size */
6567 *psbuf = smb_fname->st;
6568 TALLOC_FREE(smb_fname);
6570 if (!NT_STATUS_IS_OK(status)) {
6574 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6575 extended_oplock_granted = True;
6578 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6579 extended_oplock_granted = True;
6582 info_level_return = SVAL(pdata,16);
6584 /* Allocate the correct return size. */
6586 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6587 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6588 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6589 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6591 *pdata_return_size = 12;
6594 /* Realloc the data size */
6595 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6596 if (*ppdata == NULL) {
6597 close_file(req, fsp, ERROR_CLOSE);
6598 *pdata_return_size = 0;
6599 return NT_STATUS_NO_MEMORY;
6603 if (extended_oplock_granted) {
6604 if (flags & REQUEST_BATCH_OPLOCK) {
6605 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6607 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6609 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6610 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6612 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6615 SSVAL(pdata,2,fsp->fnum);
6616 SIVAL(pdata,4,info); /* Was file created etc. */
6618 switch (info_level_return) {
6619 case SMB_QUERY_FILE_UNIX_BASIC:
6620 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6621 SSVAL(pdata,10,0); /* padding. */
6622 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6624 case SMB_QUERY_FILE_UNIX_INFO2:
6625 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6626 SSVAL(pdata,10,0); /* padding. */
6627 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6630 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6631 SSVAL(pdata,10,0); /* padding. */
6634 return NT_STATUS_OK;
6637 /****************************************************************************
6638 Delete a file with POSIX semantics.
6639 ****************************************************************************/
6641 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6642 struct smb_request *req,
6646 SMB_STRUCT_STAT *psbuf)
6648 struct smb_filename *smb_fname = NULL;
6649 NTSTATUS status = NT_STATUS_OK;
6650 files_struct *fsp = NULL;
6654 int create_options = 0;
6656 struct share_mode_lock *lck = NULL;
6658 if (total_data < 2) {
6659 return NT_STATUS_INVALID_PARAMETER;
6662 flags = SVAL(pdata,0);
6664 if (!VALID_STAT(*psbuf)) {
6665 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6668 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6669 !VALID_STAT_OF_DIR(*psbuf)) {
6670 return NT_STATUS_NOT_A_DIRECTORY;
6673 DEBUG(10,("smb_posix_unlink: %s %s\n",
6674 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6677 if (VALID_STAT_OF_DIR(*psbuf)) {
6678 create_options |= FILE_DIRECTORY_FILE;
6681 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6683 if (!NT_STATUS_IS_OK(status)) {
6687 status = SMB_VFS_CREATE_FILE(
6690 0, /* root_dir_fid */
6691 smb_fname, /* fname */
6692 DELETE_ACCESS, /* access_mask */
6693 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6695 FILE_OPEN, /* create_disposition*/
6696 create_options, /* create_options */
6697 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6698 0, /* oplock_request */
6699 0, /* allocation_size */
6705 *psbuf = smb_fname->st;
6706 TALLOC_FREE(smb_fname);
6708 if (!NT_STATUS_IS_OK(status)) {
6713 * Don't lie to client. If we can't really delete due to
6714 * non-POSIX opens return SHARING_VIOLATION.
6717 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6720 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6721 "lock for file %s\n", fsp->fsp_name));
6722 close_file(req, fsp, NORMAL_CLOSE);
6723 return NT_STATUS_INVALID_PARAMETER;
6727 * See if others still have the file open. If this is the case, then
6728 * don't delete. If all opens are POSIX delete we can set the delete
6729 * on close disposition.
6731 for (i=0; i<lck->num_share_modes; i++) {
6732 struct share_mode_entry *e = &lck->share_modes[i];
6733 if (is_valid_share_mode_entry(e)) {
6734 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6737 /* Fail with sharing violation. */
6738 close_file(req, fsp, NORMAL_CLOSE);
6740 return NT_STATUS_SHARING_VIOLATION;
6745 * Set the delete on close.
6747 status = smb_set_file_disposition_info(conn,
6754 if (!NT_STATUS_IS_OK(status)) {
6755 close_file(req, fsp, NORMAL_CLOSE);
6760 return close_file(req, fsp, NORMAL_CLOSE);
6763 /****************************************************************************
6764 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6765 ****************************************************************************/
6767 static void call_trans2setfilepathinfo(connection_struct *conn,
6768 struct smb_request *req,
6769 unsigned int tran_call,
6770 char **pparams, int total_params,
6771 char **ppdata, int total_data,
6772 unsigned int max_data_bytes)
6774 char *params = *pparams;
6775 char *pdata = *ppdata;
6777 SMB_STRUCT_STAT sbuf;
6779 struct smb_filename *smb_fname = NULL;
6780 files_struct *fsp = NULL;
6781 NTSTATUS status = NT_STATUS_OK;
6782 int data_return_size = 0;
6783 TALLOC_CTX *ctx = talloc_tos();
6786 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6790 if (tran_call == TRANSACT2_SETFILEINFO) {
6791 if (total_params < 4) {
6792 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6796 fsp = file_fsp(req, SVAL(params,0));
6797 /* Basic check for non-null fsp. */
6798 if (!check_fsp_open(conn, req, fsp)) {
6801 info_level = SVAL(params,2);
6803 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6805 reply_nterror(req, NT_STATUS_NO_MEMORY);
6809 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
6811 if (!NT_STATUS_IS_OK(status)) {
6812 reply_nterror(req, status);
6816 if(fsp->is_directory || fsp->fh->fd == -1) {
6818 * This is actually a SETFILEINFO on a directory
6819 * handle (returned from an NT SMB). NT5.0 seems
6820 * to do this call. JRA.
6822 if (INFO_LEVEL_IS_UNIX(info_level)) {
6823 /* Always do lstat for UNIX calls. */
6824 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6825 DEBUG(3,("call_trans2setfilepathinfo: "
6826 "SMB_VFS_LSTAT of %s failed "
6828 smb_fname_str_dbg(smb_fname),
6830 reply_unixerror(req,ERRDOS,ERRbadpath);
6834 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6835 DEBUG(3,("call_trans2setfilepathinfo: "
6836 "fileinfo of %s failed (%s)\n",
6837 smb_fname_str_dbg(smb_fname),
6839 reply_unixerror(req,ERRDOS,ERRbadpath);
6843 } else if (fsp->print_file) {
6845 * Doing a DELETE_ON_CLOSE should cancel a print job.
6847 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6848 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6850 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6853 send_trans2_replies(conn, req, params, 2,
6858 reply_unixerror(req, ERRDOS, ERRbadpath);
6863 * Original code - this is an open file.
6865 if (!check_fsp(conn, req, fsp)) {
6869 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6870 DEBUG(3,("call_trans2setfilepathinfo: fstat "
6871 "of fnum %d failed (%s)\n", fsp->fnum,
6873 reply_unixerror(req, ERRDOS, ERRbadfid);
6879 if (total_params < 7) {
6880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6884 info_level = SVAL(params,0);
6885 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6886 total_params - 6, STR_TERMINATE,
6888 if (!NT_STATUS_IS_OK(status)) {
6889 reply_nterror(req, status);
6893 status = filename_convert(ctx, conn,
6894 req->flags2 & FLAGS2_DFS_PATHNAMES,
6898 if (!NT_STATUS_IS_OK(status)) {
6899 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6900 reply_botherror(req,
6901 NT_STATUS_PATH_NOT_COVERED,
6902 ERRSRV, ERRbadpath);
6905 reply_nterror(req, status);
6909 if (INFO_LEVEL_IS_UNIX(info_level)) {
6911 * For CIFS UNIX extensions the target name may not exist.
6914 /* Always do lstat for UNIX calls. */
6915 SMB_VFS_LSTAT(conn, smb_fname);
6917 } else if (!VALID_STAT(smb_fname->st) &&
6918 SMB_VFS_STAT(conn, smb_fname)) {
6919 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
6921 smb_fname_str_dbg(smb_fname),
6923 reply_unixerror(req, ERRDOS, ERRbadpath);
6928 /* Set sbuf for use below. */
6929 sbuf = smb_fname->st;
6931 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6932 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6936 if (!CAN_WRITE(conn)) {
6937 /* Allow POSIX opens. The open path will deny
6938 * any non-readonly opens. */
6939 if (info_level != SMB_POSIX_PATH_OPEN) {
6940 reply_doserror(req, ERRSRV, ERRaccess);
6945 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6946 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6948 /* Realloc the parameter size */
6949 *pparams = (char *)SMB_REALLOC(*pparams,2);
6950 if (*pparams == NULL) {
6951 reply_nterror(req, NT_STATUS_NO_MEMORY);
6958 switch (info_level) {
6960 case SMB_INFO_STANDARD:
6962 status = smb_set_info_standard(conn,
6971 case SMB_INFO_SET_EA:
6973 status = smb_info_set_ea(conn,
6981 case SMB_SET_FILE_BASIC_INFO:
6982 case SMB_FILE_BASIC_INFORMATION:
6984 status = smb_set_file_basic_info(conn,
6993 case SMB_FILE_ALLOCATION_INFORMATION:
6994 case SMB_SET_FILE_ALLOCATION_INFO:
6996 status = smb_set_file_allocation_info(conn, req,
7005 case SMB_FILE_END_OF_FILE_INFORMATION:
7006 case SMB_SET_FILE_END_OF_FILE_INFO:
7008 status = smb_set_file_end_of_file_info(conn, req,
7017 case SMB_FILE_DISPOSITION_INFORMATION:
7018 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7021 /* JRA - We used to just ignore this on a path ?
7022 * Shouldn't this be invalid level on a pathname
7025 if (tran_call != TRANSACT2_SETFILEINFO) {
7026 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7029 status = smb_set_file_disposition_info(conn,
7038 case SMB_FILE_POSITION_INFORMATION:
7040 status = smb_file_position_information(conn,
7047 /* From tridge Samba4 :
7048 * MODE_INFORMATION in setfileinfo (I have no
7049 * idea what "mode information" on a file is - it takes a value of 0,
7050 * 2, 4 or 6. What could it be?).
7053 case SMB_FILE_MODE_INFORMATION:
7055 status = smb_file_mode_information(conn,
7062 * CIFS UNIX extensions.
7065 case SMB_SET_FILE_UNIX_BASIC:
7067 status = smb_set_file_unix_basic(conn, req,
7076 case SMB_SET_FILE_UNIX_INFO2:
7078 status = smb_set_file_unix_info2(conn, req,
7087 case SMB_SET_FILE_UNIX_LINK:
7089 if (tran_call != TRANSACT2_SETPATHINFO) {
7090 /* We must have a pathname for this. */
7091 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7094 status = smb_set_file_unix_link(conn, req, pdata,
7099 case SMB_SET_FILE_UNIX_HLINK:
7101 if (tran_call != TRANSACT2_SETPATHINFO || smb_fname == NULL) {
7102 /* We must have a pathname for this. */
7103 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7106 status = smb_set_file_unix_hlink(conn, req,
7112 case SMB_FILE_RENAME_INFORMATION:
7114 status = smb_file_rename_information(conn, req,
7120 #if defined(HAVE_POSIX_ACLS)
7121 case SMB_SET_POSIX_ACL:
7123 status = smb_set_posix_acl(conn,
7133 case SMB_SET_POSIX_LOCK:
7135 if (tran_call != TRANSACT2_SETFILEINFO) {
7136 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7139 status = smb_set_posix_lock(conn, req,
7140 pdata, total_data, fsp);
7144 case SMB_POSIX_PATH_OPEN:
7146 if (tran_call != TRANSACT2_SETPATHINFO) {
7147 /* We must have a pathname for this. */
7148 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7152 status = smb_posix_open(conn, req,
7161 case SMB_POSIX_PATH_UNLINK:
7163 if (tran_call != TRANSACT2_SETPATHINFO) {
7164 /* We must have a pathname for this. */
7165 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7169 status = smb_posix_unlink(conn, req,
7178 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7182 if (!NT_STATUS_IS_OK(status)) {
7183 if (open_was_deferred(req->mid)) {
7184 /* We have re-scheduled this call. */
7187 if (blocking_lock_was_deferred(req->mid)) {
7188 /* We have re-scheduled this call. */
7191 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7192 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7193 ERRSRV, ERRbadpath);
7196 if (info_level == SMB_POSIX_PATH_OPEN) {
7197 reply_openerror(req, status);
7201 reply_nterror(req, status);
7206 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7212 /****************************************************************************
7213 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7214 ****************************************************************************/
7216 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7217 char **pparams, int total_params,
7218 char **ppdata, int total_data,
7219 unsigned int max_data_bytes)
7221 struct smb_filename *smb_dname = NULL;
7222 char *params = *pparams;
7223 char *pdata = *ppdata;
7224 char *directory = NULL;
7225 NTSTATUS status = NT_STATUS_OK;
7226 struct ea_list *ea_list = NULL;
7227 TALLOC_CTX *ctx = talloc_tos();
7229 if (!CAN_WRITE(conn)) {
7230 reply_doserror(req, ERRSRV, ERRaccess);
7234 if (total_params < 5) {
7235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7239 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7240 total_params - 4, STR_TERMINATE,
7242 if (!NT_STATUS_IS_OK(status)) {
7243 reply_nterror(req, status);
7247 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7249 status = filename_convert(ctx,
7251 req->flags2 & FLAGS2_DFS_PATHNAMES,
7256 if (!NT_STATUS_IS_OK(status)) {
7257 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7258 reply_botherror(req,
7259 NT_STATUS_PATH_NOT_COVERED,
7260 ERRSRV, ERRbadpath);
7263 reply_nterror(req, status);
7267 /* Any data in this call is an EA list. */
7268 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7269 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7274 * OS/2 workplace shell seems to send SET_EA requests of "null"
7275 * length (4 bytes containing IVAL 4).
7276 * They seem to have no effect. Bug #3212. JRA.
7279 if (total_data != 4) {
7280 if (total_data < 10) {
7281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7285 if (IVAL(pdata,0) > total_data) {
7286 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7287 IVAL(pdata,0), (unsigned int)total_data));
7288 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7292 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7299 /* If total_data == 4 Windows doesn't care what values
7300 * are placed in that field, it just ignores them.
7301 * The System i QNTC IBM SMB client puts bad values here,
7302 * so ignore them. */
7304 status = create_directory(conn, req, smb_dname);
7306 if (!NT_STATUS_IS_OK(status)) {
7307 reply_nterror(req, status);
7311 /* Try and set any given EA. */
7313 status = set_ea(conn, NULL, smb_dname, ea_list);
7314 if (!NT_STATUS_IS_OK(status)) {
7315 reply_nterror(req, status);
7320 /* Realloc the parameter and data sizes */
7321 *pparams = (char *)SMB_REALLOC(*pparams,2);
7322 if(*pparams == NULL) {
7323 reply_nterror(req, NT_STATUS_NO_MEMORY);
7330 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7333 TALLOC_FREE(smb_dname);
7337 /****************************************************************************
7338 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7339 We don't actually do this - we just send a null response.
7340 ****************************************************************************/
7342 static void call_trans2findnotifyfirst(connection_struct *conn,
7343 struct smb_request *req,
7344 char **pparams, int total_params,
7345 char **ppdata, int total_data,
7346 unsigned int max_data_bytes)
7348 char *params = *pparams;
7351 if (total_params < 6) {
7352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7356 info_level = SVAL(params,4);
7357 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7359 switch (info_level) {
7364 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7368 /* Realloc the parameter and data sizes */
7369 *pparams = (char *)SMB_REALLOC(*pparams,6);
7370 if (*pparams == NULL) {
7371 reply_nterror(req, NT_STATUS_NO_MEMORY);
7376 SSVAL(params,0,fnf_handle);
7377 SSVAL(params,2,0); /* No changes */
7378 SSVAL(params,4,0); /* No EA errors */
7385 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7390 /****************************************************************************
7391 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7392 changes). Currently this does nothing.
7393 ****************************************************************************/
7395 static void call_trans2findnotifynext(connection_struct *conn,
7396 struct smb_request *req,
7397 char **pparams, int total_params,
7398 char **ppdata, int total_data,
7399 unsigned int max_data_bytes)
7401 char *params = *pparams;
7403 DEBUG(3,("call_trans2findnotifynext\n"));
7405 /* Realloc the parameter and data sizes */
7406 *pparams = (char *)SMB_REALLOC(*pparams,4);
7407 if (*pparams == NULL) {
7408 reply_nterror(req, NT_STATUS_NO_MEMORY);
7413 SSVAL(params,0,0); /* No changes */
7414 SSVAL(params,2,0); /* No EA errors */
7416 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7421 /****************************************************************************
7422 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7423 ****************************************************************************/
7425 static void call_trans2getdfsreferral(connection_struct *conn,
7426 struct smb_request *req,
7427 char **pparams, int total_params,
7428 char **ppdata, int total_data,
7429 unsigned int max_data_bytes)
7431 char *params = *pparams;
7432 char *pathname = NULL;
7434 int max_referral_level;
7435 NTSTATUS status = NT_STATUS_OK;
7436 TALLOC_CTX *ctx = talloc_tos();
7438 DEBUG(10,("call_trans2getdfsreferral\n"));
7440 if (total_params < 3) {
7441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7445 max_referral_level = SVAL(params,0);
7447 if(!lp_host_msdfs()) {
7448 reply_doserror(req, ERRDOS, ERRbadfunc);
7452 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7453 total_params - 2, STR_TERMINATE);
7455 reply_nterror(req, NT_STATUS_NOT_FOUND);
7458 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7459 ppdata,&status)) < 0) {
7460 reply_nterror(req, status);
7464 SSVAL(req->inbuf, smb_flg2,
7465 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7466 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7471 #define LMCAT_SPL 0x53
7472 #define LMFUNC_GETJOBID 0x60
7474 /****************************************************************************
7475 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7476 ****************************************************************************/
7478 static void call_trans2ioctl(connection_struct *conn,
7479 struct smb_request *req,
7480 char **pparams, int total_params,
7481 char **ppdata, int total_data,
7482 unsigned int max_data_bytes)
7484 char *pdata = *ppdata;
7485 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7487 /* check for an invalid fid before proceeding */
7490 reply_doserror(req, ERRDOS, ERRbadfid);
7494 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7495 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7496 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7497 if (*ppdata == NULL) {
7498 reply_nterror(req, NT_STATUS_NO_MEMORY);
7503 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7504 CAN ACCEPT THIS IN UNICODE. JRA. */
7506 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7507 srvstr_push(pdata, req->flags2, pdata + 2,
7508 global_myname(), 15,
7509 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7510 srvstr_push(pdata, req->flags2, pdata+18,
7511 lp_servicename(SNUM(conn)), 13,
7512 STR_ASCII|STR_TERMINATE); /* Service name */
7513 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7518 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7519 reply_doserror(req, ERRSRV, ERRerror);
7522 /****************************************************************************
7523 Reply to a SMBfindclose (stop trans2 directory search).
7524 ****************************************************************************/
7526 void reply_findclose(struct smb_request *req)
7530 START_PROFILE(SMBfindclose);
7533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7534 END_PROFILE(SMBfindclose);
7538 dptr_num = SVALS(req->vwv+0, 0);
7540 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7542 dptr_close(&dptr_num);
7544 reply_outbuf(req, 0, 0);
7546 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7548 END_PROFILE(SMBfindclose);
7552 /****************************************************************************
7553 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7554 ****************************************************************************/
7556 void reply_findnclose(struct smb_request *req)
7560 START_PROFILE(SMBfindnclose);
7563 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7564 END_PROFILE(SMBfindnclose);
7568 dptr_num = SVAL(req->vwv+0, 0);
7570 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7572 /* We never give out valid handles for a
7573 findnotifyfirst - so any dptr_num is ok here.
7576 reply_outbuf(req, 0, 0);
7578 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7580 END_PROFILE(SMBfindnclose);
7584 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7585 struct trans_state *state)
7587 if (Protocol >= PROTOCOL_NT1) {
7588 req->flags2 |= 0x40; /* IS_LONG_NAME */
7589 SSVAL(req->inbuf,smb_flg2,req->flags2);
7592 if (conn->encrypt_level == Required && !req->encrypted) {
7593 if (state->call != TRANSACT2_QFSINFO &&
7594 state->call != TRANSACT2_SETFSINFO) {
7595 DEBUG(0,("handle_trans2: encryption required "
7597 (unsigned int)state->call));
7598 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7603 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7605 /* Now we must call the relevant TRANS2 function */
7606 switch(state->call) {
7607 case TRANSACT2_OPEN:
7609 START_PROFILE(Trans2_open);
7610 call_trans2open(conn, req,
7611 &state->param, state->total_param,
7612 &state->data, state->total_data,
7613 state->max_data_return);
7614 END_PROFILE(Trans2_open);
7618 case TRANSACT2_FINDFIRST:
7620 START_PROFILE(Trans2_findfirst);
7621 call_trans2findfirst(conn, req,
7622 &state->param, state->total_param,
7623 &state->data, state->total_data,
7624 state->max_data_return);
7625 END_PROFILE(Trans2_findfirst);
7629 case TRANSACT2_FINDNEXT:
7631 START_PROFILE(Trans2_findnext);
7632 call_trans2findnext(conn, req,
7633 &state->param, state->total_param,
7634 &state->data, state->total_data,
7635 state->max_data_return);
7636 END_PROFILE(Trans2_findnext);
7640 case TRANSACT2_QFSINFO:
7642 START_PROFILE(Trans2_qfsinfo);
7643 call_trans2qfsinfo(conn, req,
7644 &state->param, state->total_param,
7645 &state->data, state->total_data,
7646 state->max_data_return);
7647 END_PROFILE(Trans2_qfsinfo);
7651 case TRANSACT2_SETFSINFO:
7653 START_PROFILE(Trans2_setfsinfo);
7654 call_trans2setfsinfo(conn, req,
7655 &state->param, state->total_param,
7656 &state->data, state->total_data,
7657 state->max_data_return);
7658 END_PROFILE(Trans2_setfsinfo);
7662 case TRANSACT2_QPATHINFO:
7663 case TRANSACT2_QFILEINFO:
7665 START_PROFILE(Trans2_qpathinfo);
7666 call_trans2qfilepathinfo(conn, req, state->call,
7667 &state->param, state->total_param,
7668 &state->data, state->total_data,
7669 state->max_data_return);
7670 END_PROFILE(Trans2_qpathinfo);
7674 case TRANSACT2_SETPATHINFO:
7675 case TRANSACT2_SETFILEINFO:
7677 START_PROFILE(Trans2_setpathinfo);
7678 call_trans2setfilepathinfo(conn, req, state->call,
7679 &state->param, state->total_param,
7680 &state->data, state->total_data,
7681 state->max_data_return);
7682 END_PROFILE(Trans2_setpathinfo);
7686 case TRANSACT2_FINDNOTIFYFIRST:
7688 START_PROFILE(Trans2_findnotifyfirst);
7689 call_trans2findnotifyfirst(conn, req,
7690 &state->param, state->total_param,
7691 &state->data, state->total_data,
7692 state->max_data_return);
7693 END_PROFILE(Trans2_findnotifyfirst);
7697 case TRANSACT2_FINDNOTIFYNEXT:
7699 START_PROFILE(Trans2_findnotifynext);
7700 call_trans2findnotifynext(conn, req,
7701 &state->param, state->total_param,
7702 &state->data, state->total_data,
7703 state->max_data_return);
7704 END_PROFILE(Trans2_findnotifynext);
7708 case TRANSACT2_MKDIR:
7710 START_PROFILE(Trans2_mkdir);
7711 call_trans2mkdir(conn, req,
7712 &state->param, state->total_param,
7713 &state->data, state->total_data,
7714 state->max_data_return);
7715 END_PROFILE(Trans2_mkdir);
7719 case TRANSACT2_GET_DFS_REFERRAL:
7721 START_PROFILE(Trans2_get_dfs_referral);
7722 call_trans2getdfsreferral(conn, req,
7723 &state->param, state->total_param,
7724 &state->data, state->total_data,
7725 state->max_data_return);
7726 END_PROFILE(Trans2_get_dfs_referral);
7730 case TRANSACT2_IOCTL:
7732 START_PROFILE(Trans2_ioctl);
7733 call_trans2ioctl(conn, req,
7734 &state->param, state->total_param,
7735 &state->data, state->total_data,
7736 state->max_data_return);
7737 END_PROFILE(Trans2_ioctl);
7742 /* Error in request */
7743 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7744 reply_doserror(req, ERRSRV,ERRerror);
7748 /****************************************************************************
7749 Reply to a SMBtrans2.
7750 ****************************************************************************/
7752 void reply_trans2(struct smb_request *req)
7754 connection_struct *conn = req->conn;
7759 unsigned int tran_call;
7760 struct trans_state *state;
7763 START_PROFILE(SMBtrans2);
7765 if (req->wct < 14) {
7766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7767 END_PROFILE(SMBtrans2);
7771 dsoff = SVAL(req->vwv+12, 0);
7772 dscnt = SVAL(req->vwv+11, 0);
7773 psoff = SVAL(req->vwv+10, 0);
7774 pscnt = SVAL(req->vwv+9, 0);
7775 tran_call = SVAL(req->vwv+14, 0);
7777 result = allow_new_trans(conn->pending_trans, req->mid);
7778 if (!NT_STATUS_IS_OK(result)) {
7779 DEBUG(2, ("Got invalid trans2 request: %s\n",
7780 nt_errstr(result)));
7781 reply_nterror(req, result);
7782 END_PROFILE(SMBtrans2);
7787 switch (tran_call) {
7788 /* List the allowed trans2 calls on IPC$ */
7789 case TRANSACT2_OPEN:
7790 case TRANSACT2_GET_DFS_REFERRAL:
7791 case TRANSACT2_QFILEINFO:
7792 case TRANSACT2_QFSINFO:
7793 case TRANSACT2_SETFSINFO:
7796 reply_doserror(req, ERRSRV, ERRaccess);
7797 END_PROFILE(SMBtrans2);
7802 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7803 DEBUG(0, ("talloc failed\n"));
7804 reply_nterror(req, NT_STATUS_NO_MEMORY);
7805 END_PROFILE(SMBtrans2);
7809 state->cmd = SMBtrans2;
7811 state->mid = req->mid;
7812 state->vuid = req->vuid;
7813 state->setup_count = SVAL(req->vwv+13, 0);
7814 state->setup = NULL;
7815 state->total_param = SVAL(req->vwv+0, 0);
7816 state->param = NULL;
7817 state->total_data = SVAL(req->vwv+1, 0);
7819 state->max_param_return = SVAL(req->vwv+2, 0);
7820 state->max_data_return = SVAL(req->vwv+3, 0);
7821 state->max_setup_return = SVAL(req->vwv+4, 0);
7822 state->close_on_completion = BITSETW(req->vwv+5, 0);
7823 state->one_way = BITSETW(req->vwv+5, 1);
7825 state->call = tran_call;
7827 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7828 is so as a sanity check */
7829 if (state->setup_count != 1) {
7831 * Need to have rc=0 for ioctl to get job id for OS/2.
7832 * Network printing will fail if function is not successful.
7833 * Similar function in reply.c will be used if protocol
7834 * is LANMAN1.0 instead of LM1.2X002.
7835 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7836 * outbuf doesn't have to be set(only job id is used).
7838 if ( (state->setup_count == 4)
7839 && (tran_call == TRANSACT2_IOCTL)
7840 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7841 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7842 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7844 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7845 DEBUG(2,("Transaction is %d\n",tran_call));
7847 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7848 END_PROFILE(SMBtrans2);
7853 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7856 if (state->total_data) {
7858 if (trans_oob(state->total_data, 0, dscnt)
7859 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7863 /* Can't use talloc here, the core routines do realloc on the
7864 * params and data. */
7865 state->data = (char *)SMB_MALLOC(state->total_data);
7866 if (state->data == NULL) {
7867 DEBUG(0,("reply_trans2: data malloc fail for %u "
7868 "bytes !\n", (unsigned int)state->total_data));
7870 reply_nterror(req, NT_STATUS_NO_MEMORY);
7871 END_PROFILE(SMBtrans2);
7875 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7878 if (state->total_param) {
7880 if (trans_oob(state->total_param, 0, pscnt)
7881 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7885 /* Can't use talloc here, the core routines do realloc on the
7886 * params and data. */
7887 state->param = (char *)SMB_MALLOC(state->total_param);
7888 if (state->param == NULL) {
7889 DEBUG(0,("reply_trans: param malloc fail for %u "
7890 "bytes !\n", (unsigned int)state->total_param));
7891 SAFE_FREE(state->data);
7893 reply_nterror(req, NT_STATUS_NO_MEMORY);
7894 END_PROFILE(SMBtrans2);
7898 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7901 state->received_data = dscnt;
7902 state->received_param = pscnt;
7904 if ((state->received_param == state->total_param) &&
7905 (state->received_data == state->total_data)) {
7907 handle_trans2(conn, req, state);
7909 SAFE_FREE(state->data);
7910 SAFE_FREE(state->param);
7912 END_PROFILE(SMBtrans2);
7916 DLIST_ADD(conn->pending_trans, state);
7918 /* We need to send an interim response then receive the rest
7919 of the parameter/data bytes */
7920 reply_outbuf(req, 0, 0);
7921 show_msg((char *)req->outbuf);
7922 END_PROFILE(SMBtrans2);
7927 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7928 SAFE_FREE(state->data);
7929 SAFE_FREE(state->param);
7931 END_PROFILE(SMBtrans2);
7932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7936 /****************************************************************************
7937 Reply to a SMBtranss2
7938 ****************************************************************************/
7940 void reply_transs2(struct smb_request *req)
7942 connection_struct *conn = req->conn;
7943 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7944 struct trans_state *state;
7946 START_PROFILE(SMBtranss2);
7948 show_msg((char *)req->inbuf);
7951 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7952 END_PROFILE(SMBtranss2);
7956 for (state = conn->pending_trans; state != NULL;
7957 state = state->next) {
7958 if (state->mid == req->mid) {
7963 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7964 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7965 END_PROFILE(SMBtranss2);
7969 /* Revise state->total_param and state->total_data in case they have
7970 changed downwards */
7972 if (SVAL(req->vwv+0, 0) < state->total_param)
7973 state->total_param = SVAL(req->vwv+0, 0);
7974 if (SVAL(req->vwv+1, 0) < state->total_data)
7975 state->total_data = SVAL(req->vwv+1, 0);
7977 pcnt = SVAL(req->vwv+2, 0);
7978 poff = SVAL(req->vwv+3, 0);
7979 pdisp = SVAL(req->vwv+4, 0);
7981 dcnt = SVAL(req->vwv+5, 0);
7982 doff = SVAL(req->vwv+6, 0);
7983 ddisp = SVAL(req->vwv+7, 0);
7985 state->received_param += pcnt;
7986 state->received_data += dcnt;
7988 if ((state->received_data > state->total_data) ||
7989 (state->received_param > state->total_param))
7993 if (trans_oob(state->total_param, pdisp, pcnt)
7994 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7997 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8001 if (trans_oob(state->total_data, ddisp, dcnt)
8002 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8005 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8008 if ((state->received_param < state->total_param) ||
8009 (state->received_data < state->total_data)) {
8010 END_PROFILE(SMBtranss2);
8014 handle_trans2(conn, req, state);
8016 DLIST_REMOVE(conn->pending_trans, state);
8017 SAFE_FREE(state->data);
8018 SAFE_FREE(state->param);
8021 END_PROFILE(SMBtranss2);
8026 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8027 DLIST_REMOVE(conn->pending_trans, state);
8028 SAFE_FREE(state->data);
8029 SAFE_FREE(state->param);
8031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8032 END_PROFILE(SMBtranss2);