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, const char *fname, struct ea_list *ea_list)
409 if (!lp_ea_support(SNUM(conn))) {
410 return NT_STATUS_EAS_NOT_SUPPORTED;
413 for (;ea_list; ea_list = ea_list->next) {
415 fstring unix_ea_name;
417 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
418 fstrcat(unix_ea_name, ea_list->ea.name);
420 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
422 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
424 if (samba_private_attr_name(unix_ea_name)) {
425 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
426 return NT_STATUS_ACCESS_DENIED;
429 if (ea_list->ea.value.length == 0) {
430 /* Remove the attribute. */
431 if (fsp && (fsp->fh->fd != -1)) {
432 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
433 unix_ea_name, fsp->fsp_name));
434 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
436 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
437 unix_ea_name, fname));
438 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
441 /* Removing a non existent attribute always succeeds. */
442 if (ret == -1 && errno == ENOATTR) {
443 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
449 if (fsp && (fsp->fh->fd != -1)) {
450 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
451 unix_ea_name, fsp->fsp_name));
452 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
453 ea_list->ea.value.data, ea_list->ea.value.length, 0);
455 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
456 unix_ea_name, fname));
457 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
458 ea_list->ea.value.data, ea_list->ea.value.length, 0);
464 if (errno == ENOTSUP) {
465 return NT_STATUS_EAS_NOT_SUPPORTED;
468 return map_nt_error_from_unix(errno);
474 /****************************************************************************
475 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
476 ****************************************************************************/
478 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
480 struct ea_list *ea_list_head = NULL;
481 size_t converted_size, offset = 0;
483 while (offset + 2 < data_size) {
484 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
485 unsigned int namelen = CVAL(pdata,offset);
487 offset++; /* Go past the namelen byte. */
489 /* integer wrap paranioa. */
490 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
491 (offset > data_size) || (namelen > data_size) ||
492 (offset + namelen >= data_size)) {
495 /* Ensure the name is null terminated. */
496 if (pdata[offset + namelen] != '\0') {
499 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
501 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
502 "failed: %s", strerror(errno)));
508 offset += (namelen + 1); /* Go past the name + terminating zero. */
509 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
510 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
516 /****************************************************************************
517 Read one EA list entry from the buffer.
518 ****************************************************************************/
520 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
522 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
524 unsigned int namelen;
525 size_t converted_size;
535 eal->ea.flags = CVAL(pdata,0);
536 namelen = CVAL(pdata,1);
537 val_len = SVAL(pdata,2);
539 if (4 + namelen + 1 + val_len > data_size) {
543 /* Ensure the name is null terminated. */
544 if (pdata[namelen + 4] != '\0') {
547 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
548 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
555 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
556 if (!eal->ea.value.data) {
560 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
562 /* Ensure we're null terminated just in case we print the value. */
563 eal->ea.value.data[val_len] = '\0';
564 /* But don't count the null. */
565 eal->ea.value.length--;
568 *pbytes_used = 4 + namelen + 1 + val_len;
571 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
572 dump_data(10, eal->ea.value.data, eal->ea.value.length);
577 /****************************************************************************
578 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
579 ****************************************************************************/
581 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
583 struct ea_list *ea_list_head = NULL;
585 size_t bytes_used = 0;
587 while (offset < data_size) {
588 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
594 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
595 offset += bytes_used;
601 /****************************************************************************
602 Count the total EA size needed.
603 ****************************************************************************/
605 static size_t ea_list_size(struct ea_list *ealist)
608 struct ea_list *listp;
611 for (listp = ealist; listp; listp = listp->next) {
612 push_ascii_fstring(dos_ea_name, listp->ea.name);
613 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
615 /* Add on 4 for total length. */
623 /****************************************************************************
624 Return a union of EA's from a file list and a list of names.
625 The TALLOC context for the two lists *MUST* be identical as we steal
626 memory from one list to add to another. JRA.
627 ****************************************************************************/
629 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
631 struct ea_list *nlistp, *flistp;
633 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
634 for (flistp = file_list; flistp; flistp = flistp->next) {
635 if (strequal(nlistp->ea.name, flistp->ea.name)) {
641 /* Copy the data from this entry. */
642 nlistp->ea.flags = flistp->ea.flags;
643 nlistp->ea.value = flistp->ea.value;
646 nlistp->ea.flags = 0;
647 ZERO_STRUCT(nlistp->ea.value);
651 *total_ea_len = ea_list_size(name_list);
655 /****************************************************************************
656 Send the required number of replies back.
657 We assume all fields other than the data fields are
658 set correctly for the type of call.
659 HACK ! Always assumes smb_setup field is zero.
660 ****************************************************************************/
662 void send_trans2_replies(connection_struct *conn,
663 struct smb_request *req,
670 /* As we are using a protocol > LANMAN1 then the max_send
671 variable must have been set in the sessetupX call.
672 This takes precedence over the max_xmit field in the
673 global struct. These different max_xmit variables should
674 be merged as this is now too confusing */
676 int data_to_send = datasize;
677 int params_to_send = paramsize;
679 const char *pp = params;
680 const char *pd = pdata;
681 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
682 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
683 int data_alignment_offset = 0;
684 bool overflow = False;
685 struct smbd_server_connection *sconn = smbd_server_conn;
686 int max_send = sconn->smb1.sessions.max_send;
688 /* Modify the data_to_send and datasize and set the error if
689 we're trying to send more than max_data_bytes. We still send
690 the part of the packet(s) that fit. Strange, but needed
693 if (max_data_bytes > 0 && datasize > max_data_bytes) {
694 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
695 max_data_bytes, datasize ));
696 datasize = data_to_send = max_data_bytes;
700 /* If there genuinely are no parameters or data to send just send the empty packet */
702 if(params_to_send == 0 && data_to_send == 0) {
703 reply_outbuf(req, 10, 0);
704 show_msg((char *)req->outbuf);
708 /* When sending params and data ensure that both are nicely aligned */
709 /* Only do this alignment when there is also data to send - else
710 can cause NT redirector problems. */
712 if (((params_to_send % 4) != 0) && (data_to_send != 0))
713 data_alignment_offset = 4 - (params_to_send % 4);
715 /* Space is bufsize minus Netbios over TCP header minus SMB header */
716 /* The alignment_offset is to align the param bytes on an even byte
717 boundary. NT 4.0 Beta needs this to work correctly. */
719 useable_space = max_send - (smb_size
722 + data_alignment_offset);
724 if (useable_space < 0) {
725 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
726 "= %d!!!", useable_space));
727 exit_server_cleanly("send_trans2_replies: Not enough space");
730 while (params_to_send || data_to_send) {
731 /* Calculate whether we will totally or partially fill this packet */
733 total_sent_thistime = params_to_send + data_to_send;
735 /* We can never send more than useable_space */
737 * Note that 'useable_space' does not include the alignment offsets,
738 * but we must include the alignment offsets in the calculation of
739 * the length of the data we send over the wire, as the alignment offsets
740 * are sent here. Fix from Marc_Jacobsen@hp.com.
743 total_sent_thistime = MIN(total_sent_thistime, useable_space);
745 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
746 + data_alignment_offset);
749 * We might have SMBtrans2s in req which was transferred to
750 * the outbuf, fix that.
752 SCVAL(req->outbuf, smb_com, SMBtrans2);
754 /* Set total params and data to be sent */
755 SSVAL(req->outbuf,smb_tprcnt,paramsize);
756 SSVAL(req->outbuf,smb_tdrcnt,datasize);
758 /* Calculate how many parameters and data we can fit into
759 * this packet. Parameters get precedence
762 params_sent_thistime = MIN(params_to_send,useable_space);
763 data_sent_thistime = useable_space - params_sent_thistime;
764 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
766 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
768 /* smb_proff is the offset from the start of the SMB header to the
769 parameter bytes, however the first 4 bytes of outbuf are
770 the Netbios over TCP header. Thus use smb_base() to subtract
771 them from the calculation */
773 SSVAL(req->outbuf,smb_proff,
774 ((smb_buf(req->outbuf)+alignment_offset)
775 - smb_base(req->outbuf)));
777 if(params_sent_thistime == 0)
778 SSVAL(req->outbuf,smb_prdisp,0);
780 /* Absolute displacement of param bytes sent in this packet */
781 SSVAL(req->outbuf,smb_prdisp,pp - params);
783 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
784 if(data_sent_thistime == 0) {
785 SSVAL(req->outbuf,smb_droff,0);
786 SSVAL(req->outbuf,smb_drdisp, 0);
788 /* The offset of the data bytes is the offset of the
789 parameter bytes plus the number of parameters being sent this time */
790 SSVAL(req->outbuf, smb_droff,
791 ((smb_buf(req->outbuf)+alignment_offset)
792 - smb_base(req->outbuf))
793 + params_sent_thistime + data_alignment_offset);
794 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
797 /* Initialize the padding for alignment */
799 if (alignment_offset != 0) {
800 memset(smb_buf(req->outbuf), 0, alignment_offset);
803 /* Copy the param bytes into the packet */
805 if(params_sent_thistime) {
806 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
807 params_sent_thistime);
810 /* Copy in the data bytes */
811 if(data_sent_thistime) {
812 if (data_alignment_offset != 0) {
813 memset((smb_buf(req->outbuf)+alignment_offset+
814 params_sent_thistime), 0,
815 data_alignment_offset);
817 memcpy(smb_buf(req->outbuf)+alignment_offset
818 +params_sent_thistime+data_alignment_offset,
819 pd,data_sent_thistime);
822 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
823 params_sent_thistime, data_sent_thistime, useable_space));
824 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
825 params_to_send, data_to_send, paramsize, datasize));
828 error_packet_set((char *)req->outbuf,
829 ERRDOS,ERRbufferoverflow,
830 STATUS_BUFFER_OVERFLOW,
834 /* Send the packet */
835 show_msg((char *)req->outbuf);
836 if (!srv_send_smb(smbd_server_fd(),
839 IS_CONN_ENCRYPTED(conn),
841 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
843 TALLOC_FREE(req->outbuf);
845 pp += params_sent_thistime;
846 pd += data_sent_thistime;
848 params_to_send -= params_sent_thistime;
849 data_to_send -= data_sent_thistime;
852 if(params_to_send < 0 || data_to_send < 0) {
853 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
854 params_to_send, data_to_send));
862 /****************************************************************************
863 Reply to a TRANSACT2_OPEN.
864 ****************************************************************************/
866 static void call_trans2open(connection_struct *conn,
867 struct smb_request *req,
868 char **pparams, int total_params,
869 char **ppdata, int total_data,
870 unsigned int max_data_bytes)
872 struct smb_filename *smb_fname = NULL;
873 char *params = *pparams;
874 char *pdata = *ppdata;
879 bool return_additional_info;
892 struct ea_list *ea_list = NULL;
897 uint32 create_disposition;
898 uint32 create_options = 0;
899 TALLOC_CTX *ctx = talloc_tos();
902 * Ensure we have enough parameters to perform the operation.
905 if (total_params < 29) {
906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
910 flags = SVAL(params, 0);
911 deny_mode = SVAL(params, 2);
912 open_attr = SVAL(params,6);
913 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
914 if (oplock_request) {
915 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
919 return_additional_info = BITSETW(params,0);
920 open_sattr = SVAL(params, 4);
921 open_time = make_unix_date3(params+8);
923 open_ofun = SVAL(params,12);
924 open_size = IVAL(params,14);
928 reply_doserror(req, ERRSRV, ERRaccess);
932 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
933 total_params - 28, STR_TERMINATE,
935 if (!NT_STATUS_IS_OK(status)) {
936 reply_nterror(req, status);
940 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
941 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
942 (unsigned int)open_ofun, open_size));
944 status = filename_convert(ctx,
946 req->flags2 & FLAGS2_DFS_PATHNAMES,
950 if (!NT_STATUS_IS_OK(status)) {
951 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
953 NT_STATUS_PATH_NOT_COVERED,
957 reply_nterror(req, status);
961 if (open_ofun == 0) {
962 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
966 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
971 reply_doserror(req, ERRDOS, ERRbadaccess);
975 /* Any data in this call is an EA list. */
976 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
977 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
981 if (total_data != 4) {
982 if (total_data < 10) {
983 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
987 if (IVAL(pdata,0) > total_data) {
988 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
989 IVAL(pdata,0), (unsigned int)total_data));
990 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
994 ea_list = read_ea_list(talloc_tos(), pdata + 4,
997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1000 } else if (IVAL(pdata,0) != 4) {
1001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1005 status = SMB_VFS_CREATE_FILE(
1008 0, /* root_dir_fid */
1009 smb_fname, /* fname */
1010 access_mask, /* access_mask */
1011 share_mode, /* share_access */
1012 create_disposition, /* create_disposition*/
1013 create_options, /* create_options */
1014 open_attr, /* file_attributes */
1015 oplock_request, /* oplock_request */
1016 open_size, /* allocation_size */
1018 ea_list, /* ea_list */
1020 &smb_action); /* psbuf */
1022 if (!NT_STATUS_IS_OK(status)) {
1023 if (open_was_deferred(req->mid)) {
1024 /* We have re-scheduled this call. */
1027 reply_openerror(req, status);
1031 size = get_file_size_stat(&smb_fname->st);
1032 fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st);
1033 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1034 inode = smb_fname->st.st_ex_ino;
1036 close_file(req, fsp, ERROR_CLOSE);
1037 reply_doserror(req, ERRDOS,ERRnoaccess);
1041 /* Realloc the size of parameters and data we will return */
1042 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1043 if(*pparams == NULL ) {
1044 reply_nterror(req, NT_STATUS_NO_MEMORY);
1049 SSVAL(params,0,fsp->fnum);
1050 SSVAL(params,2,fattr);
1051 srv_put_dos_date2(params,4, mtime);
1052 SIVAL(params,8, (uint32)size);
1053 SSVAL(params,12,deny_mode);
1054 SSVAL(params,14,0); /* open_type - file or directory. */
1055 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1057 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1058 smb_action |= EXTENDED_OPLOCK_GRANTED;
1061 SSVAL(params,18,smb_action);
1064 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1066 SIVAL(params,20,inode);
1067 SSVAL(params,24,0); /* Padding. */
1069 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1070 SIVAL(params, 26, ea_size);
1072 SIVAL(params, 26, 0);
1075 /* Send the required number of replies */
1076 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1078 TALLOC_FREE(smb_fname);
1081 /*********************************************************
1082 Routine to check if a given string matches exactly.
1083 as a special case a mask of "." does NOT match. That
1084 is required for correct wildcard semantics
1085 Case can be significant or not.
1086 **********************************************************/
1088 static bool exact_match(connection_struct *conn,
1092 if (mask[0] == '.' && mask[1] == 0)
1094 if (dptr_has_wild(conn->dirptr)) {
1097 if (conn->case_sensitive)
1098 return strcmp(str,mask)==0;
1100 return StrCaseCmp(str,mask) == 0;
1103 /****************************************************************************
1104 Return the filetype for UNIX extensions.
1105 ****************************************************************************/
1107 static uint32 unix_filetype(mode_t mode)
1110 return UNIX_TYPE_FILE;
1111 else if(S_ISDIR(mode))
1112 return UNIX_TYPE_DIR;
1114 else if(S_ISLNK(mode))
1115 return UNIX_TYPE_SYMLINK;
1118 else if(S_ISCHR(mode))
1119 return UNIX_TYPE_CHARDEV;
1122 else if(S_ISBLK(mode))
1123 return UNIX_TYPE_BLKDEV;
1126 else if(S_ISFIFO(mode))
1127 return UNIX_TYPE_FIFO;
1130 else if(S_ISSOCK(mode))
1131 return UNIX_TYPE_SOCKET;
1134 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1135 return UNIX_TYPE_UNKNOWN;
1138 /****************************************************************************
1139 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1140 ****************************************************************************/
1142 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1144 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1145 SMB_STRUCT_STAT *psbuf,
1147 enum perm_type ptype,
1152 if (perms == SMB_MODE_NO_CHANGE) {
1153 if (!VALID_STAT(*psbuf)) {
1154 return NT_STATUS_INVALID_PARAMETER;
1156 *ret_perms = psbuf->st_ex_mode;
1157 return NT_STATUS_OK;
1161 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1162 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1163 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1164 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1165 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1166 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1167 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1168 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1169 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1171 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1174 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1177 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1182 /* Apply mode mask */
1183 ret &= lp_create_mask(SNUM(conn));
1184 /* Add in force bits */
1185 ret |= lp_force_create_mode(SNUM(conn));
1188 ret &= lp_dir_mask(SNUM(conn));
1189 /* Add in force bits */
1190 ret |= lp_force_dir_mode(SNUM(conn));
1192 case PERM_EXISTING_FILE:
1193 /* Apply mode mask */
1194 ret &= lp_security_mask(SNUM(conn));
1195 /* Add in force bits */
1196 ret |= lp_force_security_mode(SNUM(conn));
1198 case PERM_EXISTING_DIR:
1199 /* Apply mode mask */
1200 ret &= lp_dir_security_mask(SNUM(conn));
1201 /* Add in force bits */
1202 ret |= lp_force_dir_security_mode(SNUM(conn));
1207 return NT_STATUS_OK;
1210 /****************************************************************************
1211 Needed to show the msdfs symlinks as directories. Modifies psbuf
1212 to be a directory if it's a msdfs link.
1213 ****************************************************************************/
1215 static bool check_msdfs_link(connection_struct *conn,
1216 const char *pathname,
1217 SMB_STRUCT_STAT *psbuf)
1219 int saved_errno = errno;
1220 if(lp_host_msdfs() &&
1221 lp_msdfs_root(SNUM(conn)) &&
1222 is_msdfs_link(conn, pathname, psbuf)) {
1224 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1227 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1228 errno = saved_errno;
1231 errno = saved_errno;
1236 /****************************************************************************
1237 Get a level dependent lanman2 dir entry.
1238 ****************************************************************************/
1240 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1241 connection_struct *conn,
1243 const char *path_mask,
1246 int requires_resume_key,
1252 int space_remaining,
1254 bool *got_exact_match,
1255 int *last_entry_off,
1256 struct ea_list *name_list)
1260 SMB_STRUCT_STAT sbuf;
1261 const char *mask = NULL;
1262 char *pathreal = NULL;
1264 char *p, *q, *pdata = *ppdata;
1268 SMB_OFF_T file_size = 0;
1269 uint64_t allocation_size = 0;
1271 struct timespec mdate_ts, adate_ts, create_date_ts;
1272 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1274 char *last_entry_ptr;
1276 uint32 nt_extmode; /* Used for NT connections instead of mode */
1277 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1278 bool check_mangled_names = lp_manglednames(conn->params);
1279 char mangled_name[13]; /* mangled 8.3 name. */
1281 *out_of_space = False;
1282 *got_exact_match = False;
1284 ZERO_STRUCT(mdate_ts);
1285 ZERO_STRUCT(adate_ts);
1286 ZERO_STRUCT(create_date_ts);
1288 if (!conn->dirptr) {
1292 p = strrchr_m(path_mask,'/');
1295 mask = talloc_strdup(ctx,"*.*");
1305 bool ms_dfs_link = False;
1307 /* Needed if we run out of space */
1308 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1309 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1312 * Due to bugs in NT client redirectors we are not using
1313 * resume keys any more - set them to zero.
1314 * Check out the related comments in findfirst/findnext.
1320 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1321 (long)conn->dirptr,curr_dirpos));
1328 * fname may get mangled, dname is never mangled.
1329 * Whenever we're accessing the filesystem we use
1330 * pathreal which is composed from dname.
1336 /* Mangle fname if it's an illegal name. */
1337 if (mangle_must_mangle(dname,conn->params)) {
1338 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1340 continue; /* Error - couldn't mangle. */
1342 fname = talloc_strdup(ctx, mangled_name);
1348 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1349 got_match = mask_match(fname, mask, conn->case_sensitive);
1352 if(!got_match && check_mangled_names &&
1353 !mangle_is_8_3(fname, False, conn->params)) {
1355 * It turns out that NT matches wildcards against
1356 * both long *and* short names. This may explain some
1357 * of the wildcard wierdness from old DOS clients
1358 * that some people have been seeing.... JRA.
1360 /* Force the mangling into 8.3. */
1361 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1363 continue; /* Error - couldn't mangle. */
1366 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1367 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1372 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1374 if (dont_descend && !isdots) {
1381 pathreal = talloc_asprintf(ctx,
1386 pathreal = talloc_asprintf(ctx,
1397 if (INFO_LEVEL_IS_UNIX(info_level)) {
1398 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1399 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1400 pathreal,strerror(errno)));
1401 TALLOC_FREE(pathreal);
1405 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1406 /* Needed to show the msdfs symlinks as
1409 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1411 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1412 pathreal,strerror(errno)));
1413 TALLOC_FREE(pathreal);
1420 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1422 mode = dos_mode(conn,pathreal,&sbuf);
1425 if (!dir_check_ftype(conn,mode,dirtype)) {
1426 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1427 TALLOC_FREE(pathreal);
1432 if (!(mode & aDIR)) {
1433 file_size = get_file_size_stat(&sbuf);
1435 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1437 mdate_ts = sbuf.st_ex_mtime;
1438 adate_ts = sbuf.st_ex_atime;
1439 create_date_ts = sbuf.st_ex_btime;
1441 if (ask_sharemode) {
1442 struct timespec write_time_ts;
1443 struct file_id fileid;
1445 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1446 get_file_infos(fileid, NULL, &write_time_ts);
1447 if (!null_timespec(write_time_ts)) {
1448 mdate_ts = write_time_ts;
1452 if (lp_dos_filetime_resolution(SNUM(conn))) {
1453 dos_filetime_timespec(&create_date_ts);
1454 dos_filetime_timespec(&mdate_ts);
1455 dos_filetime_timespec(&adate_ts);
1458 create_date = convert_timespec_to_time_t(create_date_ts);
1459 mdate = convert_timespec_to_time_t(mdate_ts);
1460 adate = convert_timespec_to_time_t(adate_ts);
1462 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1467 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1477 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1479 switch (info_level) {
1480 case SMB_FIND_INFO_STANDARD:
1481 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1482 if(requires_resume_key) {
1486 srv_put_dos_date2(p,0,create_date);
1487 srv_put_dos_date2(p,4,adate);
1488 srv_put_dos_date2(p,8,mdate);
1489 SIVAL(p,12,(uint32)file_size);
1490 SIVAL(p,16,(uint32)allocation_size);
1494 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1495 p += ucs2_align(base_data, p, 0);
1497 len = srvstr_push(base_data, flags2, p,
1498 fname, PTR_DIFF(end_data, p),
1500 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1502 SCVAL(nameptr, -1, len - 2);
1504 SCVAL(nameptr, -1, 0);
1508 SCVAL(nameptr, -1, len - 1);
1510 SCVAL(nameptr, -1, 0);
1516 case SMB_FIND_EA_SIZE:
1517 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1518 if(requires_resume_key) {
1522 srv_put_dos_date2(p,0,create_date);
1523 srv_put_dos_date2(p,4,adate);
1524 srv_put_dos_date2(p,8,mdate);
1525 SIVAL(p,12,(uint32)file_size);
1526 SIVAL(p,16,(uint32)allocation_size);
1529 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1530 SIVAL(p,22,ea_size); /* Extended attributes */
1534 len = srvstr_push(base_data, flags2,
1535 p, fname, PTR_DIFF(end_data, p),
1536 STR_TERMINATE | STR_NOALIGN);
1537 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1550 SCVAL(nameptr,0,len);
1552 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1555 case SMB_FIND_EA_LIST:
1557 struct ea_list *file_list = NULL;
1560 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1564 if(requires_resume_key) {
1568 srv_put_dos_date2(p,0,create_date);
1569 srv_put_dos_date2(p,4,adate);
1570 srv_put_dos_date2(p,8,mdate);
1571 SIVAL(p,12,(uint32)file_size);
1572 SIVAL(p,16,(uint32)allocation_size);
1574 p += 22; /* p now points to the EA area. */
1576 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1577 name_list = ea_list_union(name_list, file_list, &ea_len);
1579 /* We need to determine if this entry will fit in the space available. */
1580 /* Max string size is 255 bytes. */
1581 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1582 /* Move the dirptr back to prev_dirpos */
1583 dptr_SeekDir(conn->dirptr, prev_dirpos);
1584 *out_of_space = True;
1585 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1586 return False; /* Not finished - just out of space */
1589 /* Push the ea_data followed by the name. */
1590 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1592 len = srvstr_push(base_data, flags2,
1593 p + 1, fname, PTR_DIFF(end_data, p+1),
1594 STR_TERMINATE | STR_NOALIGN);
1595 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1608 SCVAL(nameptr,0,len);
1610 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1614 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1615 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1616 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1618 SIVAL(p,0,reskey); p += 4;
1619 put_long_date_timespec(p,create_date_ts); p += 8;
1620 put_long_date_timespec(p,adate_ts); p += 8;
1621 put_long_date_timespec(p,mdate_ts); p += 8;
1622 put_long_date_timespec(p,mdate_ts); p += 8;
1623 SOFF_T(p,0,file_size); p += 8;
1624 SOFF_T(p,0,allocation_size); p += 8;
1625 SIVAL(p,0,nt_extmode); p += 4;
1626 q = p; p += 4; /* q is placeholder for name length. */
1628 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1629 SIVAL(p,0,ea_size); /* Extended attributes */
1632 /* Clear the short name buffer. This is
1633 * IMPORTANT as not doing so will trigger
1634 * a Win2k client bug. JRA.
1636 if (!was_8_3 && check_mangled_names) {
1637 if (!name_to_8_3(fname,mangled_name,True,
1639 /* Error - mangle failed ! */
1640 memset(mangled_name,'\0',12);
1642 mangled_name[12] = 0;
1643 len = srvstr_push(base_data, flags2,
1644 p+2, mangled_name, 24,
1645 STR_UPPER|STR_UNICODE);
1647 memset(p + 2 + len,'\0',24 - len);
1654 len = srvstr_push(base_data, flags2, p,
1655 fname, PTR_DIFF(end_data, p),
1656 STR_TERMINATE_ASCII);
1659 SIVAL(p,0,0); /* Ensure any padding is null. */
1660 len = PTR_DIFF(p, pdata);
1661 len = (len + 3) & ~3;
1666 case SMB_FIND_FILE_DIRECTORY_INFO:
1667 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1669 SIVAL(p,0,reskey); p += 4;
1670 put_long_date_timespec(p,create_date_ts); p += 8;
1671 put_long_date_timespec(p,adate_ts); p += 8;
1672 put_long_date_timespec(p,mdate_ts); p += 8;
1673 put_long_date_timespec(p,mdate_ts); p += 8;
1674 SOFF_T(p,0,file_size); p += 8;
1675 SOFF_T(p,0,allocation_size); p += 8;
1676 SIVAL(p,0,nt_extmode); p += 4;
1677 len = srvstr_push(base_data, flags2,
1678 p + 4, fname, PTR_DIFF(end_data, p+4),
1679 STR_TERMINATE_ASCII);
1682 SIVAL(p,0,0); /* Ensure any padding is null. */
1683 len = PTR_DIFF(p, pdata);
1684 len = (len + 3) & ~3;
1689 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1690 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1692 SIVAL(p,0,reskey); p += 4;
1693 put_long_date_timespec(p,create_date_ts); p += 8;
1694 put_long_date_timespec(p,adate_ts); p += 8;
1695 put_long_date_timespec(p,mdate_ts); p += 8;
1696 put_long_date_timespec(p,mdate_ts); p += 8;
1697 SOFF_T(p,0,file_size); p += 8;
1698 SOFF_T(p,0,allocation_size); p += 8;
1699 SIVAL(p,0,nt_extmode); p += 4;
1700 q = p; p += 4; /* q is placeholder for name length. */
1702 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1703 SIVAL(p,0,ea_size); /* Extended attributes */
1706 len = srvstr_push(base_data, flags2, p,
1707 fname, PTR_DIFF(end_data, p),
1708 STR_TERMINATE_ASCII);
1712 SIVAL(p,0,0); /* Ensure any padding is null. */
1713 len = PTR_DIFF(p, pdata);
1714 len = (len + 3) & ~3;
1719 case SMB_FIND_FILE_NAMES_INFO:
1720 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1722 SIVAL(p,0,reskey); p += 4;
1724 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1725 acl on a dir (tridge) */
1726 len = srvstr_push(base_data, flags2, p,
1727 fname, PTR_DIFF(end_data, p),
1728 STR_TERMINATE_ASCII);
1731 SIVAL(p,0,0); /* Ensure any padding is null. */
1732 len = PTR_DIFF(p, pdata);
1733 len = (len + 3) & ~3;
1738 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1739 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1741 SIVAL(p,0,reskey); p += 4;
1742 put_long_date_timespec(p,create_date_ts); p += 8;
1743 put_long_date_timespec(p,adate_ts); p += 8;
1744 put_long_date_timespec(p,mdate_ts); p += 8;
1745 put_long_date_timespec(p,mdate_ts); p += 8;
1746 SOFF_T(p,0,file_size); p += 8;
1747 SOFF_T(p,0,allocation_size); p += 8;
1748 SIVAL(p,0,nt_extmode); p += 4;
1749 q = p; p += 4; /* q is placeholder for name length. */
1751 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1752 SIVAL(p,0,ea_size); /* Extended attributes */
1755 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1756 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1757 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1758 len = srvstr_push(base_data, flags2, p,
1759 fname, PTR_DIFF(end_data, p),
1760 STR_TERMINATE_ASCII);
1763 SIVAL(p,0,0); /* Ensure any padding is null. */
1764 len = PTR_DIFF(p, pdata);
1765 len = (len + 3) & ~3;
1770 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1771 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1772 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1774 SIVAL(p,0,reskey); p += 4;
1775 put_long_date_timespec(p,create_date_ts); p += 8;
1776 put_long_date_timespec(p,adate_ts); p += 8;
1777 put_long_date_timespec(p,mdate_ts); p += 8;
1778 put_long_date_timespec(p,mdate_ts); p += 8;
1779 SOFF_T(p,0,file_size); p += 8;
1780 SOFF_T(p,0,allocation_size); p += 8;
1781 SIVAL(p,0,nt_extmode); p += 4;
1782 q = p; p += 4; /* q is placeholder for name length */
1784 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1785 SIVAL(p,0,ea_size); /* Extended attributes */
1788 /* Clear the short name buffer. This is
1789 * IMPORTANT as not doing so will trigger
1790 * a Win2k client bug. JRA.
1792 if (!was_8_3 && check_mangled_names) {
1793 if (!name_to_8_3(fname,mangled_name,True,
1795 /* Error - mangle failed ! */
1796 memset(mangled_name,'\0',12);
1798 mangled_name[12] = 0;
1799 len = srvstr_push(base_data, flags2,
1800 p+2, mangled_name, 24,
1801 STR_UPPER|STR_UNICODE);
1804 memset(p + 2 + len,'\0',24 - len);
1811 SSVAL(p,0,0); p += 2; /* Reserved ? */
1812 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1813 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1814 len = srvstr_push(base_data, flags2, p,
1815 fname, PTR_DIFF(end_data, p),
1816 STR_TERMINATE_ASCII);
1819 SIVAL(p,0,0); /* Ensure any padding is null. */
1820 len = PTR_DIFF(p, pdata);
1821 len = (len + 3) & ~3;
1826 /* CIFS UNIX Extension. */
1828 case SMB_FIND_FILE_UNIX:
1829 case SMB_FIND_FILE_UNIX_INFO2:
1831 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1833 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1835 if (info_level == SMB_FIND_FILE_UNIX) {
1836 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1837 p = store_file_unix_basic(conn, p,
1839 len = srvstr_push(base_data, flags2, p,
1840 fname, PTR_DIFF(end_data, p),
1843 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1844 p = store_file_unix_basic_info2(conn, p,
1848 len = srvstr_push(base_data, flags2, p, fname,
1849 PTR_DIFF(end_data, p), 0);
1850 SIVAL(nameptr, 0, len);
1854 SIVAL(p,0,0); /* Ensure any padding is null. */
1856 len = PTR_DIFF(p, pdata);
1857 len = (len + 3) & ~3;
1858 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1860 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1870 if (PTR_DIFF(p,pdata) > space_remaining) {
1871 /* Move the dirptr back to prev_dirpos */
1872 dptr_SeekDir(conn->dirptr, prev_dirpos);
1873 *out_of_space = True;
1874 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1875 return False; /* Not finished - just out of space */
1878 /* Setup the last entry pointer, as an offset from base_data */
1879 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1880 /* Advance the data pointer to the next slot */
1886 /****************************************************************************
1887 Reply to a TRANS2_FINDFIRST.
1888 ****************************************************************************/
1890 static void call_trans2findfirst(connection_struct *conn,
1891 struct smb_request *req,
1892 char **pparams, int total_params,
1893 char **ppdata, int total_data,
1894 unsigned int max_data_bytes)
1896 /* We must be careful here that we don't return more than the
1897 allowed number of data bytes. If this means returning fewer than
1898 maxentries then so be it. We assume that the redirector has
1899 enough room for the fixed number of parameter bytes it has
1901 struct smb_filename *smb_dname = NULL;
1902 char *params = *pparams;
1903 char *pdata = *ppdata;
1907 uint16 findfirst_flags;
1908 bool close_after_first;
1910 bool requires_resume_key;
1912 char *directory = NULL;
1915 int last_entry_off=0;
1919 bool finished = False;
1920 bool dont_descend = False;
1921 bool out_of_space = False;
1922 int space_remaining;
1923 bool mask_contains_wcard = False;
1924 struct ea_list *ea_list = NULL;
1925 NTSTATUS ntstatus = NT_STATUS_OK;
1926 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1927 TALLOC_CTX *ctx = talloc_tos();
1929 if (total_params < 13) {
1930 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1934 dirtype = SVAL(params,0);
1935 maxentries = SVAL(params,2);
1936 findfirst_flags = SVAL(params,4);
1937 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1938 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1939 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1940 info_level = SVAL(params,6);
1942 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1943 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1944 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1945 info_level, max_data_bytes));
1948 /* W2K3 seems to treat zero as 1. */
1952 switch (info_level) {
1953 case SMB_FIND_INFO_STANDARD:
1954 case SMB_FIND_EA_SIZE:
1955 case SMB_FIND_EA_LIST:
1956 case SMB_FIND_FILE_DIRECTORY_INFO:
1957 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1958 case SMB_FIND_FILE_NAMES_INFO:
1959 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1960 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1961 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1963 case SMB_FIND_FILE_UNIX:
1964 case SMB_FIND_FILE_UNIX_INFO2:
1965 /* Always use filesystem for UNIX mtime query. */
1966 ask_sharemode = false;
1967 if (!lp_unix_extensions()) {
1968 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1973 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1977 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1978 params+12, total_params - 12,
1979 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1980 if (!NT_STATUS_IS_OK(ntstatus)) {
1981 reply_nterror(req, ntstatus);
1985 ntstatus = resolve_dfspath_wcard(ctx, conn,
1986 req->flags2 & FLAGS2_DFS_PATHNAMES,
1989 &mask_contains_wcard);
1990 if (!NT_STATUS_IS_OK(ntstatus)) {
1991 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1992 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1993 ERRSRV, ERRbadpath);
1996 reply_nterror(req, ntstatus);
2000 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2001 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2002 if (!NT_STATUS_IS_OK(ntstatus)) {
2003 reply_nterror(req, ntstatus);
2007 mask = smb_dname->original_lcomp;
2009 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2010 TALLOC_FREE(smb_dname);
2011 if (!NT_STATUS_IS_OK(ntstatus)) {
2012 reply_nterror(req, ntstatus);
2016 ntstatus = check_name(conn, directory);
2017 if (!NT_STATUS_IS_OK(ntstatus)) {
2018 reply_nterror(req, ntstatus);
2022 p = strrchr_m(directory,'/');
2024 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2025 if((directory[0] == '.') && (directory[1] == '\0')) {
2026 mask = talloc_strdup(ctx,"*");
2028 reply_nterror(req, NT_STATUS_NO_MEMORY);
2031 mask_contains_wcard = True;
2033 directory = talloc_strdup(talloc_tos(), "./");
2035 reply_nterror(req, NT_STATUS_NO_MEMORY);
2042 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2044 if (info_level == SMB_FIND_EA_LIST) {
2047 if (total_data < 4) {
2048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2052 ea_size = IVAL(pdata,0);
2053 if (ea_size != total_data) {
2054 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2055 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2060 if (!lp_ea_support(SNUM(conn))) {
2061 reply_doserror(req, ERRDOS, ERReasnotsupported);
2065 /* Pull out the list of names. */
2066 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2073 *ppdata = (char *)SMB_REALLOC(
2074 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2075 if(*ppdata == NULL ) {
2076 reply_nterror(req, NT_STATUS_NO_MEMORY);
2080 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2082 /* Realloc the params space */
2083 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2084 if (*pparams == NULL) {
2085 reply_nterror(req, NT_STATUS_NO_MEMORY);
2090 /* Save the wildcard match and attribs we are using on this directory -
2091 needed as lanman2 assumes these are being saved between calls */
2093 ntstatus = dptr_create(conn,
2099 mask_contains_wcard,
2103 if (!NT_STATUS_IS_OK(ntstatus)) {
2104 reply_nterror(req, ntstatus);
2108 dptr_num = dptr_dnum(conn->dirptr);
2109 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2111 /* Initialize per TRANS2_FIND_FIRST operation data */
2112 dptr_init_search_op(conn->dirptr);
2114 /* We don't need to check for VOL here as this is returned by
2115 a different TRANS2 call. */
2117 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2118 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2119 dont_descend = True;
2122 space_remaining = max_data_bytes;
2123 out_of_space = False;
2125 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2126 bool got_exact_match = False;
2128 /* this is a heuristic to avoid seeking the dirptr except when
2129 absolutely necessary. It allows for a filename of about 40 chars */
2130 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2131 out_of_space = True;
2134 finished = !get_lanman2_dir_entry(ctx,
2137 mask,dirtype,info_level,
2138 requires_resume_key,dont_descend,
2141 space_remaining, &out_of_space,
2143 &last_entry_off, ea_list);
2146 if (finished && out_of_space)
2149 if (!finished && !out_of_space)
2153 * As an optimisation if we know we aren't looking
2154 * for a wildcard name (ie. the name matches the wildcard exactly)
2155 * then we can finish on any (first) match.
2156 * This speeds up large directory searches. JRA.
2162 /* Ensure space_remaining never goes -ve. */
2163 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2164 space_remaining = 0;
2165 out_of_space = true;
2167 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2171 /* Check if we can close the dirptr */
2172 if(close_after_first || (finished && close_if_end)) {
2173 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2174 dptr_close(&dptr_num);
2178 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2179 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2180 * the protocol level is less than NT1. Tested with smbclient. JRA.
2181 * This should fix the OS/2 client bug #2335.
2184 if(numentries == 0) {
2185 dptr_close(&dptr_num);
2186 if (Protocol < PROTOCOL_NT1) {
2187 reply_doserror(req, ERRDOS, ERRnofiles);
2190 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2191 ERRDOS, ERRbadfile);
2196 /* At this point pdata points to numentries directory entries. */
2198 /* Set up the return parameter block */
2199 SSVAL(params,0,dptr_num);
2200 SSVAL(params,2,numentries);
2201 SSVAL(params,4,finished);
2202 SSVAL(params,6,0); /* Never an EA error */
2203 SSVAL(params,8,last_entry_off);
2205 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2208 if ((! *directory) && dptr_path(dptr_num)) {
2209 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2211 reply_nterror(req, NT_STATUS_NO_MEMORY);
2215 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2216 smb_fn_name(req->cmd),
2217 mask, directory, dirtype, numentries ) );
2220 * Force a name mangle here to ensure that the
2221 * mask as an 8.3 name is top of the mangled cache.
2222 * The reasons for this are subtle. Don't remove
2223 * this code unless you know what you are doing
2224 * (see PR#13758). JRA.
2227 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2228 char mangled_name[13];
2229 name_to_8_3(mask, mangled_name, True, conn->params);
2235 /****************************************************************************
2236 Reply to a TRANS2_FINDNEXT.
2237 ****************************************************************************/
2239 static void call_trans2findnext(connection_struct *conn,
2240 struct smb_request *req,
2241 char **pparams, int total_params,
2242 char **ppdata, int total_data,
2243 unsigned int max_data_bytes)
2245 /* We must be careful here that we don't return more than the
2246 allowed number of data bytes. If this means returning fewer than
2247 maxentries then so be it. We assume that the redirector has
2248 enough room for the fixed number of parameter bytes it has
2250 char *params = *pparams;
2251 char *pdata = *ppdata;
2257 uint16 findnext_flags;
2258 bool close_after_request;
2260 bool requires_resume_key;
2262 bool mask_contains_wcard = False;
2263 char *resume_name = NULL;
2264 const char *mask = NULL;
2265 const char *directory = NULL;
2269 int i, last_entry_off=0;
2270 bool finished = False;
2271 bool dont_descend = False;
2272 bool out_of_space = False;
2273 int space_remaining;
2274 struct ea_list *ea_list = NULL;
2275 NTSTATUS ntstatus = NT_STATUS_OK;
2276 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2277 TALLOC_CTX *ctx = talloc_tos();
2279 if (total_params < 13) {
2280 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2284 dptr_num = SVAL(params,0);
2285 maxentries = SVAL(params,2);
2286 info_level = SVAL(params,4);
2287 resume_key = IVAL(params,6);
2288 findnext_flags = SVAL(params,10);
2289 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2290 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2291 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2292 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2294 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2296 total_params - 12, STR_TERMINATE, &ntstatus,
2297 &mask_contains_wcard);
2298 if (!NT_STATUS_IS_OK(ntstatus)) {
2299 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2300 complain (it thinks we're asking for the directory above the shared
2301 path or an invalid name). Catch this as the resume name is only compared, never used in
2302 a file access. JRA. */
2303 srvstr_pull_talloc(ctx, params, req->flags2,
2304 &resume_name, params+12,
2308 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2309 reply_nterror(req, ntstatus);
2314 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2315 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2316 resume_key = %d resume name = %s continue=%d level = %d\n",
2317 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2318 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2321 /* W2K3 seems to treat zero as 1. */
2325 switch (info_level) {
2326 case SMB_FIND_INFO_STANDARD:
2327 case SMB_FIND_EA_SIZE:
2328 case SMB_FIND_EA_LIST:
2329 case SMB_FIND_FILE_DIRECTORY_INFO:
2330 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2331 case SMB_FIND_FILE_NAMES_INFO:
2332 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2333 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2334 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2336 case SMB_FIND_FILE_UNIX:
2337 case SMB_FIND_FILE_UNIX_INFO2:
2338 /* Always use filesystem for UNIX mtime query. */
2339 ask_sharemode = false;
2340 if (!lp_unix_extensions()) {
2341 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2346 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2350 if (info_level == SMB_FIND_EA_LIST) {
2353 if (total_data < 4) {
2354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2358 ea_size = IVAL(pdata,0);
2359 if (ea_size != total_data) {
2360 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2361 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2366 if (!lp_ea_support(SNUM(conn))) {
2367 reply_doserror(req, ERRDOS, ERReasnotsupported);
2371 /* Pull out the list of names. */
2372 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2379 *ppdata = (char *)SMB_REALLOC(
2380 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2381 if(*ppdata == NULL) {
2382 reply_nterror(req, NT_STATUS_NO_MEMORY);
2387 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2389 /* Realloc the params space */
2390 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2391 if(*pparams == NULL ) {
2392 reply_nterror(req, NT_STATUS_NO_MEMORY);
2398 /* Check that the dptr is valid */
2399 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2400 reply_doserror(req, ERRDOS, ERRnofiles);
2404 string_set(&conn->dirpath,dptr_path(dptr_num));
2406 /* Get the wildcard mask from the dptr */
2407 if((p = dptr_wcard(dptr_num))== NULL) {
2408 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2409 reply_doserror(req, ERRDOS, ERRnofiles);
2414 directory = conn->dirpath;
2416 /* Get the attr mask from the dptr */
2417 dirtype = dptr_attr(dptr_num);
2419 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2420 dptr_num, mask, dirtype,
2422 dptr_TellDir(conn->dirptr)));
2424 /* Initialize per TRANS2_FIND_NEXT operation data */
2425 dptr_init_search_op(conn->dirptr);
2427 /* We don't need to check for VOL here as this is returned by
2428 a different TRANS2 call. */
2430 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2431 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2432 dont_descend = True;
2435 space_remaining = max_data_bytes;
2436 out_of_space = False;
2439 * Seek to the correct position. We no longer use the resume key but
2440 * depend on the last file name instead.
2443 if(*resume_name && !continue_bit) {
2446 long current_pos = 0;
2448 * Remember, name_to_8_3 is called by
2449 * get_lanman2_dir_entry(), so the resume name
2450 * could be mangled. Ensure we check the unmangled name.
2453 if (mangle_is_mangled(resume_name, conn->params)) {
2454 char *new_resume_name = NULL;
2455 mangle_lookup_name_from_8_3(ctx,
2459 if (new_resume_name) {
2460 resume_name = new_resume_name;
2465 * Fix for NT redirector problem triggered by resume key indexes
2466 * changing between directory scans. We now return a resume key of 0
2467 * and instead look for the filename to continue from (also given
2468 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2469 * findfirst/findnext (as is usual) then the directory pointer
2470 * should already be at the correct place.
2473 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2474 } /* end if resume_name && !continue_bit */
2476 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2477 bool got_exact_match = False;
2479 /* this is a heuristic to avoid seeking the dirptr except when
2480 absolutely necessary. It allows for a filename of about 40 chars */
2481 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2482 out_of_space = True;
2485 finished = !get_lanman2_dir_entry(ctx,
2488 mask,dirtype,info_level,
2489 requires_resume_key,dont_descend,
2492 space_remaining, &out_of_space,
2494 &last_entry_off, ea_list);
2497 if (finished && out_of_space)
2500 if (!finished && !out_of_space)
2504 * As an optimisation if we know we aren't looking
2505 * for a wildcard name (ie. the name matches the wildcard exactly)
2506 * then we can finish on any (first) match.
2507 * This speeds up large directory searches. JRA.
2513 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2516 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2517 smb_fn_name(req->cmd),
2518 mask, directory, dirtype, numentries ) );
2520 /* Check if we can close the dirptr */
2521 if(close_after_request || (finished && close_if_end)) {
2522 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2523 dptr_close(&dptr_num); /* This frees up the saved mask */
2526 /* Set up the return parameter block */
2527 SSVAL(params,0,numentries);
2528 SSVAL(params,2,finished);
2529 SSVAL(params,4,0); /* Never an EA error */
2530 SSVAL(params,6,last_entry_off);
2532 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2538 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2540 E_md4hash(lp_servicename(SNUM(conn)),objid);
2544 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2546 SMB_ASSERT(extended_info != NULL);
2548 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2549 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2550 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2551 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2552 #ifdef SAMBA_VERSION_REVISION
2553 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2555 extended_info->samba_subversion = 0;
2556 #ifdef SAMBA_VERSION_RC_RELEASE
2557 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2559 #ifdef SAMBA_VERSION_PRE_RELEASE
2560 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2563 #ifdef SAMBA_VERSION_VENDOR_PATCH
2564 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2566 extended_info->samba_gitcommitdate = 0;
2567 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2568 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2571 memset(extended_info->samba_version_string, 0,
2572 sizeof(extended_info->samba_version_string));
2574 snprintf (extended_info->samba_version_string,
2575 sizeof(extended_info->samba_version_string),
2576 "%s", samba_version_string());
2579 /****************************************************************************
2580 Reply to a TRANS2_QFSINFO (query filesystem info).
2581 ****************************************************************************/
2583 static void call_trans2qfsinfo(connection_struct *conn,
2584 struct smb_request *req,
2585 char **pparams, int total_params,
2586 char **ppdata, int total_data,
2587 unsigned int max_data_bytes)
2589 char *pdata, *end_data;
2590 char *params = *pparams;
2594 const char *vname = volume_label(SNUM(conn));
2595 int snum = SNUM(conn);
2596 char *fstype = lp_fstype(SNUM(conn));
2597 uint32 additional_flags = 0;
2599 if (total_params < 2) {
2600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2604 info_level = SVAL(params,0);
2607 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2608 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2609 "info level (0x%x) on IPC$.\n",
2610 (unsigned int)info_level));
2611 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2616 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2617 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2618 DEBUG(0,("call_trans2qfsinfo: encryption required "
2619 "and info level 0x%x sent.\n",
2620 (unsigned int)info_level));
2621 exit_server_cleanly("encryption required "
2627 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2629 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2630 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2631 reply_doserror(req, ERRSRV, ERRinvdevice);
2635 *ppdata = (char *)SMB_REALLOC(
2636 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2637 if (*ppdata == NULL ) {
2638 reply_nterror(req, NT_STATUS_NO_MEMORY);
2643 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2644 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2646 switch (info_level) {
2647 case SMB_INFO_ALLOCATION:
2649 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2651 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2652 reply_unixerror(req, ERRHRD, ERRgeneral);
2656 block_size = lp_block_size(snum);
2657 if (bsize < block_size) {
2658 uint64_t factor = block_size/bsize;
2663 if (bsize > block_size) {
2664 uint64_t factor = bsize/block_size;
2669 bytes_per_sector = 512;
2670 sectors_per_unit = bsize/bytes_per_sector;
2672 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2673 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2674 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2676 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2677 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2678 SIVAL(pdata,l1_cUnit,dsize);
2679 SIVAL(pdata,l1_cUnitAvail,dfree);
2680 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2684 case SMB_INFO_VOLUME:
2685 /* Return volume name */
2687 * Add volume serial number - hash of a combination of
2688 * the called hostname and the service name.
2690 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2692 * Win2k3 and previous mess this up by sending a name length
2693 * one byte short. I believe only older clients (OS/2 Win9x) use
2694 * this call so try fixing this by adding a terminating null to
2695 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2699 pdata+l2_vol_szVolLabel, vname,
2700 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2701 STR_NOALIGN|STR_TERMINATE);
2702 SCVAL(pdata,l2_vol_cch,len);
2703 data_len = l2_vol_szVolLabel + len;
2704 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2705 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2709 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2710 case SMB_FS_ATTRIBUTE_INFORMATION:
2712 additional_flags = 0;
2713 #if defined(HAVE_SYS_QUOTAS)
2714 additional_flags |= FILE_VOLUME_QUOTAS;
2717 if(lp_nt_acl_support(SNUM(conn))) {
2718 additional_flags |= FILE_PERSISTENT_ACLS;
2721 /* Capabilities are filled in at connection time through STATVFS call */
2722 additional_flags |= conn->fs_capabilities;
2724 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2725 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2726 additional_flags); /* FS ATTRIBUTES */
2728 SIVAL(pdata,4,255); /* Max filename component length */
2729 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2730 and will think we can't do long filenames */
2731 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2732 PTR_DIFF(end_data, pdata+12),
2735 data_len = 12 + len;
2738 case SMB_QUERY_FS_LABEL_INFO:
2739 case SMB_FS_LABEL_INFORMATION:
2740 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2741 PTR_DIFF(end_data, pdata+4), 0);
2746 case SMB_QUERY_FS_VOLUME_INFO:
2747 case SMB_FS_VOLUME_INFORMATION:
2750 * Add volume serial number - hash of a combination of
2751 * the called hostname and the service name.
2753 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2754 (str_checksum(get_local_machine_name())<<16));
2756 /* Max label len is 32 characters. */
2757 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2758 PTR_DIFF(end_data, pdata+18),
2760 SIVAL(pdata,12,len);
2763 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2764 (int)strlen(vname),vname, lp_servicename(snum)));
2767 case SMB_QUERY_FS_SIZE_INFO:
2768 case SMB_FS_SIZE_INFORMATION:
2770 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2772 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2773 reply_unixerror(req, ERRHRD, ERRgeneral);
2776 block_size = lp_block_size(snum);
2777 if (bsize < block_size) {
2778 uint64_t factor = block_size/bsize;
2783 if (bsize > block_size) {
2784 uint64_t factor = bsize/block_size;
2789 bytes_per_sector = 512;
2790 sectors_per_unit = bsize/bytes_per_sector;
2791 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2792 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2793 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2794 SBIG_UINT(pdata,0,dsize);
2795 SBIG_UINT(pdata,8,dfree);
2796 SIVAL(pdata,16,sectors_per_unit);
2797 SIVAL(pdata,20,bytes_per_sector);
2801 case SMB_FS_FULL_SIZE_INFORMATION:
2803 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2805 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2806 reply_unixerror(req, ERRHRD, ERRgeneral);
2809 block_size = lp_block_size(snum);
2810 if (bsize < block_size) {
2811 uint64_t factor = block_size/bsize;
2816 if (bsize > block_size) {
2817 uint64_t factor = bsize/block_size;
2822 bytes_per_sector = 512;
2823 sectors_per_unit = bsize/bytes_per_sector;
2824 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2825 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2826 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2827 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2828 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2829 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2830 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2831 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2835 case SMB_QUERY_FS_DEVICE_INFO:
2836 case SMB_FS_DEVICE_INFORMATION:
2838 SIVAL(pdata,0,0); /* dev type */
2839 SIVAL(pdata,4,0); /* characteristics */
2842 #ifdef HAVE_SYS_QUOTAS
2843 case SMB_FS_QUOTA_INFORMATION:
2845 * what we have to send --metze:
2847 * Unknown1: 24 NULL bytes
2848 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2849 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2850 * Quota Flags: 2 byte :
2851 * Unknown3: 6 NULL bytes
2855 * details for Quota Flags:
2857 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2858 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2859 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2860 * 0x0001 Enable Quotas: enable quota for this fs
2864 /* we need to fake up a fsp here,
2865 * because its not send in this call
2868 SMB_NTQUOTA_STRUCT quotas;
2871 ZERO_STRUCT(quotas);
2877 if (conn->server_info->utok.uid != 0) {
2878 DEBUG(0,("set_user_quota: access_denied "
2879 "service [%s] user [%s]\n",
2880 lp_servicename(SNUM(conn)),
2881 conn->server_info->unix_name));
2882 reply_doserror(req, ERRDOS, ERRnoaccess);
2886 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2887 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2888 reply_doserror(req, ERRSRV, ERRerror);
2894 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2896 /* Unknown1 24 NULL bytes*/
2897 SBIG_UINT(pdata,0,(uint64_t)0);
2898 SBIG_UINT(pdata,8,(uint64_t)0);
2899 SBIG_UINT(pdata,16,(uint64_t)0);
2901 /* Default Soft Quota 8 bytes */
2902 SBIG_UINT(pdata,24,quotas.softlim);
2904 /* Default Hard Quota 8 bytes */
2905 SBIG_UINT(pdata,32,quotas.hardlim);
2907 /* Quota flag 2 bytes */
2908 SSVAL(pdata,40,quotas.qflags);
2910 /* Unknown3 6 NULL bytes */
2916 #endif /* HAVE_SYS_QUOTAS */
2917 case SMB_FS_OBJECTID_INFORMATION:
2919 unsigned char objid[16];
2920 struct smb_extended_info extended_info;
2921 memcpy(pdata,create_volume_objectid(conn, objid),16);
2922 samba_extended_info_version (&extended_info);
2923 SIVAL(pdata,16,extended_info.samba_magic);
2924 SIVAL(pdata,20,extended_info.samba_version);
2925 SIVAL(pdata,24,extended_info.samba_subversion);
2926 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2927 memcpy(pdata+36,extended_info.samba_version_string,28);
2933 * Query the version and capabilities of the CIFS UNIX extensions
2937 case SMB_QUERY_CIFS_UNIX_INFO:
2939 bool large_write = lp_min_receive_file_size() &&
2940 !srv_is_signing_active(smbd_server_conn);
2941 bool large_read = !srv_is_signing_active(smbd_server_conn);
2942 int encrypt_caps = 0;
2944 if (!lp_unix_extensions()) {
2945 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2949 switch (conn->encrypt_level) {
2955 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2958 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2959 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2960 large_write = false;
2966 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2967 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2969 /* We have POSIX ACLs, pathname, encryption,
2970 * large read/write, and locking capability. */
2972 SBIG_UINT(pdata,4,((uint64_t)(
2973 CIFS_UNIX_POSIX_ACLS_CAP|
2974 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2975 CIFS_UNIX_FCNTL_LOCKS_CAP|
2976 CIFS_UNIX_EXTATTR_CAP|
2977 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2979 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2981 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2985 case SMB_QUERY_POSIX_FS_INFO:
2988 vfs_statvfs_struct svfs;
2990 if (!lp_unix_extensions()) {
2991 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2995 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2999 SIVAL(pdata,0,svfs.OptimalTransferSize);
3000 SIVAL(pdata,4,svfs.BlockSize);
3001 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3002 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3003 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3004 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3005 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3006 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3007 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3009 } else if (rc == EOPNOTSUPP) {
3010 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3012 #endif /* EOPNOTSUPP */
3014 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3015 reply_doserror(req, ERRSRV, ERRerror);
3021 case SMB_QUERY_POSIX_WHOAMI:
3027 if (!lp_unix_extensions()) {
3028 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3032 if (max_data_bytes < 40) {
3033 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3037 /* We ARE guest if global_sid_Builtin_Guests is
3038 * in our list of SIDs.
3040 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3041 conn->server_info->ptok)) {
3042 flags |= SMB_WHOAMI_GUEST;
3045 /* We are NOT guest if global_sid_Authenticated_Users
3046 * is in our list of SIDs.
3048 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3049 conn->server_info->ptok)) {
3050 flags &= ~SMB_WHOAMI_GUEST;
3053 /* NOTE: 8 bytes for UID/GID, irrespective of native
3054 * platform size. This matches
3055 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3057 data_len = 4 /* flags */
3064 + 4 /* pad/reserved */
3065 + (conn->server_info->utok.ngroups * 8)
3067 + (conn->server_info->ptok->num_sids *
3071 SIVAL(pdata, 0, flags);
3072 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3074 (uint64_t)conn->server_info->utok.uid);
3075 SBIG_UINT(pdata, 16,
3076 (uint64_t)conn->server_info->utok.gid);
3079 if (data_len >= max_data_bytes) {
3080 /* Potential overflow, skip the GIDs and SIDs. */
3082 SIVAL(pdata, 24, 0); /* num_groups */
3083 SIVAL(pdata, 28, 0); /* num_sids */
3084 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3085 SIVAL(pdata, 36, 0); /* reserved */
3091 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3092 SIVAL(pdata, 28, conn->server_info->num_sids);
3094 /* We walk the SID list twice, but this call is fairly
3095 * infrequent, and I don't expect that it's performance
3096 * sensitive -- jpeach
3098 for (i = 0, sid_bytes = 0;
3099 i < conn->server_info->ptok->num_sids; ++i) {
3100 sid_bytes += ndr_size_dom_sid(
3101 &conn->server_info->ptok->user_sids[i],
3106 /* SID list byte count */
3107 SIVAL(pdata, 32, sid_bytes);
3109 /* 4 bytes pad/reserved - must be zero */
3110 SIVAL(pdata, 36, 0);
3114 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3115 SBIG_UINT(pdata, data_len,
3116 (uint64_t)conn->server_info->utok.groups[i]);
3122 i < conn->server_info->ptok->num_sids; ++i) {
3123 int sid_len = ndr_size_dom_sid(
3124 &conn->server_info->ptok->user_sids[i],
3128 sid_linearize(pdata + data_len, sid_len,
3129 &conn->server_info->ptok->user_sids[i]);
3130 data_len += sid_len;
3136 case SMB_MAC_QUERY_FS_INFO:
3138 * Thursby MAC extension... ONLY on NTFS filesystems
3139 * once we do streams then we don't need this
3141 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3143 SIVAL(pdata,84,0x100); /* Don't support mac... */
3148 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3153 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3156 DEBUG( 4, ( "%s info_level = %d\n",
3157 smb_fn_name(req->cmd), info_level) );
3162 /****************************************************************************
3163 Reply to a TRANS2_SETFSINFO (set filesystem info).
3164 ****************************************************************************/
3166 static void call_trans2setfsinfo(connection_struct *conn,
3167 struct smb_request *req,
3168 char **pparams, int total_params,
3169 char **ppdata, int total_data,
3170 unsigned int max_data_bytes)
3172 char *pdata = *ppdata;
3173 char *params = *pparams;
3176 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3179 if (total_params < 4) {
3180 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3186 info_level = SVAL(params,2);
3189 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3190 info_level != SMB_SET_CIFS_UNIX_INFO) {
3191 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3192 "info level (0x%x) on IPC$.\n",
3193 (unsigned int)info_level));
3194 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3199 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3200 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3201 DEBUG(0,("call_trans2setfsinfo: encryption required "
3202 "and info level 0x%x sent.\n",
3203 (unsigned int)info_level));
3204 exit_server_cleanly("encryption required "
3210 switch(info_level) {
3211 case SMB_SET_CIFS_UNIX_INFO:
3213 uint16 client_unix_major;
3214 uint16 client_unix_minor;
3215 uint32 client_unix_cap_low;
3216 uint32 client_unix_cap_high;
3218 if (!lp_unix_extensions()) {
3220 NT_STATUS_INVALID_LEVEL);
3224 /* There should be 12 bytes of capabilities set. */
3225 if (total_data < 8) {
3228 NT_STATUS_INVALID_PARAMETER);
3231 client_unix_major = SVAL(pdata,0);
3232 client_unix_minor = SVAL(pdata,2);
3233 client_unix_cap_low = IVAL(pdata,4);
3234 client_unix_cap_high = IVAL(pdata,8);
3235 /* Just print these values for now. */
3236 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3237 cap_low = 0x%x, cap_high = 0x%x\n",
3238 (unsigned int)client_unix_major,
3239 (unsigned int)client_unix_minor,
3240 (unsigned int)client_unix_cap_low,
3241 (unsigned int)client_unix_cap_high ));
3243 /* Here is where we must switch to posix pathname processing... */
3244 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3245 lp_set_posix_pathnames();
3246 mangle_change_to_posix();
3249 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3250 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3251 /* Client that knows how to do posix locks,
3252 * but not posix open/mkdir operations. Set a
3253 * default type for read/write checks. */
3255 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3261 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3264 size_t param_len = 0;
3265 size_t data_len = total_data;
3267 if (!lp_unix_extensions()) {
3270 NT_STATUS_INVALID_LEVEL);
3274 if (lp_smb_encrypt(SNUM(conn)) == false) {
3277 NT_STATUS_NOT_SUPPORTED);
3281 DEBUG( 4,("call_trans2setfsinfo: "
3282 "request transport encryption.\n"));
3284 status = srv_request_encryption_setup(conn,
3285 (unsigned char **)ppdata,
3287 (unsigned char **)pparams,
3290 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3291 !NT_STATUS_IS_OK(status)) {
3292 reply_nterror(req, status);
3296 send_trans2_replies(conn, req,
3303 if (NT_STATUS_IS_OK(status)) {
3304 /* Server-side transport
3305 * encryption is now *on*. */
3306 status = srv_encryption_start(conn);
3307 if (!NT_STATUS_IS_OK(status)) {
3308 exit_server_cleanly(
3309 "Failure in setting "
3310 "up encrypted transport");
3316 case SMB_FS_QUOTA_INFORMATION:
3318 files_struct *fsp = NULL;
3319 SMB_NTQUOTA_STRUCT quotas;
3321 ZERO_STRUCT(quotas);
3324 if ((conn->server_info->utok.uid != 0)
3325 ||!CAN_WRITE(conn)) {
3326 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3327 lp_servicename(SNUM(conn)),
3328 conn->server_info->unix_name));
3329 reply_doserror(req, ERRSRV, ERRaccess);
3333 /* note: normaly there're 48 bytes,
3334 * but we didn't use the last 6 bytes for now
3337 fsp = file_fsp(req, SVAL(params,0));
3339 if (!check_fsp_ntquota_handle(conn, req,
3341 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3343 req, NT_STATUS_INVALID_HANDLE);
3347 if (total_data < 42) {
3348 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3352 NT_STATUS_INVALID_PARAMETER);
3356 /* unknown_1 24 NULL bytes in pdata*/
3358 /* the soft quotas 8 bytes (uint64_t)*/
3359 quotas.softlim = (uint64_t)IVAL(pdata,24);
3360 #ifdef LARGE_SMB_OFF_T
3361 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3362 #else /* LARGE_SMB_OFF_T */
3363 if ((IVAL(pdata,28) != 0)&&
3364 ((quotas.softlim != 0xFFFFFFFF)||
3365 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3366 /* more than 32 bits? */
3369 NT_STATUS_INVALID_PARAMETER);
3372 #endif /* LARGE_SMB_OFF_T */
3374 /* the hard quotas 8 bytes (uint64_t)*/
3375 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3376 #ifdef LARGE_SMB_OFF_T
3377 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3378 #else /* LARGE_SMB_OFF_T */
3379 if ((IVAL(pdata,36) != 0)&&
3380 ((quotas.hardlim != 0xFFFFFFFF)||
3381 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3382 /* more than 32 bits? */
3385 NT_STATUS_INVALID_PARAMETER);
3388 #endif /* LARGE_SMB_OFF_T */
3390 /* quota_flags 2 bytes **/
3391 quotas.qflags = SVAL(pdata,40);
3393 /* unknown_2 6 NULL bytes follow*/
3395 /* now set the quotas */
3396 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3397 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3398 reply_doserror(req, ERRSRV, ERRerror);
3405 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3407 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3413 * sending this reply works fine,
3414 * but I'm not sure it's the same
3415 * like windows do...
3418 reply_outbuf(req, 10, 0);
3421 #if defined(HAVE_POSIX_ACLS)
3422 /****************************************************************************
3423 Utility function to count the number of entries in a POSIX acl.
3424 ****************************************************************************/
3426 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3428 unsigned int ace_count = 0;
3429 int entry_id = SMB_ACL_FIRST_ENTRY;
3430 SMB_ACL_ENTRY_T entry;
3432 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3434 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3435 entry_id = SMB_ACL_NEXT_ENTRY;
3442 /****************************************************************************
3443 Utility function to marshall a POSIX acl into wire format.
3444 ****************************************************************************/
3446 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3448 int entry_id = SMB_ACL_FIRST_ENTRY;
3449 SMB_ACL_ENTRY_T entry;
3451 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3452 SMB_ACL_TAG_T tagtype;
3453 SMB_ACL_PERMSET_T permset;
3454 unsigned char perms = 0;
3455 unsigned int own_grp;
3458 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3459 entry_id = SMB_ACL_NEXT_ENTRY;
3462 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3463 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3467 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3468 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3472 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3473 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3474 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3476 SCVAL(pdata,1,perms);
3479 case SMB_ACL_USER_OBJ:
3480 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3481 own_grp = (unsigned int)pst->st_ex_uid;
3482 SIVAL(pdata,2,own_grp);
3487 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3489 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3492 own_grp = (unsigned int)*puid;
3493 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3494 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3495 SIVAL(pdata,2,own_grp);
3499 case SMB_ACL_GROUP_OBJ:
3500 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3501 own_grp = (unsigned int)pst->st_ex_gid;
3502 SIVAL(pdata,2,own_grp);
3507 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3509 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3512 own_grp = (unsigned int)*pgid;
3513 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3514 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3515 SIVAL(pdata,2,own_grp);
3520 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3521 SIVAL(pdata,2,0xFFFFFFFF);
3522 SIVAL(pdata,6,0xFFFFFFFF);
3525 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3526 SIVAL(pdata,2,0xFFFFFFFF);
3527 SIVAL(pdata,6,0xFFFFFFFF);
3530 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3533 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3540 /****************************************************************************
3541 Store the FILE_UNIX_BASIC info.
3542 ****************************************************************************/
3544 static char *store_file_unix_basic(connection_struct *conn,
3547 const SMB_STRUCT_STAT *psbuf)
3549 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3550 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3552 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3555 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3558 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3559 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3560 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3563 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3567 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3571 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3574 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3578 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3582 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3585 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3589 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3596 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3597 * the chflags(2) (or equivalent) flags.
3599 * XXX: this really should be behind the VFS interface. To do this, we would
3600 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3601 * Each VFS module could then implement its own mapping as appropriate for the
3602 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3604 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3608 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3612 { UF_IMMUTABLE, EXT_IMMUTABLE },
3616 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3620 { UF_HIDDEN, EXT_HIDDEN },
3623 /* Do not remove. We need to guarantee that this array has at least one
3624 * entry to build on HP-UX.
3630 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3631 uint32 *smb_fflags, uint32 *smb_fmask)
3635 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3636 *smb_fmask |= info2_flags_map[i].smb_fflag;
3637 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3638 *smb_fflags |= info2_flags_map[i].smb_fflag;
3643 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3644 const uint32 smb_fflags,
3645 const uint32 smb_fmask,
3648 uint32 max_fmask = 0;
3651 *stat_fflags = psbuf->st_ex_flags;
3653 /* For each flags requested in smb_fmask, check the state of the
3654 * corresponding flag in smb_fflags and set or clear the matching
3658 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3659 max_fmask |= info2_flags_map[i].smb_fflag;
3660 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3661 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3662 *stat_fflags |= info2_flags_map[i].stat_fflag;
3664 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3669 /* If smb_fmask is asking to set any bits that are not supported by
3670 * our flag mappings, we should fail.
3672 if ((smb_fmask & max_fmask) != smb_fmask) {
3680 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3681 * of file flags and birth (create) time.
3683 static char *store_file_unix_basic_info2(connection_struct *conn,
3686 const SMB_STRUCT_STAT *psbuf)
3688 uint32 file_flags = 0;
3689 uint32 flags_mask = 0;
3691 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3693 /* Create (birth) time 64 bit */
3694 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3697 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3698 SIVAL(pdata, 0, file_flags); /* flags */
3699 SIVAL(pdata, 4, flags_mask); /* mask */
3705 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3706 const struct stream_struct *streams,
3708 unsigned int max_data_bytes,
3709 unsigned int *data_size)
3712 unsigned int ofs = 0;
3714 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3715 unsigned int next_offset;
3717 smb_ucs2_t *namebuf;
3719 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3720 streams[i].name, &namelen) ||
3723 return NT_STATUS_INVALID_PARAMETER;
3727 * name_buf is now null-terminated, we need to marshall as not
3733 SIVAL(data, ofs+4, namelen);
3734 SOFF_T(data, ofs+8, streams[i].size);
3735 SOFF_T(data, ofs+16, streams[i].alloc_size);
3736 memcpy(data+ofs+24, namebuf, namelen);
3737 TALLOC_FREE(namebuf);
3739 next_offset = ofs + 24 + namelen;
3741 if (i == num_streams-1) {
3742 SIVAL(data, ofs, 0);
3745 unsigned int align = ndr_align_size(next_offset, 8);
3747 memset(data+next_offset, 0, align);
3748 next_offset += align;
3750 SIVAL(data, ofs, next_offset - ofs);
3759 return NT_STATUS_OK;
3762 /****************************************************************************
3763 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3764 ****************************************************************************/
3766 static void call_trans2qpipeinfo(connection_struct *conn,
3767 struct smb_request *req,
3768 unsigned int tran_call,
3769 char **pparams, int total_params,
3770 char **ppdata, int total_data,
3771 unsigned int max_data_bytes)
3773 char *params = *pparams;
3774 char *pdata = *ppdata;
3775 unsigned int data_size = 0;
3776 unsigned int param_size = 2;
3781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3785 if (total_params < 4) {
3786 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3790 fsp = file_fsp(req, SVAL(params,0));
3791 if (!fsp_is_np(fsp)) {
3792 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3796 info_level = SVAL(params,2);
3798 *pparams = (char *)SMB_REALLOC(*pparams,2);
3799 if (*pparams == NULL) {
3800 reply_nterror(req, NT_STATUS_NO_MEMORY);
3805 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3806 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3807 if (*ppdata == NULL ) {
3808 reply_nterror(req, NT_STATUS_NO_MEMORY);
3813 switch (info_level) {
3814 case SMB_FILE_STANDARD_INFORMATION:
3816 SOFF_T(pdata,0,4096LL);
3823 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3827 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3833 /****************************************************************************
3834 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3835 file name or file id).
3836 ****************************************************************************/
3838 static void call_trans2qfilepathinfo(connection_struct *conn,
3839 struct smb_request *req,
3840 unsigned int tran_call,
3841 char **pparams, int total_params,
3842 char **ppdata, int total_data,
3843 unsigned int max_data_bytes)
3845 char *params = *pparams;
3846 char *pdata = *ppdata;
3847 char *dstart, *dend;
3851 SMB_OFF_T file_size=0;
3852 uint64_t allocation_size=0;
3853 unsigned int data_size = 0;
3854 unsigned int param_size = 2;
3855 SMB_STRUCT_STAT sbuf;
3856 char *dos_fname = NULL;
3858 struct smb_filename *smb_fname = NULL;
3863 bool delete_pending = False;
3865 time_t create_time, mtime, atime;
3866 struct timespec create_time_ts, mtime_ts, atime_ts;
3867 struct timespec write_time_ts;
3868 files_struct *fsp = NULL;
3869 struct file_id fileid;
3870 struct ea_list *ea_list = NULL;
3871 char *lock_data = NULL;
3872 bool ms_dfs_link = false;
3873 TALLOC_CTX *ctx = talloc_tos();
3876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3881 ZERO_STRUCT(write_time_ts);
3883 if (tran_call == TRANSACT2_QFILEINFO) {
3884 if (total_params < 4) {
3885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3890 call_trans2qpipeinfo(conn, req, tran_call,
3891 pparams, total_params,
3897 fsp = file_fsp(req, SVAL(params,0));
3898 info_level = SVAL(params,2);
3900 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3902 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3903 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3907 /* Initial check for valid fsp ptr. */
3908 if (!check_fsp_open(conn, req, fsp)) {
3912 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3914 reply_nterror(req, NT_STATUS_NO_MEMORY);
3918 if(fsp->fake_file_handle) {
3920 * This is actually for the QUOTA_FAKE_FILE --metze
3923 /* We know this name is ok, it's already passed the checks. */
3925 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3927 * This is actually a QFILEINFO on a directory
3928 * handle (returned from an NT SMB). NT5.0 seems
3929 * to do this call. JRA.
3932 if (INFO_LEVEL_IS_UNIX(info_level)) {
3933 /* Always do lstat for UNIX calls. */
3934 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3935 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3936 reply_unixerror(req,ERRDOS,ERRbadpath);
3939 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3940 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3941 reply_unixerror(req, ERRDOS, ERRbadpath);
3945 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3946 get_file_infos(fileid, &delete_pending, &write_time_ts);
3949 * Original code - this is an open file.
3951 if (!check_fsp(conn, req, fsp)) {
3955 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3956 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3957 reply_unixerror(req, ERRDOS, ERRbadfid);
3960 pos = fsp->fh->position_information;
3961 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3962 get_file_infos(fileid, &delete_pending, &write_time_ts);
3966 NTSTATUS status = NT_STATUS_OK;
3969 if (total_params < 7) {
3970 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3974 info_level = SVAL(params,0);
3976 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3978 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3979 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3983 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3985 STR_TERMINATE, &status);
3986 if (!NT_STATUS_IS_OK(status)) {
3987 reply_nterror(req, status);
3991 status = filename_convert(ctx,
3993 req->flags2 & FLAGS2_DFS_PATHNAMES,
3997 if (!NT_STATUS_IS_OK(status)) {
3998 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3999 reply_botherror(req,
4000 NT_STATUS_PATH_NOT_COVERED,
4001 ERRSRV, ERRbadpath);
4004 reply_nterror(req, status);
4008 sbuf = smb_fname->st;
4010 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4011 && is_ntfs_stream_name(fname)) {
4013 SMB_STRUCT_STAT bsbuf;
4015 status = split_ntfs_stream_name(talloc_tos(), fname,
4017 if (!NT_STATUS_IS_OK(status)) {
4018 DEBUG(10, ("create_file_unixpath: "
4019 "split_ntfs_stream_name failed: %s\n",
4020 nt_errstr(status)));
4021 reply_nterror(req, status);
4025 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4027 if (INFO_LEVEL_IS_UNIX(info_level)) {
4028 /* Always do lstat for UNIX calls. */
4029 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4030 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4031 reply_unixerror(req,ERRDOS,ERRbadpath);
4035 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4036 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4037 reply_unixerror(req,ERRDOS,ERRbadpath);
4042 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4043 get_file_infos(fileid, &delete_pending, NULL);
4044 if (delete_pending) {
4045 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4050 if (INFO_LEVEL_IS_UNIX(info_level)) {
4051 /* Always do lstat for UNIX calls. */
4052 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4053 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4054 reply_unixerror(req, ERRDOS, ERRbadpath);
4058 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4059 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4062 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4063 reply_unixerror(req, ERRDOS, ERRbadpath);
4068 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4069 get_file_infos(fileid, &delete_pending, &write_time_ts);
4070 if (delete_pending) {
4071 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4076 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4077 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4081 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4082 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4084 p = strrchr_m(fname,'/');
4091 mode = dos_mode_msdfs(conn,fname,&sbuf);
4093 mode = dos_mode(conn,fname,&sbuf);
4096 mode = FILE_ATTRIBUTE_NORMAL;
4098 nlink = sbuf.st_ex_nlink;
4100 if (nlink && (mode&aDIR)) {
4104 if ((nlink > 0) && delete_pending) {
4108 fullpathname = fname;
4110 file_size = get_file_size_stat(&sbuf);
4112 /* Pull out any data sent here before we realloc. */
4113 switch (info_level) {
4114 case SMB_INFO_QUERY_EAS_FROM_LIST:
4116 /* Pull any EA list from the data portion. */
4119 if (total_data < 4) {
4121 req, NT_STATUS_INVALID_PARAMETER);
4124 ea_size = IVAL(pdata,0);
4126 if (total_data > 0 && ea_size != total_data) {
4127 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4128 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4130 req, NT_STATUS_INVALID_PARAMETER);
4134 if (!lp_ea_support(SNUM(conn))) {
4135 reply_doserror(req, ERRDOS,
4136 ERReasnotsupported);
4140 /* Pull out the list of names. */
4141 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4144 req, NT_STATUS_INVALID_PARAMETER);
4150 case SMB_QUERY_POSIX_LOCK:
4152 if (fsp == NULL || fsp->fh->fd == -1) {
4153 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4157 if (total_data != POSIX_LOCK_DATA_SIZE) {
4159 req, NT_STATUS_INVALID_PARAMETER);
4163 /* Copy the lock range data. */
4164 lock_data = (char *)TALLOC_MEMDUP(
4165 ctx, pdata, total_data);
4167 reply_nterror(req, NT_STATUS_NO_MEMORY);
4175 *pparams = (char *)SMB_REALLOC(*pparams,2);
4176 if (*pparams == NULL) {
4177 reply_nterror(req, NT_STATUS_NO_MEMORY);
4182 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4183 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4184 if (*ppdata == NULL ) {
4185 reply_nterror(req, NT_STATUS_NO_MEMORY);
4190 dend = dstart + data_size - 1;
4192 create_time_ts = sbuf.st_ex_btime;
4193 mtime_ts = sbuf.st_ex_mtime;
4194 atime_ts = sbuf.st_ex_atime;
4196 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4199 /* Do we have this path open ? */
4201 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4202 fsp1 = file_find_di_first(fileid);
4203 if (fsp1 && fsp1->initial_allocation_size) {
4204 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4208 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4209 mtime_ts = write_time_ts;
4212 if (lp_dos_filetime_resolution(SNUM(conn))) {
4213 dos_filetime_timespec(&create_time_ts);
4214 dos_filetime_timespec(&mtime_ts);
4215 dos_filetime_timespec(&atime_ts);
4218 create_time = convert_timespec_to_time_t(create_time_ts);
4219 mtime = convert_timespec_to_time_t(mtime_ts);
4220 atime = convert_timespec_to_time_t(atime_ts);
4222 /* NT expects the name to be in an exact form of the *full*
4223 filename. See the trans2 torture test */
4224 if (ISDOT(base_name)) {
4225 dos_fname = talloc_strdup(ctx, "\\");
4227 reply_nterror(req, NT_STATUS_NO_MEMORY);
4231 dos_fname = talloc_asprintf(ctx,
4235 reply_nterror(req, NT_STATUS_NO_MEMORY);
4238 string_replace(dos_fname, '/', '\\');
4241 switch (info_level) {
4242 case SMB_INFO_STANDARD:
4243 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4245 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4246 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4247 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4248 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4249 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4250 SSVAL(pdata,l1_attrFile,mode);
4253 case SMB_INFO_QUERY_EA_SIZE:
4255 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4256 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4258 srv_put_dos_date2(pdata,0,create_time);
4259 srv_put_dos_date2(pdata,4,atime);
4260 srv_put_dos_date2(pdata,8,mtime); /* write time */
4261 SIVAL(pdata,12,(uint32)file_size);
4262 SIVAL(pdata,16,(uint32)allocation_size);
4263 SSVAL(pdata,20,mode);
4264 SIVAL(pdata,22,ea_size);
4268 case SMB_INFO_IS_NAME_VALID:
4269 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4270 if (tran_call == TRANSACT2_QFILEINFO) {
4271 /* os/2 needs this ? really ?*/
4272 reply_doserror(req, ERRDOS, ERRbadfunc);
4279 case SMB_INFO_QUERY_EAS_FROM_LIST:
4281 size_t total_ea_len = 0;
4282 struct ea_list *ea_file_list = NULL;
4284 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4286 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4287 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4289 if (!ea_list || (total_ea_len > data_size)) {
4291 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4295 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4299 case SMB_INFO_QUERY_ALL_EAS:
4301 /* We have data_size bytes to put EA's into. */
4302 size_t total_ea_len = 0;
4304 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4306 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4307 if (!ea_list || (total_ea_len > data_size)) {
4309 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4313 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4317 case SMB_FILE_BASIC_INFORMATION:
4318 case SMB_QUERY_FILE_BASIC_INFO:
4320 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4321 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4322 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4324 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4328 put_long_date_timespec(pdata,create_time_ts);
4329 put_long_date_timespec(pdata+8,atime_ts);
4330 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4331 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4332 SIVAL(pdata,32,mode);
4334 DEBUG(5,("SMB_QFBI - "));
4335 DEBUG(5,("create: %s ", ctime(&create_time)));
4336 DEBUG(5,("access: %s ", ctime(&atime)));
4337 DEBUG(5,("write: %s ", ctime(&mtime)));
4338 DEBUG(5,("change: %s ", ctime(&mtime)));
4339 DEBUG(5,("mode: %x\n", mode));
4342 case SMB_FILE_STANDARD_INFORMATION:
4343 case SMB_QUERY_FILE_STANDARD_INFO:
4345 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4347 SOFF_T(pdata,0,allocation_size);
4348 SOFF_T(pdata,8,file_size);
4349 SIVAL(pdata,16,nlink);
4350 SCVAL(pdata,20,delete_pending?1:0);
4351 SCVAL(pdata,21,(mode&aDIR)?1:0);
4352 SSVAL(pdata,22,0); /* Padding. */
4355 case SMB_FILE_EA_INFORMATION:
4356 case SMB_QUERY_FILE_EA_INFO:
4358 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4359 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4361 SIVAL(pdata,0,ea_size);
4365 /* Get the 8.3 name - used if NT SMB was negotiated. */
4366 case SMB_QUERY_FILE_ALT_NAME_INFO:
4367 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4369 char mangled_name[13];
4370 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4371 if (!name_to_8_3(base_name,mangled_name,
4372 True,conn->params)) {
4375 NT_STATUS_NO_MEMORY);
4377 len = srvstr_push(dstart, req->flags2,
4378 pdata+4, mangled_name,
4379 PTR_DIFF(dend, pdata+4),
4381 data_size = 4 + len;
4386 case SMB_QUERY_FILE_NAME_INFO:
4388 this must be *exactly* right for ACLs on mapped drives to work
4390 len = srvstr_push(dstart, req->flags2,
4392 PTR_DIFF(dend, pdata+4),
4394 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4395 data_size = 4 + len;
4399 case SMB_FILE_ALLOCATION_INFORMATION:
4400 case SMB_QUERY_FILE_ALLOCATION_INFO:
4401 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4403 SOFF_T(pdata,0,allocation_size);
4406 case SMB_FILE_END_OF_FILE_INFORMATION:
4407 case SMB_QUERY_FILE_END_OF_FILEINFO:
4408 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4410 SOFF_T(pdata,0,file_size);
4413 case SMB_QUERY_FILE_ALL_INFO:
4414 case SMB_FILE_ALL_INFORMATION:
4416 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4417 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4418 put_long_date_timespec(pdata,create_time_ts);
4419 put_long_date_timespec(pdata+8,atime_ts);
4420 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4421 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4422 SIVAL(pdata,32,mode);
4423 SIVAL(pdata,36,0); /* padding. */
4425 SOFF_T(pdata,0,allocation_size);
4426 SOFF_T(pdata,8,file_size);
4427 SIVAL(pdata,16,nlink);
4428 SCVAL(pdata,20,delete_pending);
4429 SCVAL(pdata,21,(mode&aDIR)?1:0);
4432 SIVAL(pdata,0,ea_size);
4433 pdata += 4; /* EA info */
4434 len = srvstr_push(dstart, req->flags2,
4436 PTR_DIFF(dend, pdata+4),
4440 data_size = PTR_DIFF(pdata,(*ppdata));
4443 case SMB_FILE_INTERNAL_INFORMATION:
4444 /* This should be an index number - looks like
4447 I think this causes us to fail the IFSKIT
4448 BasicFileInformationTest. -tpot */
4450 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4451 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4452 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4456 case SMB_FILE_ACCESS_INFORMATION:
4457 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4459 SIVAL(pdata,0,fsp->access_mask);
4461 /* GENERIC_EXECUTE mapping from Windows */
4462 SIVAL(pdata,0,0x12019F);
4467 case SMB_FILE_NAME_INFORMATION:
4468 /* Pathname with leading '\'. */
4471 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4472 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4473 SIVAL(pdata,0,byte_len);
4474 data_size = 4 + byte_len;
4478 case SMB_FILE_DISPOSITION_INFORMATION:
4479 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4481 SCVAL(pdata,0,delete_pending);
4484 case SMB_FILE_POSITION_INFORMATION:
4485 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4487 SOFF_T(pdata,0,pos);
4490 case SMB_FILE_MODE_INFORMATION:
4491 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4492 SIVAL(pdata,0,mode);
4496 case SMB_FILE_ALIGNMENT_INFORMATION:
4497 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4498 SIVAL(pdata,0,0); /* No alignment needed. */
4503 * NT4 server just returns "invalid query" to this - if we try
4504 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4507 /* The first statement above is false - verified using Thursby
4508 * client against NT4 -- gcolley.
4510 case SMB_QUERY_FILE_STREAM_INFO:
4511 case SMB_FILE_STREAM_INFORMATION: {
4512 unsigned int num_streams;
4513 struct stream_struct *streams;
4516 DEBUG(10,("call_trans2qfilepathinfo: "
4517 "SMB_FILE_STREAM_INFORMATION\n"));
4519 status = SMB_VFS_STREAMINFO(
4520 conn, fsp, fname, talloc_tos(),
4521 &num_streams, &streams);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 DEBUG(10, ("could not get stream info: %s\n",
4525 nt_errstr(status)));
4526 reply_nterror(req, status);
4530 status = marshall_stream_info(num_streams, streams,
4531 pdata, max_data_bytes,
4534 if (!NT_STATUS_IS_OK(status)) {
4535 DEBUG(10, ("marshall_stream_info failed: %s\n",
4536 nt_errstr(status)));
4537 reply_nterror(req, status);
4541 TALLOC_FREE(streams);
4545 case SMB_QUERY_COMPRESSION_INFO:
4546 case SMB_FILE_COMPRESSION_INFORMATION:
4547 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4548 SOFF_T(pdata,0,file_size);
4549 SIVAL(pdata,8,0); /* ??? */
4550 SIVAL(pdata,12,0); /* ??? */
4554 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4555 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4556 put_long_date_timespec(pdata,create_time_ts);
4557 put_long_date_timespec(pdata+8,atime_ts);
4558 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4559 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4560 SOFF_T(pdata,32,allocation_size);
4561 SOFF_T(pdata,40,file_size);
4562 SIVAL(pdata,48,mode);
4563 SIVAL(pdata,52,0); /* ??? */
4567 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4568 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4569 SIVAL(pdata,0,mode);
4575 * CIFS UNIX Extensions.
4578 case SMB_QUERY_FILE_UNIX_BASIC:
4580 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4581 data_size = PTR_DIFF(pdata,(*ppdata));
4585 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4587 for (i=0; i<100; i++)
4588 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4594 case SMB_QUERY_FILE_UNIX_INFO2:
4596 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4597 data_size = PTR_DIFF(pdata,(*ppdata));
4601 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4603 for (i=0; i<100; i++)
4604 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4610 case SMB_QUERY_FILE_UNIX_LINK:
4612 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4615 reply_nterror(req, NT_STATUS_NO_MEMORY);
4619 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4621 if(!S_ISLNK(sbuf.st_ex_mode)) {
4622 reply_unixerror(req, ERRSRV,
4627 reply_unixerror(req, ERRDOS, ERRbadlink);
4630 len = SMB_VFS_READLINK(conn,fullpathname,
4633 reply_unixerror(req, ERRDOS,
4638 len = srvstr_push(dstart, req->flags2,
4640 PTR_DIFF(dend, pdata),
4643 data_size = PTR_DIFF(pdata,(*ppdata));
4648 #if defined(HAVE_POSIX_ACLS)
4649 case SMB_QUERY_POSIX_ACL:
4651 SMB_ACL_T file_acl = NULL;
4652 SMB_ACL_T def_acl = NULL;
4653 uint16 num_file_acls = 0;
4654 uint16 num_def_acls = 0;
4656 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4657 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4659 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4662 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4663 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4667 NT_STATUS_NOT_IMPLEMENTED);
4671 if (S_ISDIR(sbuf.st_ex_mode)) {
4672 if (fsp && fsp->is_directory) {
4673 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4675 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4677 def_acl = free_empty_sys_acl(conn, def_acl);
4680 num_file_acls = count_acl_entries(conn, file_acl);
4681 num_def_acls = count_acl_entries(conn, def_acl);
4683 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4684 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4686 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4687 SMB_POSIX_ACL_HEADER_SIZE) ));
4689 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4692 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4696 NT_STATUS_BUFFER_TOO_SMALL);
4700 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4701 SSVAL(pdata,2,num_file_acls);
4702 SSVAL(pdata,4,num_def_acls);
4703 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4705 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4708 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4711 req, NT_STATUS_INTERNAL_ERROR);
4714 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4716 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4719 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4723 NT_STATUS_INTERNAL_ERROR);
4728 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4731 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4733 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4739 case SMB_QUERY_POSIX_LOCK:
4741 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4745 enum brl_type lock_type;
4747 if (total_data != POSIX_LOCK_DATA_SIZE) {
4749 req, NT_STATUS_INVALID_PARAMETER);
4753 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4754 case POSIX_LOCK_TYPE_READ:
4755 lock_type = READ_LOCK;
4757 case POSIX_LOCK_TYPE_WRITE:
4758 lock_type = WRITE_LOCK;
4760 case POSIX_LOCK_TYPE_UNLOCK:
4762 /* There's no point in asking for an unlock... */
4765 NT_STATUS_INVALID_PARAMETER);
4769 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4770 #if defined(HAVE_LONGLONG)
4771 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4772 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4773 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4774 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4775 #else /* HAVE_LONGLONG */
4776 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4777 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4778 #endif /* HAVE_LONGLONG */
4780 status = query_lock(fsp,
4787 if (ERROR_WAS_LOCK_DENIED(status)) {
4788 /* Here we need to report who has it locked... */
4789 data_size = POSIX_LOCK_DATA_SIZE;
4791 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4792 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4793 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4794 #if defined(HAVE_LONGLONG)
4795 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4796 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4797 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4798 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4799 #else /* HAVE_LONGLONG */
4800 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4801 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4802 #endif /* HAVE_LONGLONG */
4804 } else if (NT_STATUS_IS_OK(status)) {
4805 /* For success we just return a copy of what we sent
4806 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4807 data_size = POSIX_LOCK_DATA_SIZE;
4808 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4809 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4811 reply_nterror(req, status);
4818 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4822 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4828 /****************************************************************************
4829 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4831 ****************************************************************************/
4833 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4834 connection_struct *conn,
4835 const struct smb_filename *smb_fname_old,
4836 const struct smb_filename *smb_fname_new)
4838 char *oldname = NULL;
4839 char *newname = NULL;
4840 NTSTATUS status = NT_STATUS_OK;
4842 /* source must already exist. */
4843 if (!VALID_STAT(smb_fname_old->st)) {
4844 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4847 /* Disallow if newname already exists. */
4848 if (VALID_STAT(smb_fname_new->st)) {
4849 return NT_STATUS_OBJECT_NAME_COLLISION;
4852 /* No links from a directory. */
4853 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
4854 return NT_STATUS_FILE_IS_A_DIRECTORY;
4857 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
4858 if (!NT_STATUS_IS_OK(status)) {
4861 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
4862 if (!NT_STATUS_IS_OK(status)) {
4866 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4868 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4869 status = map_nt_error_from_unix(errno);
4870 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4871 nt_errstr(status), newname, oldname));
4874 TALLOC_FREE(newname);
4875 TALLOC_FREE(oldname);
4879 /****************************************************************************
4880 Deal with setting the time from any of the setfilepathinfo functions.
4881 ****************************************************************************/
4883 NTSTATUS smb_set_file_time(connection_struct *conn,
4886 const SMB_STRUCT_STAT *psbuf,
4887 struct smb_file_time *ft,
4888 bool setting_write_time)
4891 FILE_NOTIFY_CHANGE_LAST_ACCESS
4892 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4894 if (!VALID_STAT(*psbuf)) {
4895 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4898 /* get some defaults (no modifications) if any info is zero or -1. */
4899 if (null_timespec(ft->atime)) {
4900 ft->atime= psbuf->st_ex_atime;
4901 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4904 if (null_timespec(ft->mtime)) {
4905 ft->mtime = psbuf->st_ex_mtime;
4906 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4909 if (!setting_write_time) {
4910 /* ft->mtime comes from change time, not write time. */
4911 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4914 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4915 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4916 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4917 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4918 if (!null_timespec(ft->create_time)) {
4919 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4920 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4924 * Try and set the times of this file if
4925 * they are different from the current values.
4929 struct timespec mts = psbuf->st_ex_mtime;
4930 struct timespec ats = psbuf->st_ex_atime;
4931 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4932 (timespec_compare(&ft->mtime, &mts) == 0)) {
4933 return NT_STATUS_OK;
4937 if (setting_write_time) {
4939 * This was a setfileinfo on an open file.
4940 * NT does this a lot. We also need to
4941 * set the time here, as it can be read by
4942 * FindFirst/FindNext and with the patch for bug #2045
4943 * in smbd/fileio.c it ensures that this timestamp is
4944 * kept sticky even after a write. We save the request
4945 * away and will set it on file close and after a write. JRA.
4948 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4949 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4952 if (fsp->base_fsp) {
4953 set_sticky_write_time_fsp(fsp->base_fsp,
4956 set_sticky_write_time_fsp(fsp, ft->mtime);
4959 set_sticky_write_time_path(conn, fname,
4960 vfs_file_id_from_sbuf(conn, psbuf),
4965 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4967 if (fsp && fsp->base_fsp) {
4968 fname = fsp->base_fsp->fsp_name;
4971 if(file_ntimes(conn, fname, ft)!=0) {
4972 return map_nt_error_from_unix(errno);
4974 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4976 return NT_STATUS_OK;
4979 /****************************************************************************
4980 Deal with setting the dosmode from any of the setfilepathinfo functions.
4981 ****************************************************************************/
4983 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4986 SMB_STRUCT_STAT *psbuf,
4989 if (!VALID_STAT(*psbuf)) {
4990 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4994 if (fsp->base_fsp) {
4995 fname = fsp->base_fsp->fsp_name;
4997 fname = fsp->fsp_name;
5002 if (S_ISDIR(psbuf->st_ex_mode)) {
5009 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5011 /* check the mode isn't different, before changing it */
5012 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5014 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5015 fname, (unsigned int)dosmode ));
5017 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5018 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5019 fname, strerror(errno)));
5020 return map_nt_error_from_unix(errno);
5023 return NT_STATUS_OK;
5026 /****************************************************************************
5027 Deal with setting the size from any of the setfilepathinfo functions.
5028 ****************************************************************************/
5030 static NTSTATUS smb_set_file_size(connection_struct *conn,
5031 struct smb_request *req,
5034 SMB_STRUCT_STAT *psbuf,
5037 struct smb_filename *smb_fname = NULL;
5038 NTSTATUS status = NT_STATUS_OK;
5039 files_struct *new_fsp = NULL;
5041 if (!VALID_STAT(*psbuf)) {
5042 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5045 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5047 if (size == get_file_size_stat(psbuf)) {
5048 return NT_STATUS_OK;
5051 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5052 fname, (double)size ));
5054 if (fsp && fsp->fh->fd != -1) {
5055 /* Handle based call. */
5056 if (vfs_set_filelen(fsp, size) == -1) {
5057 return map_nt_error_from_unix(errno);
5059 trigger_write_time_update_immediate(fsp);
5060 return NT_STATUS_OK;
5063 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5065 if (!NT_STATUS_IS_OK(status)) {
5069 status = SMB_VFS_CREATE_FILE(
5072 0, /* root_dir_fid */
5073 smb_fname, /* fname */
5074 FILE_WRITE_ATTRIBUTES, /* access_mask */
5075 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5077 FILE_OPEN, /* create_disposition*/
5078 0, /* create_options */
5079 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5080 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5081 0, /* allocation_size */
5084 &new_fsp, /* result */
5087 *psbuf = smb_fname->st;
5088 TALLOC_FREE(smb_fname);
5090 if (!NT_STATUS_IS_OK(status)) {
5091 /* NB. We check for open_was_deferred in the caller. */
5095 if (vfs_set_filelen(new_fsp, size) == -1) {
5096 status = map_nt_error_from_unix(errno);
5097 close_file(req, new_fsp,NORMAL_CLOSE);
5101 trigger_write_time_update_immediate(new_fsp);
5102 close_file(req, new_fsp,NORMAL_CLOSE);
5103 return NT_STATUS_OK;
5106 /****************************************************************************
5107 Deal with SMB_INFO_SET_EA.
5108 ****************************************************************************/
5110 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5116 struct ea_list *ea_list = NULL;
5117 TALLOC_CTX *ctx = NULL;
5118 NTSTATUS status = NT_STATUS_OK;
5120 if (total_data < 10) {
5122 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5123 length. They seem to have no effect. Bug #3212. JRA */
5125 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5126 /* We're done. We only get EA info in this call. */
5127 return NT_STATUS_OK;
5130 return NT_STATUS_INVALID_PARAMETER;
5133 if (IVAL(pdata,0) > total_data) {
5134 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5135 IVAL(pdata,0), (unsigned int)total_data));
5136 return NT_STATUS_INVALID_PARAMETER;
5140 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5142 return NT_STATUS_INVALID_PARAMETER;
5144 status = set_ea(conn, fsp, fname, ea_list);
5149 /****************************************************************************
5150 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5151 ****************************************************************************/
5153 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5158 SMB_STRUCT_STAT *psbuf)
5160 NTSTATUS status = NT_STATUS_OK;
5161 bool delete_on_close;
5164 if (total_data < 1) {
5165 return NT_STATUS_INVALID_PARAMETER;
5169 return NT_STATUS_INVALID_HANDLE;
5172 delete_on_close = (CVAL(pdata,0) ? True : False);
5173 dosmode = dos_mode(conn, fname, psbuf);
5175 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5176 "delete_on_close = %u\n",
5178 (unsigned int)dosmode,
5179 (unsigned int)delete_on_close ));
5181 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5183 if (!NT_STATUS_IS_OK(status)) {
5187 /* The set is across all open files on this dev/inode pair. */
5188 if (!set_delete_on_close(fsp, delete_on_close,
5189 &conn->server_info->utok)) {
5190 return NT_STATUS_ACCESS_DENIED;
5192 return NT_STATUS_OK;
5195 /****************************************************************************
5196 Deal with SMB_FILE_POSITION_INFORMATION.
5197 ****************************************************************************/
5199 static NTSTATUS smb_file_position_information(connection_struct *conn,
5204 uint64_t position_information;
5206 if (total_data < 8) {
5207 return NT_STATUS_INVALID_PARAMETER;
5211 /* Ignore on pathname based set. */
5212 return NT_STATUS_OK;
5215 position_information = (uint64_t)IVAL(pdata,0);
5216 #ifdef LARGE_SMB_OFF_T
5217 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5218 #else /* LARGE_SMB_OFF_T */
5219 if (IVAL(pdata,4) != 0) {
5220 /* more than 32 bits? */
5221 return NT_STATUS_INVALID_PARAMETER;
5223 #endif /* LARGE_SMB_OFF_T */
5225 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5226 fsp->fsp_name, (double)position_information ));
5227 fsp->fh->position_information = position_information;
5228 return NT_STATUS_OK;
5231 /****************************************************************************
5232 Deal with SMB_FILE_MODE_INFORMATION.
5233 ****************************************************************************/
5235 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5241 if (total_data < 4) {
5242 return NT_STATUS_INVALID_PARAMETER;
5244 mode = IVAL(pdata,0);
5245 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5246 return NT_STATUS_INVALID_PARAMETER;
5248 return NT_STATUS_OK;
5251 /****************************************************************************
5252 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5253 ****************************************************************************/
5255 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5256 struct smb_request *req,
5261 char *link_target = NULL;
5262 const char *newname = fname;
5263 NTSTATUS status = NT_STATUS_OK;
5264 TALLOC_CTX *ctx = talloc_tos();
5266 /* Set a symbolic link. */
5267 /* Don't allow this if follow links is false. */
5269 if (total_data == 0) {
5270 return NT_STATUS_INVALID_PARAMETER;
5273 if (!lp_symlinks(SNUM(conn))) {
5274 return NT_STATUS_ACCESS_DENIED;
5277 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5278 total_data, STR_TERMINATE);
5281 return NT_STATUS_INVALID_PARAMETER;
5284 /* !widelinks forces the target path to be within the share. */
5285 /* This means we can interpret the target as a pathname. */
5286 if (!lp_widelinks(SNUM(conn))) {
5287 char *rel_name = NULL;
5288 char *last_dirp = NULL;
5290 if (*link_target == '/') {
5291 /* No absolute paths allowed. */
5292 return NT_STATUS_ACCESS_DENIED;
5294 rel_name = talloc_strdup(ctx,newname);
5296 return NT_STATUS_NO_MEMORY;
5298 last_dirp = strrchr_m(rel_name, '/');
5300 last_dirp[1] = '\0';
5302 rel_name = talloc_strdup(ctx,"./");
5304 return NT_STATUS_NO_MEMORY;
5307 rel_name = talloc_asprintf_append(rel_name,
5311 return NT_STATUS_NO_MEMORY;
5314 status = check_name(conn, rel_name);
5315 if (!NT_STATUS_IS_OK(status)) {
5320 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5321 newname, link_target ));
5323 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5324 return map_nt_error_from_unix(errno);
5327 return NT_STATUS_OK;
5330 /****************************************************************************
5331 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5332 ****************************************************************************/
5334 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5335 struct smb_request *req,
5336 const char *pdata, int total_data,
5337 const struct smb_filename *smb_fname_new)
5339 char *oldname = NULL;
5340 struct smb_filename *smb_fname_old = NULL;
5341 TALLOC_CTX *ctx = talloc_tos();
5342 NTSTATUS status = NT_STATUS_OK;
5344 /* Set a hard link. */
5345 if (total_data == 0) {
5346 return NT_STATUS_INVALID_PARAMETER;
5349 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5350 total_data, STR_TERMINATE, &status);
5351 if (!NT_STATUS_IS_OK(status)) {
5355 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5356 smb_fname_str_dbg(smb_fname_new), oldname));
5358 status = filename_convert(ctx,
5360 req->flags2 & FLAGS2_DFS_PATHNAMES,
5364 if (!NT_STATUS_IS_OK(status)) {
5368 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5371 /****************************************************************************
5372 Deal with SMB_FILE_RENAME_INFORMATION.
5373 ****************************************************************************/
5375 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5376 struct smb_request *req,
5385 char *newname = NULL;
5386 char *base_name = NULL;
5387 struct smb_filename *smb_fname = NULL;
5388 bool dest_has_wcard = False;
5389 NTSTATUS status = NT_STATUS_OK;
5391 TALLOC_CTX *ctx = talloc_tos();
5393 if (total_data < 13) {
5394 return NT_STATUS_INVALID_PARAMETER;
5397 overwrite = (CVAL(pdata,0) ? True : False);
5398 root_fid = IVAL(pdata,4);
5399 len = IVAL(pdata,8);
5401 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5402 return NT_STATUS_INVALID_PARAMETER;
5405 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5408 if (!NT_STATUS_IS_OK(status)) {
5412 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5415 status = resolve_dfspath_wcard(ctx, conn,
5416 req->flags2 & FLAGS2_DFS_PATHNAMES,
5420 if (!NT_STATUS_IS_OK(status)) {
5424 /* Check the new name has no '/' characters. */
5425 if (strchr_m(newname, '/')) {
5426 return NT_STATUS_NOT_SUPPORTED;
5429 if (fsp && fsp->base_fsp) {
5430 /* newname must be a stream name. */
5431 if (newname[0] != ':') {
5432 return NT_STATUS_NOT_SUPPORTED;
5434 base_name = talloc_asprintf(ctx, "%s%s",
5435 fsp->base_fsp->fsp_name,
5438 return NT_STATUS_NO_MEMORY;
5441 /* newname must *not* be a stream name. */
5442 if (is_ntfs_stream_name(newname)) {
5443 return NT_STATUS_NOT_SUPPORTED;
5446 /* Create the base directory. */
5447 base_name = talloc_strdup(ctx, fname);
5449 return NT_STATUS_NO_MEMORY;
5451 p = strrchr_m(base_name, '/');
5455 base_name = talloc_strdup(ctx, "./");
5457 return NT_STATUS_NO_MEMORY;
5460 /* Append the new name. */
5461 base_name = talloc_asprintf_append(base_name,
5465 return NT_STATUS_NO_MEMORY;
5468 status = unix_convert(ctx, conn, newname, &smb_fname,
5471 /* If an error we expect this to be
5472 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5474 if (!NT_STATUS_IS_OK(status)
5475 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5482 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5483 fsp->fnum, fsp->fsp_name, base_name ));
5484 status = rename_internals_fsp(conn, fsp, base_name,
5486 smb_fname->original_lcomp : NULL,
5489 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5490 fname, base_name ));
5491 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5492 overwrite, False, dest_has_wcard,
5493 FILE_WRITE_ATTRIBUTES);
5496 TALLOC_FREE(smb_fname);
5500 /****************************************************************************
5501 Deal with SMB_SET_POSIX_ACL.
5502 ****************************************************************************/
5504 #if defined(HAVE_POSIX_ACLS)
5505 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5510 SMB_STRUCT_STAT *psbuf)
5512 uint16 posix_acl_version;
5513 uint16 num_file_acls;
5514 uint16 num_def_acls;
5515 bool valid_file_acls = True;
5516 bool valid_def_acls = True;
5518 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5519 return NT_STATUS_INVALID_PARAMETER;
5521 posix_acl_version = SVAL(pdata,0);
5522 num_file_acls = SVAL(pdata,2);
5523 num_def_acls = SVAL(pdata,4);
5525 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5526 valid_file_acls = False;
5530 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5531 valid_def_acls = False;
5535 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5536 return NT_STATUS_INVALID_PARAMETER;
5539 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5540 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5541 return NT_STATUS_INVALID_PARAMETER;
5544 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5545 fname ? fname : fsp->fsp_name,
5546 (unsigned int)num_file_acls,
5547 (unsigned int)num_def_acls));
5549 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5550 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5551 return map_nt_error_from_unix(errno);
5554 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5555 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5556 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5557 return map_nt_error_from_unix(errno);
5559 return NT_STATUS_OK;
5563 /****************************************************************************
5564 Deal with SMB_SET_POSIX_LOCK.
5565 ****************************************************************************/
5567 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5568 struct smb_request *req,
5576 bool blocking_lock = False;
5577 enum brl_type lock_type;
5579 NTSTATUS status = NT_STATUS_OK;
5581 if (fsp == NULL || fsp->fh->fd == -1) {
5582 return NT_STATUS_INVALID_HANDLE;
5585 if (total_data != POSIX_LOCK_DATA_SIZE) {
5586 return NT_STATUS_INVALID_PARAMETER;
5589 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5590 case POSIX_LOCK_TYPE_READ:
5591 lock_type = READ_LOCK;
5593 case POSIX_LOCK_TYPE_WRITE:
5594 /* Return the right POSIX-mappable error code for files opened read-only. */
5595 if (!fsp->can_write) {
5596 return NT_STATUS_INVALID_HANDLE;
5598 lock_type = WRITE_LOCK;
5600 case POSIX_LOCK_TYPE_UNLOCK:
5601 lock_type = UNLOCK_LOCK;
5604 return NT_STATUS_INVALID_PARAMETER;
5607 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5608 blocking_lock = False;
5609 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5610 blocking_lock = True;
5612 return NT_STATUS_INVALID_PARAMETER;
5615 if (!lp_blocking_locks(SNUM(conn))) {
5616 blocking_lock = False;
5619 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5620 #if defined(HAVE_LONGLONG)
5621 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5622 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5623 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5624 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5625 #else /* HAVE_LONGLONG */
5626 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5627 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5628 #endif /* HAVE_LONGLONG */
5630 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5631 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5633 (unsigned int)lock_type,
5634 (unsigned int)lock_pid,
5638 if (lock_type == UNLOCK_LOCK) {
5639 status = do_unlock(smbd_messaging_context(),
5646 uint32 block_smbpid;
5648 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5660 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5662 * A blocking lock was requested. Package up
5663 * this smb into a queued request and push it
5664 * onto the blocking lock queue.
5666 if(push_blocking_lock_request(br_lck,
5669 -1, /* infinite timeout. */
5677 TALLOC_FREE(br_lck);
5681 TALLOC_FREE(br_lck);
5687 /****************************************************************************
5688 Deal with SMB_INFO_STANDARD.
5689 ****************************************************************************/
5691 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5696 const SMB_STRUCT_STAT *psbuf)
5698 struct smb_file_time ft;
5701 if (total_data < 12) {
5702 return NT_STATUS_INVALID_PARAMETER;
5706 ft.create_time = interpret_long_date(pdata);
5709 ft.atime = interpret_long_date(pdata + 8);
5712 ft.mtime = interpret_long_date(pdata + 16);
5714 DEBUG(10,("smb_set_info_standard: file %s\n",
5715 fname ? fname : fsp->fsp_name ));
5717 return smb_set_file_time(conn,
5725 /****************************************************************************
5726 Deal with SMB_SET_FILE_BASIC_INFO.
5727 ****************************************************************************/
5729 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5734 SMB_STRUCT_STAT *psbuf)
5736 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5737 struct timespec write_time;
5738 struct timespec changed_time;
5739 struct smb_file_time ft;
5741 NTSTATUS status = NT_STATUS_OK;
5742 bool setting_write_time = true;
5746 if (total_data < 36) {
5747 return NT_STATUS_INVALID_PARAMETER;
5750 /* Set the attributes */
5751 dosmode = IVAL(pdata,32);
5752 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5753 if (!NT_STATUS_IS_OK(status)) {
5758 ft.atime = interpret_long_date(pdata+8);
5760 write_time = interpret_long_date(pdata+16);
5761 changed_time = interpret_long_date(pdata+24);
5764 ft.mtime = timespec_min(&write_time, &changed_time);
5767 ft.create_time = interpret_long_date(pdata);
5769 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5770 !null_timespec(write_time)) {
5771 ft.mtime = write_time;
5774 /* Prefer a defined time to an undefined one. */
5775 if (null_timespec(ft.mtime)) {
5776 if (null_timespec(write_time)) {
5777 ft.mtime = changed_time;
5778 setting_write_time = false;
5780 ft.mtime = write_time;
5784 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5785 fname ? fname : fsp->fsp_name ));
5787 return smb_set_file_time(conn,
5792 setting_write_time);
5795 /****************************************************************************
5796 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5797 ****************************************************************************/
5799 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5800 struct smb_request *req,
5805 SMB_STRUCT_STAT *psbuf)
5807 struct smb_filename *smb_fname = NULL;
5808 uint64_t allocation_size = 0;
5809 NTSTATUS status = NT_STATUS_OK;
5810 files_struct *new_fsp = NULL;
5812 if (!VALID_STAT(*psbuf)) {
5813 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5816 if (total_data < 8) {
5817 return NT_STATUS_INVALID_PARAMETER;
5820 allocation_size = (uint64_t)IVAL(pdata,0);
5821 #ifdef LARGE_SMB_OFF_T
5822 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5823 #else /* LARGE_SMB_OFF_T */
5824 if (IVAL(pdata,4) != 0) {
5825 /* more than 32 bits? */
5826 return NT_STATUS_INVALID_PARAMETER;
5828 #endif /* LARGE_SMB_OFF_T */
5830 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5831 fname, (double)allocation_size ));
5833 if (allocation_size) {
5834 allocation_size = smb_roundup(conn, allocation_size);
5837 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5838 fname, (double)allocation_size ));
5840 if (fsp && fsp->fh->fd != -1) {
5841 /* Open file handle. */
5842 /* Only change if needed. */
5843 if (allocation_size != get_file_size_stat(psbuf)) {
5844 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5845 return map_nt_error_from_unix(errno);
5848 /* But always update the time. */
5850 * This is equivalent to a write. Ensure it's seen immediately
5851 * if there are no pending writes.
5853 trigger_write_time_update_immediate(fsp);
5854 return NT_STATUS_OK;
5857 /* Pathname or stat or directory file. */
5859 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5861 if (!NT_STATUS_IS_OK(status)) {
5865 status = SMB_VFS_CREATE_FILE(
5868 0, /* root_dir_fid */
5869 smb_fname, /* fname */
5870 FILE_WRITE_DATA, /* access_mask */
5871 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5873 FILE_OPEN, /* create_disposition*/
5874 0, /* create_options */
5875 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5876 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5877 0, /* allocation_size */
5880 &new_fsp, /* result */
5883 *psbuf = smb_fname->st;
5884 TALLOC_FREE(smb_fname);
5886 if (!NT_STATUS_IS_OK(status)) {
5887 /* NB. We check for open_was_deferred in the caller. */
5891 /* Only change if needed. */
5892 if (allocation_size != get_file_size_stat(psbuf)) {
5893 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5894 status = map_nt_error_from_unix(errno);
5895 close_file(req, new_fsp, NORMAL_CLOSE);
5900 /* Changing the allocation size should set the last mod time. */
5902 * This is equivalent to a write. Ensure it's seen immediately
5903 * if there are no pending writes.
5905 trigger_write_time_update_immediate(new_fsp);
5907 close_file(req, new_fsp, NORMAL_CLOSE);
5908 return NT_STATUS_OK;
5911 /****************************************************************************
5912 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5913 ****************************************************************************/
5915 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5916 struct smb_request *req,
5921 SMB_STRUCT_STAT *psbuf)
5925 if (total_data < 8) {
5926 return NT_STATUS_INVALID_PARAMETER;
5929 size = IVAL(pdata,0);
5930 #ifdef LARGE_SMB_OFF_T
5931 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5932 #else /* LARGE_SMB_OFF_T */
5933 if (IVAL(pdata,4) != 0) {
5934 /* more than 32 bits? */
5935 return NT_STATUS_INVALID_PARAMETER;
5937 #endif /* LARGE_SMB_OFF_T */
5938 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5939 "file %s to %.0f\n", fname, (double)size ));
5941 return smb_set_file_size(conn, req,
5948 /****************************************************************************
5949 Allow a UNIX info mknod.
5950 ****************************************************************************/
5952 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5956 SMB_STRUCT_STAT *psbuf)
5958 uint32 file_type = IVAL(pdata,56);
5959 #if defined(HAVE_MAKEDEV)
5960 uint32 dev_major = IVAL(pdata,60);
5961 uint32 dev_minor = IVAL(pdata,68);
5963 SMB_DEV_T dev = (SMB_DEV_T)0;
5964 uint32 raw_unixmode = IVAL(pdata,84);
5968 if (total_data < 100) {
5969 return NT_STATUS_INVALID_PARAMETER;
5972 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5973 if (!NT_STATUS_IS_OK(status)) {
5977 #if defined(HAVE_MAKEDEV)
5978 dev = makedev(dev_major, dev_minor);
5981 switch (file_type) {
5982 #if defined(S_IFIFO)
5983 case UNIX_TYPE_FIFO:
5984 unixmode |= S_IFIFO;
5987 #if defined(S_IFSOCK)
5988 case UNIX_TYPE_SOCKET:
5989 unixmode |= S_IFSOCK;
5992 #if defined(S_IFCHR)
5993 case UNIX_TYPE_CHARDEV:
5994 unixmode |= S_IFCHR;
5997 #if defined(S_IFBLK)
5998 case UNIX_TYPE_BLKDEV:
5999 unixmode |= S_IFBLK;
6003 return NT_STATUS_INVALID_PARAMETER;
6006 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6007 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6009 /* Ok - do the mknod. */
6010 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6011 return map_nt_error_from_unix(errno);
6014 /* If any of the other "set" calls fail we
6015 * don't want to end up with a half-constructed mknod.
6018 if (lp_inherit_perms(SNUM(conn))) {
6020 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6021 return NT_STATUS_NO_MEMORY;
6023 inherit_access_posix_acl(conn, parent, fname, unixmode);
6024 TALLOC_FREE(parent);
6027 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6028 status = map_nt_error_from_unix(errno);
6029 SMB_VFS_UNLINK(conn,fname);
6032 return NT_STATUS_OK;
6035 /****************************************************************************
6036 Deal with SMB_SET_FILE_UNIX_BASIC.
6037 ****************************************************************************/
6039 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6040 struct smb_request *req,
6045 SMB_STRUCT_STAT *psbuf)
6047 struct smb_file_time ft;
6048 uint32 raw_unixmode;
6051 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6052 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6053 NTSTATUS status = NT_STATUS_OK;
6054 bool delete_on_fail = False;
6055 enum perm_type ptype;
6059 if (total_data < 100) {
6060 return NT_STATUS_INVALID_PARAMETER;
6063 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6064 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6065 size=IVAL(pdata,0); /* first 8 Bytes are size */
6066 #ifdef LARGE_SMB_OFF_T
6067 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6068 #else /* LARGE_SMB_OFF_T */
6069 if (IVAL(pdata,4) != 0) {
6070 /* more than 32 bits? */
6071 return NT_STATUS_INVALID_PARAMETER;
6073 #endif /* LARGE_SMB_OFF_T */
6076 ft.atime = interpret_long_date(pdata+24); /* access_time */
6077 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6078 set_owner = (uid_t)IVAL(pdata,40);
6079 set_grp = (gid_t)IVAL(pdata,48);
6080 raw_unixmode = IVAL(pdata,84);
6082 if (VALID_STAT(*psbuf)) {
6083 if (S_ISDIR(psbuf->st_ex_mode)) {
6084 ptype = PERM_EXISTING_DIR;
6086 ptype = PERM_EXISTING_FILE;
6089 ptype = PERM_NEW_FILE;
6092 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6093 if (!NT_STATUS_IS_OK(status)) {
6097 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6098 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6099 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6101 if (!VALID_STAT(*psbuf)) {
6103 * The only valid use of this is to create character and block
6104 * devices, and named pipes. This is deprecated (IMHO) and
6105 * a new info level should be used for mknod. JRA.
6108 status = smb_unix_mknod(conn,
6113 if (!NT_STATUS_IS_OK(status)) {
6117 /* Ensure we don't try and change anything else. */
6118 raw_unixmode = SMB_MODE_NO_CHANGE;
6119 size = get_file_size_stat(psbuf);
6120 ft.atime = psbuf->st_ex_atime;
6121 ft.mtime = psbuf->st_ex_mtime;
6123 * We continue here as we might want to change the
6126 delete_on_fail = True;
6130 /* Horrible backwards compatibility hack as an old server bug
6131 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6135 size = get_file_size_stat(psbuf);
6140 * Deal with the UNIX specific mode set.
6143 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6144 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6145 (unsigned int)unixmode, fname ));
6146 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6147 return map_nt_error_from_unix(errno);
6152 * Deal with the UNIX specific uid set.
6155 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_ex_uid != set_owner)) {
6158 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6159 (unsigned int)set_owner, fname ));
6161 if (S_ISLNK(psbuf->st_ex_mode)) {
6162 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6164 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6168 status = map_nt_error_from_unix(errno);
6169 if (delete_on_fail) {
6170 SMB_VFS_UNLINK(conn,fname);
6177 * Deal with the UNIX specific gid set.
6180 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_ex_gid != set_grp)) {
6181 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6182 (unsigned int)set_owner, fname ));
6183 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6184 status = map_nt_error_from_unix(errno);
6185 if (delete_on_fail) {
6186 SMB_VFS_UNLINK(conn,fname);
6192 /* Deal with any size changes. */
6194 status = smb_set_file_size(conn, req,
6199 if (!NT_STATUS_IS_OK(status)) {
6203 /* Deal with any time changes. */
6205 return smb_set_file_time(conn,
6213 /****************************************************************************
6214 Deal with SMB_SET_FILE_UNIX_INFO2.
6215 ****************************************************************************/
6217 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6218 struct smb_request *req,
6223 SMB_STRUCT_STAT *psbuf)
6229 if (total_data < 116) {
6230 return NT_STATUS_INVALID_PARAMETER;
6233 /* Start by setting all the fields that are common between UNIX_BASIC
6236 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6238 if (!NT_STATUS_IS_OK(status)) {
6242 smb_fflags = IVAL(pdata, 108);
6243 smb_fmask = IVAL(pdata, 112);
6245 /* NB: We should only attempt to alter the file flags if the client
6246 * sends a non-zero mask.
6248 if (smb_fmask != 0) {
6249 int stat_fflags = 0;
6251 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6253 /* Client asked to alter a flag we don't understand. */
6254 return NT_STATUS_INVALID_PARAMETER;
6257 if (fsp && fsp->fh->fd != -1) {
6258 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6259 return NT_STATUS_NOT_SUPPORTED;
6261 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6262 return map_nt_error_from_unix(errno);
6267 /* XXX: need to add support for changing the create_time here. You
6268 * can do this for paths on Darwin with setattrlist(2). The right way
6269 * to hook this up is probably by extending the VFS utimes interface.
6272 return NT_STATUS_OK;
6275 /****************************************************************************
6276 Create a directory with POSIX semantics.
6277 ****************************************************************************/
6279 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6280 struct smb_request *req,
6284 SMB_STRUCT_STAT *psbuf,
6285 int *pdata_return_size)
6287 struct smb_filename *smb_fname;
6288 NTSTATUS status = NT_STATUS_OK;
6289 uint32 raw_unixmode = 0;
6290 uint32 mod_unixmode = 0;
6291 mode_t unixmode = (mode_t)0;
6292 files_struct *fsp = NULL;
6293 uint16 info_level_return = 0;
6295 char *pdata = *ppdata;
6297 if (total_data < 18) {
6298 return NT_STATUS_INVALID_PARAMETER;
6301 raw_unixmode = IVAL(pdata,8);
6302 /* Next 4 bytes are not yet defined. */
6304 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6305 if (!NT_STATUS_IS_OK(status)) {
6309 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6311 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6312 fname, (unsigned int)unixmode ));
6314 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6316 if (!NT_STATUS_IS_OK(status)) {
6320 status = SMB_VFS_CREATE_FILE(
6323 0, /* root_dir_fid */
6324 smb_fname, /* fname */
6325 FILE_READ_ATTRIBUTES, /* access_mask */
6326 FILE_SHARE_NONE, /* share_access */
6327 FILE_CREATE, /* create_disposition*/
6328 FILE_DIRECTORY_FILE, /* create_options */
6329 mod_unixmode, /* file_attributes */
6330 0, /* oplock_request */
6331 0, /* allocation_size */
6337 *psbuf = smb_fname->st;
6338 TALLOC_FREE(smb_fname);
6340 if (NT_STATUS_IS_OK(status)) {
6341 close_file(req, fsp, NORMAL_CLOSE);
6344 info_level_return = SVAL(pdata,16);
6346 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6347 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6348 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6349 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6351 *pdata_return_size = 12;
6354 /* Realloc the data size */
6355 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6356 if (*ppdata == NULL) {
6357 *pdata_return_size = 0;
6358 return NT_STATUS_NO_MEMORY;
6362 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6363 SSVAL(pdata,2,0); /* No fnum. */
6364 SIVAL(pdata,4,info); /* Was directory created. */
6366 switch (info_level_return) {
6367 case SMB_QUERY_FILE_UNIX_BASIC:
6368 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6369 SSVAL(pdata,10,0); /* Padding. */
6370 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6372 case SMB_QUERY_FILE_UNIX_INFO2:
6373 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6374 SSVAL(pdata,10,0); /* Padding. */
6375 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6378 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6379 SSVAL(pdata,10,0); /* Padding. */
6386 /****************************************************************************
6387 Open/Create a file with POSIX semantics.
6388 ****************************************************************************/
6390 static NTSTATUS smb_posix_open(connection_struct *conn,
6391 struct smb_request *req,
6395 SMB_STRUCT_STAT *psbuf,
6396 int *pdata_return_size)
6398 struct smb_filename *smb_fname = NULL;
6399 bool extended_oplock_granted = False;
6400 char *pdata = *ppdata;
6402 uint32 wire_open_mode = 0;
6403 uint32 raw_unixmode = 0;
6404 uint32 mod_unixmode = 0;
6405 uint32 create_disp = 0;
6406 uint32 access_mask = 0;
6407 uint32 create_options = 0;
6408 NTSTATUS status = NT_STATUS_OK;
6409 mode_t unixmode = (mode_t)0;
6410 files_struct *fsp = NULL;
6411 int oplock_request = 0;
6413 uint16 info_level_return = 0;
6415 if (total_data < 18) {
6416 return NT_STATUS_INVALID_PARAMETER;
6419 flags = IVAL(pdata,0);
6420 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6421 if (oplock_request) {
6422 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6425 wire_open_mode = IVAL(pdata,4);
6427 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6428 return smb_posix_mkdir(conn, req,
6436 switch (wire_open_mode & SMB_ACCMODE) {
6438 access_mask = FILE_READ_DATA;
6441 access_mask = FILE_WRITE_DATA;
6444 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6447 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6448 (unsigned int)wire_open_mode ));
6449 return NT_STATUS_INVALID_PARAMETER;
6452 wire_open_mode &= ~SMB_ACCMODE;
6454 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6455 create_disp = FILE_CREATE;
6456 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6457 create_disp = FILE_OVERWRITE_IF;
6458 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6459 create_disp = FILE_OPEN_IF;
6460 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6461 create_disp = FILE_OPEN;
6463 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6464 (unsigned int)wire_open_mode ));
6465 return NT_STATUS_INVALID_PARAMETER;
6468 raw_unixmode = IVAL(pdata,8);
6469 /* Next 4 bytes are not yet defined. */
6471 status = unix_perms_from_wire(conn,
6474 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6477 if (!NT_STATUS_IS_OK(status)) {
6481 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6483 if (wire_open_mode & SMB_O_SYNC) {
6484 create_options |= FILE_WRITE_THROUGH;
6486 if (wire_open_mode & SMB_O_APPEND) {
6487 access_mask |= FILE_APPEND_DATA;
6489 if (wire_open_mode & SMB_O_DIRECT) {
6490 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6493 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6495 (unsigned int)wire_open_mode,
6496 (unsigned int)unixmode ));
6498 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6500 if (!NT_STATUS_IS_OK(status)) {
6504 status = SMB_VFS_CREATE_FILE(
6507 0, /* root_dir_fid */
6508 smb_fname, /* fname */
6509 access_mask, /* access_mask */
6510 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6512 create_disp, /* create_disposition*/
6513 FILE_NON_DIRECTORY_FILE, /* create_options */
6514 mod_unixmode, /* file_attributes */
6515 oplock_request, /* oplock_request */
6516 0, /* allocation_size */
6522 *psbuf = smb_fname->st;
6523 TALLOC_FREE(smb_fname);
6525 if (!NT_STATUS_IS_OK(status)) {
6529 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6530 extended_oplock_granted = True;
6533 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6534 extended_oplock_granted = True;
6537 info_level_return = SVAL(pdata,16);
6539 /* Allocate the correct return size. */
6541 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6542 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6543 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6544 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6546 *pdata_return_size = 12;
6549 /* Realloc the data size */
6550 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6551 if (*ppdata == NULL) {
6552 close_file(req, fsp, ERROR_CLOSE);
6553 *pdata_return_size = 0;
6554 return NT_STATUS_NO_MEMORY;
6558 if (extended_oplock_granted) {
6559 if (flags & REQUEST_BATCH_OPLOCK) {
6560 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6562 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6564 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6565 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6567 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6570 SSVAL(pdata,2,fsp->fnum);
6571 SIVAL(pdata,4,info); /* Was file created etc. */
6573 switch (info_level_return) {
6574 case SMB_QUERY_FILE_UNIX_BASIC:
6575 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6576 SSVAL(pdata,10,0); /* padding. */
6577 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6579 case SMB_QUERY_FILE_UNIX_INFO2:
6580 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6581 SSVAL(pdata,10,0); /* padding. */
6582 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6585 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6586 SSVAL(pdata,10,0); /* padding. */
6589 return NT_STATUS_OK;
6592 /****************************************************************************
6593 Delete a file with POSIX semantics.
6594 ****************************************************************************/
6596 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6597 struct smb_request *req,
6601 SMB_STRUCT_STAT *psbuf)
6603 struct smb_filename *smb_fname = NULL;
6604 NTSTATUS status = NT_STATUS_OK;
6605 files_struct *fsp = NULL;
6609 int create_options = 0;
6611 struct share_mode_lock *lck = NULL;
6613 if (total_data < 2) {
6614 return NT_STATUS_INVALID_PARAMETER;
6617 flags = SVAL(pdata,0);
6619 if (!VALID_STAT(*psbuf)) {
6620 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6623 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6624 !VALID_STAT_OF_DIR(*psbuf)) {
6625 return NT_STATUS_NOT_A_DIRECTORY;
6628 DEBUG(10,("smb_posix_unlink: %s %s\n",
6629 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6632 if (VALID_STAT_OF_DIR(*psbuf)) {
6633 create_options |= FILE_DIRECTORY_FILE;
6636 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6638 if (!NT_STATUS_IS_OK(status)) {
6642 status = SMB_VFS_CREATE_FILE(
6645 0, /* root_dir_fid */
6646 smb_fname, /* fname */
6647 DELETE_ACCESS, /* access_mask */
6648 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6650 FILE_OPEN, /* create_disposition*/
6651 create_options, /* create_options */
6652 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6653 0, /* oplock_request */
6654 0, /* allocation_size */
6660 *psbuf = smb_fname->st;
6661 TALLOC_FREE(smb_fname);
6663 if (!NT_STATUS_IS_OK(status)) {
6668 * Don't lie to client. If we can't really delete due to
6669 * non-POSIX opens return SHARING_VIOLATION.
6672 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6675 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6676 "lock for file %s\n", fsp->fsp_name));
6677 close_file(req, fsp, NORMAL_CLOSE);
6678 return NT_STATUS_INVALID_PARAMETER;
6682 * See if others still have the file open. If this is the case, then
6683 * don't delete. If all opens are POSIX delete we can set the delete
6684 * on close disposition.
6686 for (i=0; i<lck->num_share_modes; i++) {
6687 struct share_mode_entry *e = &lck->share_modes[i];
6688 if (is_valid_share_mode_entry(e)) {
6689 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6692 /* Fail with sharing violation. */
6693 close_file(req, fsp, NORMAL_CLOSE);
6695 return NT_STATUS_SHARING_VIOLATION;
6700 * Set the delete on close.
6702 status = smb_set_file_disposition_info(conn,
6709 if (!NT_STATUS_IS_OK(status)) {
6710 close_file(req, fsp, NORMAL_CLOSE);
6715 return close_file(req, fsp, NORMAL_CLOSE);
6718 /****************************************************************************
6719 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6720 ****************************************************************************/
6722 static void call_trans2setfilepathinfo(connection_struct *conn,
6723 struct smb_request *req,
6724 unsigned int tran_call,
6725 char **pparams, int total_params,
6726 char **ppdata, int total_data,
6727 unsigned int max_data_bytes)
6729 char *params = *pparams;
6730 char *pdata = *ppdata;
6732 SMB_STRUCT_STAT sbuf;
6734 struct smb_filename *smb_fname = NULL;
6735 files_struct *fsp = NULL;
6736 NTSTATUS status = NT_STATUS_OK;
6737 int data_return_size = 0;
6738 TALLOC_CTX *ctx = talloc_tos();
6741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6747 if (tran_call == TRANSACT2_SETFILEINFO) {
6748 if (total_params < 4) {
6749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6753 fsp = file_fsp(req, SVAL(params,0));
6754 /* Basic check for non-null fsp. */
6755 if (!check_fsp_open(conn, req, fsp)) {
6758 info_level = SVAL(params,2);
6760 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6762 reply_nterror(req, NT_STATUS_NO_MEMORY);
6766 if(fsp->is_directory || fsp->fh->fd == -1) {
6768 * This is actually a SETFILEINFO on a directory
6769 * handle (returned from an NT SMB). NT5.0 seems
6770 * to do this call. JRA.
6772 if (INFO_LEVEL_IS_UNIX(info_level)) {
6773 /* Always do lstat for UNIX calls. */
6774 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6775 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6776 reply_unixerror(req,ERRDOS,ERRbadpath);
6780 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6781 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6782 reply_unixerror(req,ERRDOS,ERRbadpath);
6786 } else if (fsp->print_file) {
6788 * Doing a DELETE_ON_CLOSE should cancel a print job.
6790 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6791 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6793 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6796 send_trans2_replies(conn, req, params, 2,
6801 reply_unixerror(req, ERRDOS, ERRbadpath);
6806 * Original code - this is an open file.
6808 if (!check_fsp(conn, req, fsp)) {
6812 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6813 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6814 reply_unixerror(req, ERRDOS, ERRbadfid);
6820 if (total_params < 7) {
6821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6825 info_level = SVAL(params,0);
6826 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6827 total_params - 6, STR_TERMINATE,
6829 if (!NT_STATUS_IS_OK(status)) {
6830 reply_nterror(req, status);
6834 status = filename_convert(ctx, conn,
6835 req->flags2 & FLAGS2_DFS_PATHNAMES,
6839 if (!NT_STATUS_IS_OK(status)) {
6840 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6841 reply_botherror(req,
6842 NT_STATUS_PATH_NOT_COVERED,
6843 ERRSRV, ERRbadpath);
6846 reply_nterror(req, status);
6850 sbuf = smb_fname->st;
6852 if (INFO_LEVEL_IS_UNIX(info_level)) {
6854 * For CIFS UNIX extensions the target name may not exist.
6857 /* Always do lstat for UNIX calls. */
6858 SMB_VFS_LSTAT(conn,fname,&sbuf);
6860 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6861 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6862 reply_unixerror(req, ERRDOS, ERRbadpath);
6867 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6868 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6872 if (!CAN_WRITE(conn)) {
6873 /* Allow POSIX opens. The open path will deny
6874 * any non-readonly opens. */
6875 if (info_level != SMB_POSIX_PATH_OPEN) {
6876 reply_doserror(req, ERRSRV, ERRaccess);
6881 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6882 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6884 /* Realloc the parameter size */
6885 *pparams = (char *)SMB_REALLOC(*pparams,2);
6886 if (*pparams == NULL) {
6887 reply_nterror(req, NT_STATUS_NO_MEMORY);
6894 switch (info_level) {
6896 case SMB_INFO_STANDARD:
6898 status = smb_set_info_standard(conn,
6907 case SMB_INFO_SET_EA:
6909 status = smb_info_set_ea(conn,
6917 case SMB_SET_FILE_BASIC_INFO:
6918 case SMB_FILE_BASIC_INFORMATION:
6920 status = smb_set_file_basic_info(conn,
6929 case SMB_FILE_ALLOCATION_INFORMATION:
6930 case SMB_SET_FILE_ALLOCATION_INFO:
6932 status = smb_set_file_allocation_info(conn, req,
6941 case SMB_FILE_END_OF_FILE_INFORMATION:
6942 case SMB_SET_FILE_END_OF_FILE_INFO:
6944 status = smb_set_file_end_of_file_info(conn, req,
6953 case SMB_FILE_DISPOSITION_INFORMATION:
6954 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6957 /* JRA - We used to just ignore this on a path ?
6958 * Shouldn't this be invalid level on a pathname
6961 if (tran_call != TRANSACT2_SETFILEINFO) {
6962 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6965 status = smb_set_file_disposition_info(conn,
6974 case SMB_FILE_POSITION_INFORMATION:
6976 status = smb_file_position_information(conn,
6983 /* From tridge Samba4 :
6984 * MODE_INFORMATION in setfileinfo (I have no
6985 * idea what "mode information" on a file is - it takes a value of 0,
6986 * 2, 4 or 6. What could it be?).
6989 case SMB_FILE_MODE_INFORMATION:
6991 status = smb_file_mode_information(conn,
6998 * CIFS UNIX extensions.
7001 case SMB_SET_FILE_UNIX_BASIC:
7003 status = smb_set_file_unix_basic(conn, req,
7012 case SMB_SET_FILE_UNIX_INFO2:
7014 status = smb_set_file_unix_info2(conn, req,
7023 case SMB_SET_FILE_UNIX_LINK:
7025 if (tran_call != TRANSACT2_SETPATHINFO) {
7026 /* We must have a pathname for this. */
7027 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7030 status = smb_set_file_unix_link(conn, req, pdata,
7035 case SMB_SET_FILE_UNIX_HLINK:
7037 if (tran_call != TRANSACT2_SETPATHINFO || smb_fname == NULL) {
7038 /* We must have a pathname for this. */
7039 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7042 status = smb_set_file_unix_hlink(conn, req,
7048 case SMB_FILE_RENAME_INFORMATION:
7050 status = smb_file_rename_information(conn, req,
7056 #if defined(HAVE_POSIX_ACLS)
7057 case SMB_SET_POSIX_ACL:
7059 status = smb_set_posix_acl(conn,
7069 case SMB_SET_POSIX_LOCK:
7071 if (tran_call != TRANSACT2_SETFILEINFO) {
7072 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7075 status = smb_set_posix_lock(conn, req,
7076 pdata, total_data, fsp);
7080 case SMB_POSIX_PATH_OPEN:
7082 if (tran_call != TRANSACT2_SETPATHINFO) {
7083 /* We must have a pathname for this. */
7084 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7088 status = smb_posix_open(conn, req,
7097 case SMB_POSIX_PATH_UNLINK:
7099 if (tran_call != TRANSACT2_SETPATHINFO) {
7100 /* We must have a pathname for this. */
7101 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7105 status = smb_posix_unlink(conn, req,
7114 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7118 if (!NT_STATUS_IS_OK(status)) {
7119 if (open_was_deferred(req->mid)) {
7120 /* We have re-scheduled this call. */
7123 if (blocking_lock_was_deferred(req->mid)) {
7124 /* We have re-scheduled this call. */
7127 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7128 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7129 ERRSRV, ERRbadpath);
7132 if (info_level == SMB_POSIX_PATH_OPEN) {
7133 reply_openerror(req, status);
7137 reply_nterror(req, status);
7142 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7148 /****************************************************************************
7149 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7150 ****************************************************************************/
7152 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7153 char **pparams, int total_params,
7154 char **ppdata, int total_data,
7155 unsigned int max_data_bytes)
7157 struct smb_filename *smb_dname = NULL;
7158 char *params = *pparams;
7159 char *pdata = *ppdata;
7160 char *directory = NULL;
7161 NTSTATUS status = NT_STATUS_OK;
7162 struct ea_list *ea_list = NULL;
7163 TALLOC_CTX *ctx = talloc_tos();
7165 if (!CAN_WRITE(conn)) {
7166 reply_doserror(req, ERRSRV, ERRaccess);
7170 if (total_params < 5) {
7171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7175 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7176 total_params - 4, STR_TERMINATE,
7178 if (!NT_STATUS_IS_OK(status)) {
7179 reply_nterror(req, status);
7183 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7185 status = filename_convert(ctx,
7187 req->flags2 & FLAGS2_DFS_PATHNAMES,
7192 if (!NT_STATUS_IS_OK(status)) {
7193 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7194 reply_botherror(req,
7195 NT_STATUS_PATH_NOT_COVERED,
7196 ERRSRV, ERRbadpath);
7199 reply_nterror(req, status);
7203 /* Any data in this call is an EA list. */
7204 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7205 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7210 * OS/2 workplace shell seems to send SET_EA requests of "null"
7211 * length (4 bytes containing IVAL 4).
7212 * They seem to have no effect. Bug #3212. JRA.
7215 if (total_data != 4) {
7216 if (total_data < 10) {
7217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7221 if (IVAL(pdata,0) > total_data) {
7222 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7223 IVAL(pdata,0), (unsigned int)total_data));
7224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7228 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7231 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7235 /* If total_data == 4 Windows doesn't care what values
7236 * are placed in that field, it just ignores them.
7237 * The System i QNTC IBM SMB client puts bad values here,
7238 * so ignore them. */
7240 status = create_directory(conn, req, smb_dname);
7242 if (!NT_STATUS_IS_OK(status)) {
7243 reply_nterror(req, status);
7247 /* Try and set any given EA. */
7249 status = set_ea(conn, NULL, smb_dname->base_name, ea_list);
7250 if (!NT_STATUS_IS_OK(status)) {
7251 reply_nterror(req, status);
7256 /* Realloc the parameter and data sizes */
7257 *pparams = (char *)SMB_REALLOC(*pparams,2);
7258 if(*pparams == NULL) {
7259 reply_nterror(req, NT_STATUS_NO_MEMORY);
7266 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7269 TALLOC_FREE(smb_dname);
7273 /****************************************************************************
7274 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7275 We don't actually do this - we just send a null response.
7276 ****************************************************************************/
7278 static void call_trans2findnotifyfirst(connection_struct *conn,
7279 struct smb_request *req,
7280 char **pparams, int total_params,
7281 char **ppdata, int total_data,
7282 unsigned int max_data_bytes)
7284 char *params = *pparams;
7287 if (total_params < 6) {
7288 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7292 info_level = SVAL(params,4);
7293 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7295 switch (info_level) {
7300 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7304 /* Realloc the parameter and data sizes */
7305 *pparams = (char *)SMB_REALLOC(*pparams,6);
7306 if (*pparams == NULL) {
7307 reply_nterror(req, NT_STATUS_NO_MEMORY);
7312 SSVAL(params,0,fnf_handle);
7313 SSVAL(params,2,0); /* No changes */
7314 SSVAL(params,4,0); /* No EA errors */
7321 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7326 /****************************************************************************
7327 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7328 changes). Currently this does nothing.
7329 ****************************************************************************/
7331 static void call_trans2findnotifynext(connection_struct *conn,
7332 struct smb_request *req,
7333 char **pparams, int total_params,
7334 char **ppdata, int total_data,
7335 unsigned int max_data_bytes)
7337 char *params = *pparams;
7339 DEBUG(3,("call_trans2findnotifynext\n"));
7341 /* Realloc the parameter and data sizes */
7342 *pparams = (char *)SMB_REALLOC(*pparams,4);
7343 if (*pparams == NULL) {
7344 reply_nterror(req, NT_STATUS_NO_MEMORY);
7349 SSVAL(params,0,0); /* No changes */
7350 SSVAL(params,2,0); /* No EA errors */
7352 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7357 /****************************************************************************
7358 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7359 ****************************************************************************/
7361 static void call_trans2getdfsreferral(connection_struct *conn,
7362 struct smb_request *req,
7363 char **pparams, int total_params,
7364 char **ppdata, int total_data,
7365 unsigned int max_data_bytes)
7367 char *params = *pparams;
7368 char *pathname = NULL;
7370 int max_referral_level;
7371 NTSTATUS status = NT_STATUS_OK;
7372 TALLOC_CTX *ctx = talloc_tos();
7374 DEBUG(10,("call_trans2getdfsreferral\n"));
7376 if (total_params < 3) {
7377 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7381 max_referral_level = SVAL(params,0);
7383 if(!lp_host_msdfs()) {
7384 reply_doserror(req, ERRDOS, ERRbadfunc);
7388 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7389 total_params - 2, STR_TERMINATE);
7391 reply_nterror(req, NT_STATUS_NOT_FOUND);
7394 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7395 ppdata,&status)) < 0) {
7396 reply_nterror(req, status);
7400 SSVAL(req->inbuf, smb_flg2,
7401 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7402 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7407 #define LMCAT_SPL 0x53
7408 #define LMFUNC_GETJOBID 0x60
7410 /****************************************************************************
7411 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7412 ****************************************************************************/
7414 static void call_trans2ioctl(connection_struct *conn,
7415 struct smb_request *req,
7416 char **pparams, int total_params,
7417 char **ppdata, int total_data,
7418 unsigned int max_data_bytes)
7420 char *pdata = *ppdata;
7421 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7423 /* check for an invalid fid before proceeding */
7426 reply_doserror(req, ERRDOS, ERRbadfid);
7430 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7431 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7432 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7433 if (*ppdata == NULL) {
7434 reply_nterror(req, NT_STATUS_NO_MEMORY);
7439 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7440 CAN ACCEPT THIS IN UNICODE. JRA. */
7442 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7443 srvstr_push(pdata, req->flags2, pdata + 2,
7444 global_myname(), 15,
7445 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7446 srvstr_push(pdata, req->flags2, pdata+18,
7447 lp_servicename(SNUM(conn)), 13,
7448 STR_ASCII|STR_TERMINATE); /* Service name */
7449 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7454 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7455 reply_doserror(req, ERRSRV, ERRerror);
7458 /****************************************************************************
7459 Reply to a SMBfindclose (stop trans2 directory search).
7460 ****************************************************************************/
7462 void reply_findclose(struct smb_request *req)
7466 START_PROFILE(SMBfindclose);
7469 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7470 END_PROFILE(SMBfindclose);
7474 dptr_num = SVALS(req->vwv+0, 0);
7476 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7478 dptr_close(&dptr_num);
7480 reply_outbuf(req, 0, 0);
7482 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7484 END_PROFILE(SMBfindclose);
7488 /****************************************************************************
7489 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7490 ****************************************************************************/
7492 void reply_findnclose(struct smb_request *req)
7496 START_PROFILE(SMBfindnclose);
7499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7500 END_PROFILE(SMBfindnclose);
7504 dptr_num = SVAL(req->vwv+0, 0);
7506 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7508 /* We never give out valid handles for a
7509 findnotifyfirst - so any dptr_num is ok here.
7512 reply_outbuf(req, 0, 0);
7514 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7516 END_PROFILE(SMBfindnclose);
7520 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7521 struct trans_state *state)
7523 if (Protocol >= PROTOCOL_NT1) {
7524 req->flags2 |= 0x40; /* IS_LONG_NAME */
7525 SSVAL(req->inbuf,smb_flg2,req->flags2);
7528 if (conn->encrypt_level == Required && !req->encrypted) {
7529 if (state->call != TRANSACT2_QFSINFO &&
7530 state->call != TRANSACT2_SETFSINFO) {
7531 DEBUG(0,("handle_trans2: encryption required "
7533 (unsigned int)state->call));
7534 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7539 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7541 /* Now we must call the relevant TRANS2 function */
7542 switch(state->call) {
7543 case TRANSACT2_OPEN:
7545 START_PROFILE(Trans2_open);
7546 call_trans2open(conn, req,
7547 &state->param, state->total_param,
7548 &state->data, state->total_data,
7549 state->max_data_return);
7550 END_PROFILE(Trans2_open);
7554 case TRANSACT2_FINDFIRST:
7556 START_PROFILE(Trans2_findfirst);
7557 call_trans2findfirst(conn, req,
7558 &state->param, state->total_param,
7559 &state->data, state->total_data,
7560 state->max_data_return);
7561 END_PROFILE(Trans2_findfirst);
7565 case TRANSACT2_FINDNEXT:
7567 START_PROFILE(Trans2_findnext);
7568 call_trans2findnext(conn, req,
7569 &state->param, state->total_param,
7570 &state->data, state->total_data,
7571 state->max_data_return);
7572 END_PROFILE(Trans2_findnext);
7576 case TRANSACT2_QFSINFO:
7578 START_PROFILE(Trans2_qfsinfo);
7579 call_trans2qfsinfo(conn, req,
7580 &state->param, state->total_param,
7581 &state->data, state->total_data,
7582 state->max_data_return);
7583 END_PROFILE(Trans2_qfsinfo);
7587 case TRANSACT2_SETFSINFO:
7589 START_PROFILE(Trans2_setfsinfo);
7590 call_trans2setfsinfo(conn, req,
7591 &state->param, state->total_param,
7592 &state->data, state->total_data,
7593 state->max_data_return);
7594 END_PROFILE(Trans2_setfsinfo);
7598 case TRANSACT2_QPATHINFO:
7599 case TRANSACT2_QFILEINFO:
7601 START_PROFILE(Trans2_qpathinfo);
7602 call_trans2qfilepathinfo(conn, req, state->call,
7603 &state->param, state->total_param,
7604 &state->data, state->total_data,
7605 state->max_data_return);
7606 END_PROFILE(Trans2_qpathinfo);
7610 case TRANSACT2_SETPATHINFO:
7611 case TRANSACT2_SETFILEINFO:
7613 START_PROFILE(Trans2_setpathinfo);
7614 call_trans2setfilepathinfo(conn, req, state->call,
7615 &state->param, state->total_param,
7616 &state->data, state->total_data,
7617 state->max_data_return);
7618 END_PROFILE(Trans2_setpathinfo);
7622 case TRANSACT2_FINDNOTIFYFIRST:
7624 START_PROFILE(Trans2_findnotifyfirst);
7625 call_trans2findnotifyfirst(conn, req,
7626 &state->param, state->total_param,
7627 &state->data, state->total_data,
7628 state->max_data_return);
7629 END_PROFILE(Trans2_findnotifyfirst);
7633 case TRANSACT2_FINDNOTIFYNEXT:
7635 START_PROFILE(Trans2_findnotifynext);
7636 call_trans2findnotifynext(conn, req,
7637 &state->param, state->total_param,
7638 &state->data, state->total_data,
7639 state->max_data_return);
7640 END_PROFILE(Trans2_findnotifynext);
7644 case TRANSACT2_MKDIR:
7646 START_PROFILE(Trans2_mkdir);
7647 call_trans2mkdir(conn, req,
7648 &state->param, state->total_param,
7649 &state->data, state->total_data,
7650 state->max_data_return);
7651 END_PROFILE(Trans2_mkdir);
7655 case TRANSACT2_GET_DFS_REFERRAL:
7657 START_PROFILE(Trans2_get_dfs_referral);
7658 call_trans2getdfsreferral(conn, req,
7659 &state->param, state->total_param,
7660 &state->data, state->total_data,
7661 state->max_data_return);
7662 END_PROFILE(Trans2_get_dfs_referral);
7666 case TRANSACT2_IOCTL:
7668 START_PROFILE(Trans2_ioctl);
7669 call_trans2ioctl(conn, req,
7670 &state->param, state->total_param,
7671 &state->data, state->total_data,
7672 state->max_data_return);
7673 END_PROFILE(Trans2_ioctl);
7678 /* Error in request */
7679 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7680 reply_doserror(req, ERRSRV,ERRerror);
7684 /****************************************************************************
7685 Reply to a SMBtrans2.
7686 ****************************************************************************/
7688 void reply_trans2(struct smb_request *req)
7690 connection_struct *conn = req->conn;
7695 unsigned int tran_call;
7696 struct trans_state *state;
7699 START_PROFILE(SMBtrans2);
7701 if (req->wct < 14) {
7702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7703 END_PROFILE(SMBtrans2);
7707 dsoff = SVAL(req->vwv+12, 0);
7708 dscnt = SVAL(req->vwv+11, 0);
7709 psoff = SVAL(req->vwv+10, 0);
7710 pscnt = SVAL(req->vwv+9, 0);
7711 tran_call = SVAL(req->vwv+14, 0);
7713 result = allow_new_trans(conn->pending_trans, req->mid);
7714 if (!NT_STATUS_IS_OK(result)) {
7715 DEBUG(2, ("Got invalid trans2 request: %s\n",
7716 nt_errstr(result)));
7717 reply_nterror(req, result);
7718 END_PROFILE(SMBtrans2);
7723 switch (tran_call) {
7724 /* List the allowed trans2 calls on IPC$ */
7725 case TRANSACT2_OPEN:
7726 case TRANSACT2_GET_DFS_REFERRAL:
7727 case TRANSACT2_QFILEINFO:
7728 case TRANSACT2_QFSINFO:
7729 case TRANSACT2_SETFSINFO:
7732 reply_doserror(req, ERRSRV, ERRaccess);
7733 END_PROFILE(SMBtrans2);
7738 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7739 DEBUG(0, ("talloc failed\n"));
7740 reply_nterror(req, NT_STATUS_NO_MEMORY);
7741 END_PROFILE(SMBtrans2);
7745 state->cmd = SMBtrans2;
7747 state->mid = req->mid;
7748 state->vuid = req->vuid;
7749 state->setup_count = SVAL(req->vwv+13, 0);
7750 state->setup = NULL;
7751 state->total_param = SVAL(req->vwv+0, 0);
7752 state->param = NULL;
7753 state->total_data = SVAL(req->vwv+1, 0);
7755 state->max_param_return = SVAL(req->vwv+2, 0);
7756 state->max_data_return = SVAL(req->vwv+3, 0);
7757 state->max_setup_return = SVAL(req->vwv+4, 0);
7758 state->close_on_completion = BITSETW(req->vwv+5, 0);
7759 state->one_way = BITSETW(req->vwv+5, 1);
7761 state->call = tran_call;
7763 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7764 is so as a sanity check */
7765 if (state->setup_count != 1) {
7767 * Need to have rc=0 for ioctl to get job id for OS/2.
7768 * Network printing will fail if function is not successful.
7769 * Similar function in reply.c will be used if protocol
7770 * is LANMAN1.0 instead of LM1.2X002.
7771 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7772 * outbuf doesn't have to be set(only job id is used).
7774 if ( (state->setup_count == 4)
7775 && (tran_call == TRANSACT2_IOCTL)
7776 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7777 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7778 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7780 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7781 DEBUG(2,("Transaction is %d\n",tran_call));
7783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7784 END_PROFILE(SMBtrans2);
7789 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7792 if (state->total_data) {
7794 if (trans_oob(state->total_data, 0, dscnt)
7795 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7799 /* Can't use talloc here, the core routines do realloc on the
7800 * params and data. */
7801 state->data = (char *)SMB_MALLOC(state->total_data);
7802 if (state->data == NULL) {
7803 DEBUG(0,("reply_trans2: data malloc fail for %u "
7804 "bytes !\n", (unsigned int)state->total_data));
7806 reply_nterror(req, NT_STATUS_NO_MEMORY);
7807 END_PROFILE(SMBtrans2);
7811 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7814 if (state->total_param) {
7816 if (trans_oob(state->total_param, 0, pscnt)
7817 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7821 /* Can't use talloc here, the core routines do realloc on the
7822 * params and data. */
7823 state->param = (char *)SMB_MALLOC(state->total_param);
7824 if (state->param == NULL) {
7825 DEBUG(0,("reply_trans: param malloc fail for %u "
7826 "bytes !\n", (unsigned int)state->total_param));
7827 SAFE_FREE(state->data);
7829 reply_nterror(req, NT_STATUS_NO_MEMORY);
7830 END_PROFILE(SMBtrans2);
7834 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7837 state->received_data = dscnt;
7838 state->received_param = pscnt;
7840 if ((state->received_param == state->total_param) &&
7841 (state->received_data == state->total_data)) {
7843 handle_trans2(conn, req, state);
7845 SAFE_FREE(state->data);
7846 SAFE_FREE(state->param);
7848 END_PROFILE(SMBtrans2);
7852 DLIST_ADD(conn->pending_trans, state);
7854 /* We need to send an interim response then receive the rest
7855 of the parameter/data bytes */
7856 reply_outbuf(req, 0, 0);
7857 show_msg((char *)req->outbuf);
7858 END_PROFILE(SMBtrans2);
7863 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7864 SAFE_FREE(state->data);
7865 SAFE_FREE(state->param);
7867 END_PROFILE(SMBtrans2);
7868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7872 /****************************************************************************
7873 Reply to a SMBtranss2
7874 ****************************************************************************/
7876 void reply_transs2(struct smb_request *req)
7878 connection_struct *conn = req->conn;
7879 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7880 struct trans_state *state;
7882 START_PROFILE(SMBtranss2);
7884 show_msg((char *)req->inbuf);
7887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7888 END_PROFILE(SMBtranss2);
7892 for (state = conn->pending_trans; state != NULL;
7893 state = state->next) {
7894 if (state->mid == req->mid) {
7899 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7901 END_PROFILE(SMBtranss2);
7905 /* Revise state->total_param and state->total_data in case they have
7906 changed downwards */
7908 if (SVAL(req->vwv+0, 0) < state->total_param)
7909 state->total_param = SVAL(req->vwv+0, 0);
7910 if (SVAL(req->vwv+1, 0) < state->total_data)
7911 state->total_data = SVAL(req->vwv+1, 0);
7913 pcnt = SVAL(req->vwv+2, 0);
7914 poff = SVAL(req->vwv+3, 0);
7915 pdisp = SVAL(req->vwv+4, 0);
7917 dcnt = SVAL(req->vwv+5, 0);
7918 doff = SVAL(req->vwv+6, 0);
7919 ddisp = SVAL(req->vwv+7, 0);
7921 state->received_param += pcnt;
7922 state->received_data += dcnt;
7924 if ((state->received_data > state->total_data) ||
7925 (state->received_param > state->total_param))
7929 if (trans_oob(state->total_param, pdisp, pcnt)
7930 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7933 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7937 if (trans_oob(state->total_data, ddisp, dcnt)
7938 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7941 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7944 if ((state->received_param < state->total_param) ||
7945 (state->received_data < state->total_data)) {
7946 END_PROFILE(SMBtranss2);
7950 handle_trans2(conn, req, state);
7952 DLIST_REMOVE(conn->pending_trans, state);
7953 SAFE_FREE(state->data);
7954 SAFE_FREE(state->param);
7957 END_PROFILE(SMBtranss2);
7962 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7963 DLIST_REMOVE(conn->pending_trans, state);
7964 SAFE_FREE(state->data);
7965 SAFE_FREE(state->param);
7967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7968 END_PROFILE(SMBtranss2);