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 (vfs_lstat_smb_fname(conn, pathreal,
1400 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1401 pathreal,strerror(errno)));
1402 TALLOC_FREE(pathreal);
1406 } else if (!VALID_STAT(sbuf) &&
1407 vfs_stat_smb_fname(conn, pathreal,
1409 /* Needed to show the msdfs symlinks as
1412 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1414 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1415 pathreal,strerror(errno)));
1416 TALLOC_FREE(pathreal);
1423 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1425 mode = dos_mode(conn,pathreal,&sbuf);
1428 if (!dir_check_ftype(conn,mode,dirtype)) {
1429 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1430 TALLOC_FREE(pathreal);
1435 if (!(mode & aDIR)) {
1436 file_size = get_file_size_stat(&sbuf);
1438 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1440 mdate_ts = sbuf.st_ex_mtime;
1441 adate_ts = sbuf.st_ex_atime;
1442 create_date_ts = sbuf.st_ex_btime;
1444 if (ask_sharemode) {
1445 struct timespec write_time_ts;
1446 struct file_id fileid;
1448 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1449 get_file_infos(fileid, NULL, &write_time_ts);
1450 if (!null_timespec(write_time_ts)) {
1451 mdate_ts = write_time_ts;
1455 if (lp_dos_filetime_resolution(SNUM(conn))) {
1456 dos_filetime_timespec(&create_date_ts);
1457 dos_filetime_timespec(&mdate_ts);
1458 dos_filetime_timespec(&adate_ts);
1461 create_date = convert_timespec_to_time_t(create_date_ts);
1462 mdate = convert_timespec_to_time_t(mdate_ts);
1463 adate = convert_timespec_to_time_t(adate_ts);
1465 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1470 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1480 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1482 switch (info_level) {
1483 case SMB_FIND_INFO_STANDARD:
1484 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1485 if(requires_resume_key) {
1489 srv_put_dos_date2(p,0,create_date);
1490 srv_put_dos_date2(p,4,adate);
1491 srv_put_dos_date2(p,8,mdate);
1492 SIVAL(p,12,(uint32)file_size);
1493 SIVAL(p,16,(uint32)allocation_size);
1497 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1498 p += ucs2_align(base_data, p, 0);
1500 len = srvstr_push(base_data, flags2, p,
1501 fname, PTR_DIFF(end_data, p),
1503 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1505 SCVAL(nameptr, -1, len - 2);
1507 SCVAL(nameptr, -1, 0);
1511 SCVAL(nameptr, -1, len - 1);
1513 SCVAL(nameptr, -1, 0);
1519 case SMB_FIND_EA_SIZE:
1520 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1521 if(requires_resume_key) {
1525 srv_put_dos_date2(p,0,create_date);
1526 srv_put_dos_date2(p,4,adate);
1527 srv_put_dos_date2(p,8,mdate);
1528 SIVAL(p,12,(uint32)file_size);
1529 SIVAL(p,16,(uint32)allocation_size);
1532 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1533 SIVAL(p,22,ea_size); /* Extended attributes */
1537 len = srvstr_push(base_data, flags2,
1538 p, fname, PTR_DIFF(end_data, p),
1539 STR_TERMINATE | STR_NOALIGN);
1540 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1553 SCVAL(nameptr,0,len);
1555 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1558 case SMB_FIND_EA_LIST:
1560 struct ea_list *file_list = NULL;
1563 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1567 if(requires_resume_key) {
1571 srv_put_dos_date2(p,0,create_date);
1572 srv_put_dos_date2(p,4,adate);
1573 srv_put_dos_date2(p,8,mdate);
1574 SIVAL(p,12,(uint32)file_size);
1575 SIVAL(p,16,(uint32)allocation_size);
1577 p += 22; /* p now points to the EA area. */
1579 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1580 name_list = ea_list_union(name_list, file_list, &ea_len);
1582 /* We need to determine if this entry will fit in the space available. */
1583 /* Max string size is 255 bytes. */
1584 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1585 /* Move the dirptr back to prev_dirpos */
1586 dptr_SeekDir(conn->dirptr, prev_dirpos);
1587 *out_of_space = True;
1588 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1589 return False; /* Not finished - just out of space */
1592 /* Push the ea_data followed by the name. */
1593 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1595 len = srvstr_push(base_data, flags2,
1596 p + 1, fname, PTR_DIFF(end_data, p+1),
1597 STR_TERMINATE | STR_NOALIGN);
1598 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1611 SCVAL(nameptr,0,len);
1613 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1617 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1618 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1619 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1621 SIVAL(p,0,reskey); p += 4;
1622 put_long_date_timespec(p,create_date_ts); p += 8;
1623 put_long_date_timespec(p,adate_ts); p += 8;
1624 put_long_date_timespec(p,mdate_ts); p += 8;
1625 put_long_date_timespec(p,mdate_ts); p += 8;
1626 SOFF_T(p,0,file_size); p += 8;
1627 SOFF_T(p,0,allocation_size); p += 8;
1628 SIVAL(p,0,nt_extmode); p += 4;
1629 q = p; p += 4; /* q is placeholder for name length. */
1631 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1632 SIVAL(p,0,ea_size); /* Extended attributes */
1635 /* Clear the short name buffer. This is
1636 * IMPORTANT as not doing so will trigger
1637 * a Win2k client bug. JRA.
1639 if (!was_8_3 && check_mangled_names) {
1640 if (!name_to_8_3(fname,mangled_name,True,
1642 /* Error - mangle failed ! */
1643 memset(mangled_name,'\0',12);
1645 mangled_name[12] = 0;
1646 len = srvstr_push(base_data, flags2,
1647 p+2, mangled_name, 24,
1648 STR_UPPER|STR_UNICODE);
1650 memset(p + 2 + len,'\0',24 - len);
1657 len = srvstr_push(base_data, flags2, p,
1658 fname, PTR_DIFF(end_data, p),
1659 STR_TERMINATE_ASCII);
1662 SIVAL(p,0,0); /* Ensure any padding is null. */
1663 len = PTR_DIFF(p, pdata);
1664 len = (len + 3) & ~3;
1669 case SMB_FIND_FILE_DIRECTORY_INFO:
1670 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1672 SIVAL(p,0,reskey); p += 4;
1673 put_long_date_timespec(p,create_date_ts); p += 8;
1674 put_long_date_timespec(p,adate_ts); p += 8;
1675 put_long_date_timespec(p,mdate_ts); p += 8;
1676 put_long_date_timespec(p,mdate_ts); p += 8;
1677 SOFF_T(p,0,file_size); p += 8;
1678 SOFF_T(p,0,allocation_size); p += 8;
1679 SIVAL(p,0,nt_extmode); p += 4;
1680 len = srvstr_push(base_data, flags2,
1681 p + 4, fname, PTR_DIFF(end_data, p+4),
1682 STR_TERMINATE_ASCII);
1685 SIVAL(p,0,0); /* Ensure any padding is null. */
1686 len = PTR_DIFF(p, pdata);
1687 len = (len + 3) & ~3;
1692 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1693 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1695 SIVAL(p,0,reskey); p += 4;
1696 put_long_date_timespec(p,create_date_ts); p += 8;
1697 put_long_date_timespec(p,adate_ts); p += 8;
1698 put_long_date_timespec(p,mdate_ts); p += 8;
1699 put_long_date_timespec(p,mdate_ts); p += 8;
1700 SOFF_T(p,0,file_size); p += 8;
1701 SOFF_T(p,0,allocation_size); p += 8;
1702 SIVAL(p,0,nt_extmode); p += 4;
1703 q = p; p += 4; /* q is placeholder for name length. */
1705 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1706 SIVAL(p,0,ea_size); /* Extended attributes */
1709 len = srvstr_push(base_data, flags2, p,
1710 fname, PTR_DIFF(end_data, p),
1711 STR_TERMINATE_ASCII);
1715 SIVAL(p,0,0); /* Ensure any padding is null. */
1716 len = PTR_DIFF(p, pdata);
1717 len = (len + 3) & ~3;
1722 case SMB_FIND_FILE_NAMES_INFO:
1723 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1725 SIVAL(p,0,reskey); p += 4;
1727 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1728 acl on a dir (tridge) */
1729 len = srvstr_push(base_data, flags2, p,
1730 fname, PTR_DIFF(end_data, p),
1731 STR_TERMINATE_ASCII);
1734 SIVAL(p,0,0); /* Ensure any padding is null. */
1735 len = PTR_DIFF(p, pdata);
1736 len = (len + 3) & ~3;
1741 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1742 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1744 SIVAL(p,0,reskey); p += 4;
1745 put_long_date_timespec(p,create_date_ts); p += 8;
1746 put_long_date_timespec(p,adate_ts); p += 8;
1747 put_long_date_timespec(p,mdate_ts); p += 8;
1748 put_long_date_timespec(p,mdate_ts); p += 8;
1749 SOFF_T(p,0,file_size); p += 8;
1750 SOFF_T(p,0,allocation_size); p += 8;
1751 SIVAL(p,0,nt_extmode); p += 4;
1752 q = p; p += 4; /* q is placeholder for name length. */
1754 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1755 SIVAL(p,0,ea_size); /* Extended attributes */
1758 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1759 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1760 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1761 len = srvstr_push(base_data, flags2, p,
1762 fname, PTR_DIFF(end_data, p),
1763 STR_TERMINATE_ASCII);
1766 SIVAL(p,0,0); /* Ensure any padding is null. */
1767 len = PTR_DIFF(p, pdata);
1768 len = (len + 3) & ~3;
1773 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1774 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1775 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1777 SIVAL(p,0,reskey); p += 4;
1778 put_long_date_timespec(p,create_date_ts); p += 8;
1779 put_long_date_timespec(p,adate_ts); p += 8;
1780 put_long_date_timespec(p,mdate_ts); p += 8;
1781 put_long_date_timespec(p,mdate_ts); p += 8;
1782 SOFF_T(p,0,file_size); p += 8;
1783 SOFF_T(p,0,allocation_size); p += 8;
1784 SIVAL(p,0,nt_extmode); p += 4;
1785 q = p; p += 4; /* q is placeholder for name length */
1787 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1788 SIVAL(p,0,ea_size); /* Extended attributes */
1791 /* Clear the short name buffer. This is
1792 * IMPORTANT as not doing so will trigger
1793 * a Win2k client bug. JRA.
1795 if (!was_8_3 && check_mangled_names) {
1796 if (!name_to_8_3(fname,mangled_name,True,
1798 /* Error - mangle failed ! */
1799 memset(mangled_name,'\0',12);
1801 mangled_name[12] = 0;
1802 len = srvstr_push(base_data, flags2,
1803 p+2, mangled_name, 24,
1804 STR_UPPER|STR_UNICODE);
1807 memset(p + 2 + len,'\0',24 - len);
1814 SSVAL(p,0,0); p += 2; /* Reserved ? */
1815 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1816 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1817 len = srvstr_push(base_data, flags2, p,
1818 fname, PTR_DIFF(end_data, p),
1819 STR_TERMINATE_ASCII);
1822 SIVAL(p,0,0); /* Ensure any padding is null. */
1823 len = PTR_DIFF(p, pdata);
1824 len = (len + 3) & ~3;
1829 /* CIFS UNIX Extension. */
1831 case SMB_FIND_FILE_UNIX:
1832 case SMB_FIND_FILE_UNIX_INFO2:
1834 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1836 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1838 if (info_level == SMB_FIND_FILE_UNIX) {
1839 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1840 p = store_file_unix_basic(conn, p,
1842 len = srvstr_push(base_data, flags2, p,
1843 fname, PTR_DIFF(end_data, p),
1846 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1847 p = store_file_unix_basic_info2(conn, p,
1851 len = srvstr_push(base_data, flags2, p, fname,
1852 PTR_DIFF(end_data, p), 0);
1853 SIVAL(nameptr, 0, len);
1857 SIVAL(p,0,0); /* Ensure any padding is null. */
1859 len = PTR_DIFF(p, pdata);
1860 len = (len + 3) & ~3;
1861 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1863 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1873 if (PTR_DIFF(p,pdata) > space_remaining) {
1874 /* Move the dirptr back to prev_dirpos */
1875 dptr_SeekDir(conn->dirptr, prev_dirpos);
1876 *out_of_space = True;
1877 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1878 return False; /* Not finished - just out of space */
1881 /* Setup the last entry pointer, as an offset from base_data */
1882 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1883 /* Advance the data pointer to the next slot */
1889 /****************************************************************************
1890 Reply to a TRANS2_FINDFIRST.
1891 ****************************************************************************/
1893 static void call_trans2findfirst(connection_struct *conn,
1894 struct smb_request *req,
1895 char **pparams, int total_params,
1896 char **ppdata, int total_data,
1897 unsigned int max_data_bytes)
1899 /* We must be careful here that we don't return more than the
1900 allowed number of data bytes. If this means returning fewer than
1901 maxentries then so be it. We assume that the redirector has
1902 enough room for the fixed number of parameter bytes it has
1904 struct smb_filename *smb_dname = NULL;
1905 char *params = *pparams;
1906 char *pdata = *ppdata;
1910 uint16 findfirst_flags;
1911 bool close_after_first;
1913 bool requires_resume_key;
1915 char *directory = NULL;
1918 int last_entry_off=0;
1922 bool finished = False;
1923 bool dont_descend = False;
1924 bool out_of_space = False;
1925 int space_remaining;
1926 bool mask_contains_wcard = False;
1927 struct ea_list *ea_list = NULL;
1928 NTSTATUS ntstatus = NT_STATUS_OK;
1929 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1930 TALLOC_CTX *ctx = talloc_tos();
1932 if (total_params < 13) {
1933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1937 dirtype = SVAL(params,0);
1938 maxentries = SVAL(params,2);
1939 findfirst_flags = SVAL(params,4);
1940 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1941 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1942 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1943 info_level = SVAL(params,6);
1945 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1946 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1947 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1948 info_level, max_data_bytes));
1951 /* W2K3 seems to treat zero as 1. */
1955 switch (info_level) {
1956 case SMB_FIND_INFO_STANDARD:
1957 case SMB_FIND_EA_SIZE:
1958 case SMB_FIND_EA_LIST:
1959 case SMB_FIND_FILE_DIRECTORY_INFO:
1960 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1961 case SMB_FIND_FILE_NAMES_INFO:
1962 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1963 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1964 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1966 case SMB_FIND_FILE_UNIX:
1967 case SMB_FIND_FILE_UNIX_INFO2:
1968 /* Always use filesystem for UNIX mtime query. */
1969 ask_sharemode = false;
1970 if (!lp_unix_extensions()) {
1971 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1976 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1980 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1981 params+12, total_params - 12,
1982 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1983 if (!NT_STATUS_IS_OK(ntstatus)) {
1984 reply_nterror(req, ntstatus);
1988 ntstatus = resolve_dfspath_wcard(ctx, conn,
1989 req->flags2 & FLAGS2_DFS_PATHNAMES,
1992 &mask_contains_wcard);
1993 if (!NT_STATUS_IS_OK(ntstatus)) {
1994 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1995 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1996 ERRSRV, ERRbadpath);
1999 reply_nterror(req, ntstatus);
2003 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2004 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2005 if (!NT_STATUS_IS_OK(ntstatus)) {
2006 reply_nterror(req, ntstatus);
2010 mask = smb_dname->original_lcomp;
2012 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2013 TALLOC_FREE(smb_dname);
2014 if (!NT_STATUS_IS_OK(ntstatus)) {
2015 reply_nterror(req, ntstatus);
2019 ntstatus = check_name(conn, directory);
2020 if (!NT_STATUS_IS_OK(ntstatus)) {
2021 reply_nterror(req, ntstatus);
2025 p = strrchr_m(directory,'/');
2027 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2028 if((directory[0] == '.') && (directory[1] == '\0')) {
2029 mask = talloc_strdup(ctx,"*");
2031 reply_nterror(req, NT_STATUS_NO_MEMORY);
2034 mask_contains_wcard = True;
2036 directory = talloc_strdup(talloc_tos(), "./");
2038 reply_nterror(req, NT_STATUS_NO_MEMORY);
2045 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2047 if (info_level == SMB_FIND_EA_LIST) {
2050 if (total_data < 4) {
2051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2055 ea_size = IVAL(pdata,0);
2056 if (ea_size != total_data) {
2057 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2058 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2059 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2063 if (!lp_ea_support(SNUM(conn))) {
2064 reply_doserror(req, ERRDOS, ERReasnotsupported);
2068 /* Pull out the list of names. */
2069 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2076 *ppdata = (char *)SMB_REALLOC(
2077 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2078 if(*ppdata == NULL ) {
2079 reply_nterror(req, NT_STATUS_NO_MEMORY);
2083 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2085 /* Realloc the params space */
2086 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2087 if (*pparams == NULL) {
2088 reply_nterror(req, NT_STATUS_NO_MEMORY);
2093 /* Save the wildcard match and attribs we are using on this directory -
2094 needed as lanman2 assumes these are being saved between calls */
2096 ntstatus = dptr_create(conn,
2102 mask_contains_wcard,
2106 if (!NT_STATUS_IS_OK(ntstatus)) {
2107 reply_nterror(req, ntstatus);
2111 dptr_num = dptr_dnum(conn->dirptr);
2112 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2114 /* Initialize per TRANS2_FIND_FIRST operation data */
2115 dptr_init_search_op(conn->dirptr);
2117 /* We don't need to check for VOL here as this is returned by
2118 a different TRANS2 call. */
2120 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2121 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2122 dont_descend = True;
2125 space_remaining = max_data_bytes;
2126 out_of_space = False;
2128 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2129 bool got_exact_match = False;
2131 /* this is a heuristic to avoid seeking the dirptr except when
2132 absolutely necessary. It allows for a filename of about 40 chars */
2133 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2134 out_of_space = True;
2137 finished = !get_lanman2_dir_entry(ctx,
2140 mask,dirtype,info_level,
2141 requires_resume_key,dont_descend,
2144 space_remaining, &out_of_space,
2146 &last_entry_off, ea_list);
2149 if (finished && out_of_space)
2152 if (!finished && !out_of_space)
2156 * As an optimisation if we know we aren't looking
2157 * for a wildcard name (ie. the name matches the wildcard exactly)
2158 * then we can finish on any (first) match.
2159 * This speeds up large directory searches. JRA.
2165 /* Ensure space_remaining never goes -ve. */
2166 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2167 space_remaining = 0;
2168 out_of_space = true;
2170 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2174 /* Check if we can close the dirptr */
2175 if(close_after_first || (finished && close_if_end)) {
2176 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2177 dptr_close(&dptr_num);
2181 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2182 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2183 * the protocol level is less than NT1. Tested with smbclient. JRA.
2184 * This should fix the OS/2 client bug #2335.
2187 if(numentries == 0) {
2188 dptr_close(&dptr_num);
2189 if (Protocol < PROTOCOL_NT1) {
2190 reply_doserror(req, ERRDOS, ERRnofiles);
2193 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2194 ERRDOS, ERRbadfile);
2199 /* At this point pdata points to numentries directory entries. */
2201 /* Set up the return parameter block */
2202 SSVAL(params,0,dptr_num);
2203 SSVAL(params,2,numentries);
2204 SSVAL(params,4,finished);
2205 SSVAL(params,6,0); /* Never an EA error */
2206 SSVAL(params,8,last_entry_off);
2208 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2211 if ((! *directory) && dptr_path(dptr_num)) {
2212 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2214 reply_nterror(req, NT_STATUS_NO_MEMORY);
2218 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2219 smb_fn_name(req->cmd),
2220 mask, directory, dirtype, numentries ) );
2223 * Force a name mangle here to ensure that the
2224 * mask as an 8.3 name is top of the mangled cache.
2225 * The reasons for this are subtle. Don't remove
2226 * this code unless you know what you are doing
2227 * (see PR#13758). JRA.
2230 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2231 char mangled_name[13];
2232 name_to_8_3(mask, mangled_name, True, conn->params);
2238 /****************************************************************************
2239 Reply to a TRANS2_FINDNEXT.
2240 ****************************************************************************/
2242 static void call_trans2findnext(connection_struct *conn,
2243 struct smb_request *req,
2244 char **pparams, int total_params,
2245 char **ppdata, int total_data,
2246 unsigned int max_data_bytes)
2248 /* We must be careful here that we don't return more than the
2249 allowed number of data bytes. If this means returning fewer than
2250 maxentries then so be it. We assume that the redirector has
2251 enough room for the fixed number of parameter bytes it has
2253 char *params = *pparams;
2254 char *pdata = *ppdata;
2260 uint16 findnext_flags;
2261 bool close_after_request;
2263 bool requires_resume_key;
2265 bool mask_contains_wcard = False;
2266 char *resume_name = NULL;
2267 const char *mask = NULL;
2268 const char *directory = NULL;
2272 int i, last_entry_off=0;
2273 bool finished = False;
2274 bool dont_descend = False;
2275 bool out_of_space = False;
2276 int space_remaining;
2277 struct ea_list *ea_list = NULL;
2278 NTSTATUS ntstatus = NT_STATUS_OK;
2279 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2280 TALLOC_CTX *ctx = talloc_tos();
2282 if (total_params < 13) {
2283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2287 dptr_num = SVAL(params,0);
2288 maxentries = SVAL(params,2);
2289 info_level = SVAL(params,4);
2290 resume_key = IVAL(params,6);
2291 findnext_flags = SVAL(params,10);
2292 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2293 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2294 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2295 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2297 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2299 total_params - 12, STR_TERMINATE, &ntstatus,
2300 &mask_contains_wcard);
2301 if (!NT_STATUS_IS_OK(ntstatus)) {
2302 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2303 complain (it thinks we're asking for the directory above the shared
2304 path or an invalid name). Catch this as the resume name is only compared, never used in
2305 a file access. JRA. */
2306 srvstr_pull_talloc(ctx, params, req->flags2,
2307 &resume_name, params+12,
2311 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2312 reply_nterror(req, ntstatus);
2317 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2318 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2319 resume_key = %d resume name = %s continue=%d level = %d\n",
2320 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2321 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2324 /* W2K3 seems to treat zero as 1. */
2328 switch (info_level) {
2329 case SMB_FIND_INFO_STANDARD:
2330 case SMB_FIND_EA_SIZE:
2331 case SMB_FIND_EA_LIST:
2332 case SMB_FIND_FILE_DIRECTORY_INFO:
2333 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2334 case SMB_FIND_FILE_NAMES_INFO:
2335 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2336 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2337 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2339 case SMB_FIND_FILE_UNIX:
2340 case SMB_FIND_FILE_UNIX_INFO2:
2341 /* Always use filesystem for UNIX mtime query. */
2342 ask_sharemode = false;
2343 if (!lp_unix_extensions()) {
2344 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2349 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2353 if (info_level == SMB_FIND_EA_LIST) {
2356 if (total_data < 4) {
2357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2361 ea_size = IVAL(pdata,0);
2362 if (ea_size != total_data) {
2363 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2364 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2369 if (!lp_ea_support(SNUM(conn))) {
2370 reply_doserror(req, ERRDOS, ERReasnotsupported);
2374 /* Pull out the list of names. */
2375 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2377 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2382 *ppdata = (char *)SMB_REALLOC(
2383 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2384 if(*ppdata == NULL) {
2385 reply_nterror(req, NT_STATUS_NO_MEMORY);
2390 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2392 /* Realloc the params space */
2393 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2394 if(*pparams == NULL ) {
2395 reply_nterror(req, NT_STATUS_NO_MEMORY);
2401 /* Check that the dptr is valid */
2402 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2403 reply_doserror(req, ERRDOS, ERRnofiles);
2407 string_set(&conn->dirpath,dptr_path(dptr_num));
2409 /* Get the wildcard mask from the dptr */
2410 if((p = dptr_wcard(dptr_num))== NULL) {
2411 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2412 reply_doserror(req, ERRDOS, ERRnofiles);
2417 directory = conn->dirpath;
2419 /* Get the attr mask from the dptr */
2420 dirtype = dptr_attr(dptr_num);
2422 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2423 dptr_num, mask, dirtype,
2425 dptr_TellDir(conn->dirptr)));
2427 /* Initialize per TRANS2_FIND_NEXT operation data */
2428 dptr_init_search_op(conn->dirptr);
2430 /* We don't need to check for VOL here as this is returned by
2431 a different TRANS2 call. */
2433 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2434 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2435 dont_descend = True;
2438 space_remaining = max_data_bytes;
2439 out_of_space = False;
2442 * Seek to the correct position. We no longer use the resume key but
2443 * depend on the last file name instead.
2446 if(*resume_name && !continue_bit) {
2449 long current_pos = 0;
2451 * Remember, name_to_8_3 is called by
2452 * get_lanman2_dir_entry(), so the resume name
2453 * could be mangled. Ensure we check the unmangled name.
2456 if (mangle_is_mangled(resume_name, conn->params)) {
2457 char *new_resume_name = NULL;
2458 mangle_lookup_name_from_8_3(ctx,
2462 if (new_resume_name) {
2463 resume_name = new_resume_name;
2468 * Fix for NT redirector problem triggered by resume key indexes
2469 * changing between directory scans. We now return a resume key of 0
2470 * and instead look for the filename to continue from (also given
2471 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2472 * findfirst/findnext (as is usual) then the directory pointer
2473 * should already be at the correct place.
2476 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2477 } /* end if resume_name && !continue_bit */
2479 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2480 bool got_exact_match = False;
2482 /* this is a heuristic to avoid seeking the dirptr except when
2483 absolutely necessary. It allows for a filename of about 40 chars */
2484 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2485 out_of_space = True;
2488 finished = !get_lanman2_dir_entry(ctx,
2491 mask,dirtype,info_level,
2492 requires_resume_key,dont_descend,
2495 space_remaining, &out_of_space,
2497 &last_entry_off, ea_list);
2500 if (finished && out_of_space)
2503 if (!finished && !out_of_space)
2507 * As an optimisation if we know we aren't looking
2508 * for a wildcard name (ie. the name matches the wildcard exactly)
2509 * then we can finish on any (first) match.
2510 * This speeds up large directory searches. JRA.
2516 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2519 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2520 smb_fn_name(req->cmd),
2521 mask, directory, dirtype, numentries ) );
2523 /* Check if we can close the dirptr */
2524 if(close_after_request || (finished && close_if_end)) {
2525 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2526 dptr_close(&dptr_num); /* This frees up the saved mask */
2529 /* Set up the return parameter block */
2530 SSVAL(params,0,numentries);
2531 SSVAL(params,2,finished);
2532 SSVAL(params,4,0); /* Never an EA error */
2533 SSVAL(params,6,last_entry_off);
2535 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2541 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2543 E_md4hash(lp_servicename(SNUM(conn)),objid);
2547 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2549 SMB_ASSERT(extended_info != NULL);
2551 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2552 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2553 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2554 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2555 #ifdef SAMBA_VERSION_REVISION
2556 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2558 extended_info->samba_subversion = 0;
2559 #ifdef SAMBA_VERSION_RC_RELEASE
2560 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2562 #ifdef SAMBA_VERSION_PRE_RELEASE
2563 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2566 #ifdef SAMBA_VERSION_VENDOR_PATCH
2567 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2569 extended_info->samba_gitcommitdate = 0;
2570 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2571 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2574 memset(extended_info->samba_version_string, 0,
2575 sizeof(extended_info->samba_version_string));
2577 snprintf (extended_info->samba_version_string,
2578 sizeof(extended_info->samba_version_string),
2579 "%s", samba_version_string());
2582 /****************************************************************************
2583 Reply to a TRANS2_QFSINFO (query filesystem info).
2584 ****************************************************************************/
2586 static void call_trans2qfsinfo(connection_struct *conn,
2587 struct smb_request *req,
2588 char **pparams, int total_params,
2589 char **ppdata, int total_data,
2590 unsigned int max_data_bytes)
2592 char *pdata, *end_data;
2593 char *params = *pparams;
2597 const char *vname = volume_label(SNUM(conn));
2598 int snum = SNUM(conn);
2599 char *fstype = lp_fstype(SNUM(conn));
2600 uint32 additional_flags = 0;
2602 if (total_params < 2) {
2603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2607 info_level = SVAL(params,0);
2610 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2611 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2612 "info level (0x%x) on IPC$.\n",
2613 (unsigned int)info_level));
2614 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2619 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2620 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2621 DEBUG(0,("call_trans2qfsinfo: encryption required "
2622 "and info level 0x%x sent.\n",
2623 (unsigned int)info_level));
2624 exit_server_cleanly("encryption required "
2630 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2632 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
2633 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2634 reply_doserror(req, ERRSRV, ERRinvdevice);
2638 *ppdata = (char *)SMB_REALLOC(
2639 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2640 if (*ppdata == NULL ) {
2641 reply_nterror(req, NT_STATUS_NO_MEMORY);
2646 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2647 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2649 switch (info_level) {
2650 case SMB_INFO_ALLOCATION:
2652 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2654 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2655 reply_unixerror(req, ERRHRD, ERRgeneral);
2659 block_size = lp_block_size(snum);
2660 if (bsize < block_size) {
2661 uint64_t factor = block_size/bsize;
2666 if (bsize > block_size) {
2667 uint64_t factor = bsize/block_size;
2672 bytes_per_sector = 512;
2673 sectors_per_unit = bsize/bytes_per_sector;
2675 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2676 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2677 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2679 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2680 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2681 SIVAL(pdata,l1_cUnit,dsize);
2682 SIVAL(pdata,l1_cUnitAvail,dfree);
2683 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2687 case SMB_INFO_VOLUME:
2688 /* Return volume name */
2690 * Add volume serial number - hash of a combination of
2691 * the called hostname and the service name.
2693 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2695 * Win2k3 and previous mess this up by sending a name length
2696 * one byte short. I believe only older clients (OS/2 Win9x) use
2697 * this call so try fixing this by adding a terminating null to
2698 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2702 pdata+l2_vol_szVolLabel, vname,
2703 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2704 STR_NOALIGN|STR_TERMINATE);
2705 SCVAL(pdata,l2_vol_cch,len);
2706 data_len = l2_vol_szVolLabel + len;
2707 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2708 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2712 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2713 case SMB_FS_ATTRIBUTE_INFORMATION:
2715 additional_flags = 0;
2716 #if defined(HAVE_SYS_QUOTAS)
2717 additional_flags |= FILE_VOLUME_QUOTAS;
2720 if(lp_nt_acl_support(SNUM(conn))) {
2721 additional_flags |= FILE_PERSISTENT_ACLS;
2724 /* Capabilities are filled in at connection time through STATVFS call */
2725 additional_flags |= conn->fs_capabilities;
2727 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2728 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2729 additional_flags); /* FS ATTRIBUTES */
2731 SIVAL(pdata,4,255); /* Max filename component length */
2732 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2733 and will think we can't do long filenames */
2734 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2735 PTR_DIFF(end_data, pdata+12),
2738 data_len = 12 + len;
2741 case SMB_QUERY_FS_LABEL_INFO:
2742 case SMB_FS_LABEL_INFORMATION:
2743 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2744 PTR_DIFF(end_data, pdata+4), 0);
2749 case SMB_QUERY_FS_VOLUME_INFO:
2750 case SMB_FS_VOLUME_INFORMATION:
2753 * Add volume serial number - hash of a combination of
2754 * the called hostname and the service name.
2756 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2757 (str_checksum(get_local_machine_name())<<16));
2759 /* Max label len is 32 characters. */
2760 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2761 PTR_DIFF(end_data, pdata+18),
2763 SIVAL(pdata,12,len);
2766 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2767 (int)strlen(vname),vname, lp_servicename(snum)));
2770 case SMB_QUERY_FS_SIZE_INFO:
2771 case SMB_FS_SIZE_INFORMATION:
2773 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2775 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2776 reply_unixerror(req, ERRHRD, ERRgeneral);
2779 block_size = lp_block_size(snum);
2780 if (bsize < block_size) {
2781 uint64_t factor = block_size/bsize;
2786 if (bsize > block_size) {
2787 uint64_t factor = bsize/block_size;
2792 bytes_per_sector = 512;
2793 sectors_per_unit = bsize/bytes_per_sector;
2794 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2795 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2796 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2797 SBIG_UINT(pdata,0,dsize);
2798 SBIG_UINT(pdata,8,dfree);
2799 SIVAL(pdata,16,sectors_per_unit);
2800 SIVAL(pdata,20,bytes_per_sector);
2804 case SMB_FS_FULL_SIZE_INFORMATION:
2806 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2808 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2809 reply_unixerror(req, ERRHRD, ERRgeneral);
2812 block_size = lp_block_size(snum);
2813 if (bsize < block_size) {
2814 uint64_t factor = block_size/bsize;
2819 if (bsize > block_size) {
2820 uint64_t factor = bsize/block_size;
2825 bytes_per_sector = 512;
2826 sectors_per_unit = bsize/bytes_per_sector;
2827 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2828 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2829 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2830 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2831 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2832 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2833 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2834 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2838 case SMB_QUERY_FS_DEVICE_INFO:
2839 case SMB_FS_DEVICE_INFORMATION:
2841 SIVAL(pdata,0,0); /* dev type */
2842 SIVAL(pdata,4,0); /* characteristics */
2845 #ifdef HAVE_SYS_QUOTAS
2846 case SMB_FS_QUOTA_INFORMATION:
2848 * what we have to send --metze:
2850 * Unknown1: 24 NULL bytes
2851 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2852 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2853 * Quota Flags: 2 byte :
2854 * Unknown3: 6 NULL bytes
2858 * details for Quota Flags:
2860 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2861 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2862 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2863 * 0x0001 Enable Quotas: enable quota for this fs
2867 /* we need to fake up a fsp here,
2868 * because its not send in this call
2871 SMB_NTQUOTA_STRUCT quotas;
2874 ZERO_STRUCT(quotas);
2880 if (conn->server_info->utok.uid != 0) {
2881 DEBUG(0,("set_user_quota: access_denied "
2882 "service [%s] user [%s]\n",
2883 lp_servicename(SNUM(conn)),
2884 conn->server_info->unix_name));
2885 reply_doserror(req, ERRDOS, ERRnoaccess);
2889 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2890 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2891 reply_doserror(req, ERRSRV, ERRerror);
2897 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2899 /* Unknown1 24 NULL bytes*/
2900 SBIG_UINT(pdata,0,(uint64_t)0);
2901 SBIG_UINT(pdata,8,(uint64_t)0);
2902 SBIG_UINT(pdata,16,(uint64_t)0);
2904 /* Default Soft Quota 8 bytes */
2905 SBIG_UINT(pdata,24,quotas.softlim);
2907 /* Default Hard Quota 8 bytes */
2908 SBIG_UINT(pdata,32,quotas.hardlim);
2910 /* Quota flag 2 bytes */
2911 SSVAL(pdata,40,quotas.qflags);
2913 /* Unknown3 6 NULL bytes */
2919 #endif /* HAVE_SYS_QUOTAS */
2920 case SMB_FS_OBJECTID_INFORMATION:
2922 unsigned char objid[16];
2923 struct smb_extended_info extended_info;
2924 memcpy(pdata,create_volume_objectid(conn, objid),16);
2925 samba_extended_info_version (&extended_info);
2926 SIVAL(pdata,16,extended_info.samba_magic);
2927 SIVAL(pdata,20,extended_info.samba_version);
2928 SIVAL(pdata,24,extended_info.samba_subversion);
2929 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2930 memcpy(pdata+36,extended_info.samba_version_string,28);
2936 * Query the version and capabilities of the CIFS UNIX extensions
2940 case SMB_QUERY_CIFS_UNIX_INFO:
2942 bool large_write = lp_min_receive_file_size() &&
2943 !srv_is_signing_active(smbd_server_conn);
2944 bool large_read = !srv_is_signing_active(smbd_server_conn);
2945 int encrypt_caps = 0;
2947 if (!lp_unix_extensions()) {
2948 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2952 switch (conn->encrypt_level) {
2958 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2961 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2962 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2963 large_write = false;
2969 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2970 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2972 /* We have POSIX ACLs, pathname, encryption,
2973 * large read/write, and locking capability. */
2975 SBIG_UINT(pdata,4,((uint64_t)(
2976 CIFS_UNIX_POSIX_ACLS_CAP|
2977 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2978 CIFS_UNIX_FCNTL_LOCKS_CAP|
2979 CIFS_UNIX_EXTATTR_CAP|
2980 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2982 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2984 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2988 case SMB_QUERY_POSIX_FS_INFO:
2991 vfs_statvfs_struct svfs;
2993 if (!lp_unix_extensions()) {
2994 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2998 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3002 SIVAL(pdata,0,svfs.OptimalTransferSize);
3003 SIVAL(pdata,4,svfs.BlockSize);
3004 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3005 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3006 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3007 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3008 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3009 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3010 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3012 } else if (rc == EOPNOTSUPP) {
3013 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3015 #endif /* EOPNOTSUPP */
3017 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3018 reply_doserror(req, ERRSRV, ERRerror);
3024 case SMB_QUERY_POSIX_WHOAMI:
3030 if (!lp_unix_extensions()) {
3031 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3035 if (max_data_bytes < 40) {
3036 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3040 /* We ARE guest if global_sid_Builtin_Guests is
3041 * in our list of SIDs.
3043 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3044 conn->server_info->ptok)) {
3045 flags |= SMB_WHOAMI_GUEST;
3048 /* We are NOT guest if global_sid_Authenticated_Users
3049 * is in our list of SIDs.
3051 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3052 conn->server_info->ptok)) {
3053 flags &= ~SMB_WHOAMI_GUEST;
3056 /* NOTE: 8 bytes for UID/GID, irrespective of native
3057 * platform size. This matches
3058 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3060 data_len = 4 /* flags */
3067 + 4 /* pad/reserved */
3068 + (conn->server_info->utok.ngroups * 8)
3070 + (conn->server_info->ptok->num_sids *
3074 SIVAL(pdata, 0, flags);
3075 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3077 (uint64_t)conn->server_info->utok.uid);
3078 SBIG_UINT(pdata, 16,
3079 (uint64_t)conn->server_info->utok.gid);
3082 if (data_len >= max_data_bytes) {
3083 /* Potential overflow, skip the GIDs and SIDs. */
3085 SIVAL(pdata, 24, 0); /* num_groups */
3086 SIVAL(pdata, 28, 0); /* num_sids */
3087 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3088 SIVAL(pdata, 36, 0); /* reserved */
3094 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3095 SIVAL(pdata, 28, conn->server_info->num_sids);
3097 /* We walk the SID list twice, but this call is fairly
3098 * infrequent, and I don't expect that it's performance
3099 * sensitive -- jpeach
3101 for (i = 0, sid_bytes = 0;
3102 i < conn->server_info->ptok->num_sids; ++i) {
3103 sid_bytes += ndr_size_dom_sid(
3104 &conn->server_info->ptok->user_sids[i],
3109 /* SID list byte count */
3110 SIVAL(pdata, 32, sid_bytes);
3112 /* 4 bytes pad/reserved - must be zero */
3113 SIVAL(pdata, 36, 0);
3117 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3118 SBIG_UINT(pdata, data_len,
3119 (uint64_t)conn->server_info->utok.groups[i]);
3125 i < conn->server_info->ptok->num_sids; ++i) {
3126 int sid_len = ndr_size_dom_sid(
3127 &conn->server_info->ptok->user_sids[i],
3131 sid_linearize(pdata + data_len, sid_len,
3132 &conn->server_info->ptok->user_sids[i]);
3133 data_len += sid_len;
3139 case SMB_MAC_QUERY_FS_INFO:
3141 * Thursby MAC extension... ONLY on NTFS filesystems
3142 * once we do streams then we don't need this
3144 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3146 SIVAL(pdata,84,0x100); /* Don't support mac... */
3151 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3156 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3159 DEBUG( 4, ( "%s info_level = %d\n",
3160 smb_fn_name(req->cmd), info_level) );
3165 /****************************************************************************
3166 Reply to a TRANS2_SETFSINFO (set filesystem info).
3167 ****************************************************************************/
3169 static void call_trans2setfsinfo(connection_struct *conn,
3170 struct smb_request *req,
3171 char **pparams, int total_params,
3172 char **ppdata, int total_data,
3173 unsigned int max_data_bytes)
3175 char *pdata = *ppdata;
3176 char *params = *pparams;
3179 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3182 if (total_params < 4) {
3183 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3189 info_level = SVAL(params,2);
3192 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3193 info_level != SMB_SET_CIFS_UNIX_INFO) {
3194 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3195 "info level (0x%x) on IPC$.\n",
3196 (unsigned int)info_level));
3197 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3202 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3203 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3204 DEBUG(0,("call_trans2setfsinfo: encryption required "
3205 "and info level 0x%x sent.\n",
3206 (unsigned int)info_level));
3207 exit_server_cleanly("encryption required "
3213 switch(info_level) {
3214 case SMB_SET_CIFS_UNIX_INFO:
3216 uint16 client_unix_major;
3217 uint16 client_unix_minor;
3218 uint32 client_unix_cap_low;
3219 uint32 client_unix_cap_high;
3221 if (!lp_unix_extensions()) {
3223 NT_STATUS_INVALID_LEVEL);
3227 /* There should be 12 bytes of capabilities set. */
3228 if (total_data < 8) {
3231 NT_STATUS_INVALID_PARAMETER);
3234 client_unix_major = SVAL(pdata,0);
3235 client_unix_minor = SVAL(pdata,2);
3236 client_unix_cap_low = IVAL(pdata,4);
3237 client_unix_cap_high = IVAL(pdata,8);
3238 /* Just print these values for now. */
3239 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3240 cap_low = 0x%x, cap_high = 0x%x\n",
3241 (unsigned int)client_unix_major,
3242 (unsigned int)client_unix_minor,
3243 (unsigned int)client_unix_cap_low,
3244 (unsigned int)client_unix_cap_high ));
3246 /* Here is where we must switch to posix pathname processing... */
3247 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3248 lp_set_posix_pathnames();
3249 mangle_change_to_posix();
3252 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3253 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3254 /* Client that knows how to do posix locks,
3255 * but not posix open/mkdir operations. Set a
3256 * default type for read/write checks. */
3258 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3264 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3267 size_t param_len = 0;
3268 size_t data_len = total_data;
3270 if (!lp_unix_extensions()) {
3273 NT_STATUS_INVALID_LEVEL);
3277 if (lp_smb_encrypt(SNUM(conn)) == false) {
3280 NT_STATUS_NOT_SUPPORTED);
3284 DEBUG( 4,("call_trans2setfsinfo: "
3285 "request transport encryption.\n"));
3287 status = srv_request_encryption_setup(conn,
3288 (unsigned char **)ppdata,
3290 (unsigned char **)pparams,
3293 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3294 !NT_STATUS_IS_OK(status)) {
3295 reply_nterror(req, status);
3299 send_trans2_replies(conn, req,
3306 if (NT_STATUS_IS_OK(status)) {
3307 /* Server-side transport
3308 * encryption is now *on*. */
3309 status = srv_encryption_start(conn);
3310 if (!NT_STATUS_IS_OK(status)) {
3311 exit_server_cleanly(
3312 "Failure in setting "
3313 "up encrypted transport");
3319 case SMB_FS_QUOTA_INFORMATION:
3321 files_struct *fsp = NULL;
3322 SMB_NTQUOTA_STRUCT quotas;
3324 ZERO_STRUCT(quotas);
3327 if ((conn->server_info->utok.uid != 0)
3328 ||!CAN_WRITE(conn)) {
3329 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3330 lp_servicename(SNUM(conn)),
3331 conn->server_info->unix_name));
3332 reply_doserror(req, ERRSRV, ERRaccess);
3336 /* note: normaly there're 48 bytes,
3337 * but we didn't use the last 6 bytes for now
3340 fsp = file_fsp(req, SVAL(params,0));
3342 if (!check_fsp_ntquota_handle(conn, req,
3344 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3346 req, NT_STATUS_INVALID_HANDLE);
3350 if (total_data < 42) {
3351 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3355 NT_STATUS_INVALID_PARAMETER);
3359 /* unknown_1 24 NULL bytes in pdata*/
3361 /* the soft quotas 8 bytes (uint64_t)*/
3362 quotas.softlim = (uint64_t)IVAL(pdata,24);
3363 #ifdef LARGE_SMB_OFF_T
3364 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3365 #else /* LARGE_SMB_OFF_T */
3366 if ((IVAL(pdata,28) != 0)&&
3367 ((quotas.softlim != 0xFFFFFFFF)||
3368 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3369 /* more than 32 bits? */
3372 NT_STATUS_INVALID_PARAMETER);
3375 #endif /* LARGE_SMB_OFF_T */
3377 /* the hard quotas 8 bytes (uint64_t)*/
3378 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3379 #ifdef LARGE_SMB_OFF_T
3380 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3381 #else /* LARGE_SMB_OFF_T */
3382 if ((IVAL(pdata,36) != 0)&&
3383 ((quotas.hardlim != 0xFFFFFFFF)||
3384 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3385 /* more than 32 bits? */
3388 NT_STATUS_INVALID_PARAMETER);
3391 #endif /* LARGE_SMB_OFF_T */
3393 /* quota_flags 2 bytes **/
3394 quotas.qflags = SVAL(pdata,40);
3396 /* unknown_2 6 NULL bytes follow*/
3398 /* now set the quotas */
3399 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3400 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3401 reply_doserror(req, ERRSRV, ERRerror);
3408 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3410 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3416 * sending this reply works fine,
3417 * but I'm not sure it's the same
3418 * like windows do...
3421 reply_outbuf(req, 10, 0);
3424 #if defined(HAVE_POSIX_ACLS)
3425 /****************************************************************************
3426 Utility function to count the number of entries in a POSIX acl.
3427 ****************************************************************************/
3429 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3431 unsigned int ace_count = 0;
3432 int entry_id = SMB_ACL_FIRST_ENTRY;
3433 SMB_ACL_ENTRY_T entry;
3435 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3437 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3438 entry_id = SMB_ACL_NEXT_ENTRY;
3445 /****************************************************************************
3446 Utility function to marshall a POSIX acl into wire format.
3447 ****************************************************************************/
3449 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3451 int entry_id = SMB_ACL_FIRST_ENTRY;
3452 SMB_ACL_ENTRY_T entry;
3454 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3455 SMB_ACL_TAG_T tagtype;
3456 SMB_ACL_PERMSET_T permset;
3457 unsigned char perms = 0;
3458 unsigned int own_grp;
3461 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3462 entry_id = SMB_ACL_NEXT_ENTRY;
3465 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3466 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3470 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3471 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3475 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3476 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3477 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3479 SCVAL(pdata,1,perms);
3482 case SMB_ACL_USER_OBJ:
3483 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3484 own_grp = (unsigned int)pst->st_ex_uid;
3485 SIVAL(pdata,2,own_grp);
3490 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3492 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3495 own_grp = (unsigned int)*puid;
3496 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3497 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3498 SIVAL(pdata,2,own_grp);
3502 case SMB_ACL_GROUP_OBJ:
3503 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3504 own_grp = (unsigned int)pst->st_ex_gid;
3505 SIVAL(pdata,2,own_grp);
3510 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3512 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3515 own_grp = (unsigned int)*pgid;
3516 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3517 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3518 SIVAL(pdata,2,own_grp);
3523 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3524 SIVAL(pdata,2,0xFFFFFFFF);
3525 SIVAL(pdata,6,0xFFFFFFFF);
3528 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3529 SIVAL(pdata,2,0xFFFFFFFF);
3530 SIVAL(pdata,6,0xFFFFFFFF);
3533 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3536 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3543 /****************************************************************************
3544 Store the FILE_UNIX_BASIC info.
3545 ****************************************************************************/
3547 static char *store_file_unix_basic(connection_struct *conn,
3550 const SMB_STRUCT_STAT *psbuf)
3552 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3553 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3555 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3558 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3561 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3562 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3563 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3566 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3570 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3574 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3577 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3581 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3585 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3588 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3592 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3599 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3600 * the chflags(2) (or equivalent) flags.
3602 * XXX: this really should be behind the VFS interface. To do this, we would
3603 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3604 * Each VFS module could then implement its own mapping as appropriate for the
3605 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3607 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3611 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3615 { UF_IMMUTABLE, EXT_IMMUTABLE },
3619 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3623 { UF_HIDDEN, EXT_HIDDEN },
3626 /* Do not remove. We need to guarantee that this array has at least one
3627 * entry to build on HP-UX.
3633 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3634 uint32 *smb_fflags, uint32 *smb_fmask)
3638 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3639 *smb_fmask |= info2_flags_map[i].smb_fflag;
3640 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3641 *smb_fflags |= info2_flags_map[i].smb_fflag;
3646 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3647 const uint32 smb_fflags,
3648 const uint32 smb_fmask,
3651 uint32 max_fmask = 0;
3654 *stat_fflags = psbuf->st_ex_flags;
3656 /* For each flags requested in smb_fmask, check the state of the
3657 * corresponding flag in smb_fflags and set or clear the matching
3661 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3662 max_fmask |= info2_flags_map[i].smb_fflag;
3663 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3664 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3665 *stat_fflags |= info2_flags_map[i].stat_fflag;
3667 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3672 /* If smb_fmask is asking to set any bits that are not supported by
3673 * our flag mappings, we should fail.
3675 if ((smb_fmask & max_fmask) != smb_fmask) {
3683 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3684 * of file flags and birth (create) time.
3686 static char *store_file_unix_basic_info2(connection_struct *conn,
3689 const SMB_STRUCT_STAT *psbuf)
3691 uint32 file_flags = 0;
3692 uint32 flags_mask = 0;
3694 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3696 /* Create (birth) time 64 bit */
3697 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3700 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3701 SIVAL(pdata, 0, file_flags); /* flags */
3702 SIVAL(pdata, 4, flags_mask); /* mask */
3708 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3709 const struct stream_struct *streams,
3711 unsigned int max_data_bytes,
3712 unsigned int *data_size)
3715 unsigned int ofs = 0;
3717 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3718 unsigned int next_offset;
3720 smb_ucs2_t *namebuf;
3722 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3723 streams[i].name, &namelen) ||
3726 return NT_STATUS_INVALID_PARAMETER;
3730 * name_buf is now null-terminated, we need to marshall as not
3736 SIVAL(data, ofs+4, namelen);
3737 SOFF_T(data, ofs+8, streams[i].size);
3738 SOFF_T(data, ofs+16, streams[i].alloc_size);
3739 memcpy(data+ofs+24, namebuf, namelen);
3740 TALLOC_FREE(namebuf);
3742 next_offset = ofs + 24 + namelen;
3744 if (i == num_streams-1) {
3745 SIVAL(data, ofs, 0);
3748 unsigned int align = ndr_align_size(next_offset, 8);
3750 memset(data+next_offset, 0, align);
3751 next_offset += align;
3753 SIVAL(data, ofs, next_offset - ofs);
3762 return NT_STATUS_OK;
3765 /****************************************************************************
3766 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3767 ****************************************************************************/
3769 static void call_trans2qpipeinfo(connection_struct *conn,
3770 struct smb_request *req,
3771 unsigned int tran_call,
3772 char **pparams, int total_params,
3773 char **ppdata, int total_data,
3774 unsigned int max_data_bytes)
3776 char *params = *pparams;
3777 char *pdata = *ppdata;
3778 unsigned int data_size = 0;
3779 unsigned int param_size = 2;
3784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3788 if (total_params < 4) {
3789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3793 fsp = file_fsp(req, SVAL(params,0));
3794 if (!fsp_is_np(fsp)) {
3795 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3799 info_level = SVAL(params,2);
3801 *pparams = (char *)SMB_REALLOC(*pparams,2);
3802 if (*pparams == NULL) {
3803 reply_nterror(req, NT_STATUS_NO_MEMORY);
3808 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3809 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3810 if (*ppdata == NULL ) {
3811 reply_nterror(req, NT_STATUS_NO_MEMORY);
3816 switch (info_level) {
3817 case SMB_FILE_STANDARD_INFORMATION:
3819 SOFF_T(pdata,0,4096LL);
3826 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3830 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3836 /****************************************************************************
3837 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3838 file name or file id).
3839 ****************************************************************************/
3841 static void call_trans2qfilepathinfo(connection_struct *conn,
3842 struct smb_request *req,
3843 unsigned int tran_call,
3844 char **pparams, int total_params,
3845 char **ppdata, int total_data,
3846 unsigned int max_data_bytes)
3848 char *params = *pparams;
3849 char *pdata = *ppdata;
3850 char *dstart, *dend;
3854 SMB_OFF_T file_size=0;
3855 uint64_t allocation_size=0;
3856 unsigned int data_size = 0;
3857 unsigned int param_size = 2;
3858 SMB_STRUCT_STAT sbuf;
3859 char *dos_fname = NULL;
3861 struct smb_filename *smb_fname = NULL;
3866 bool delete_pending = False;
3868 time_t create_time, mtime, atime;
3869 struct timespec create_time_ts, mtime_ts, atime_ts;
3870 struct timespec write_time_ts;
3871 files_struct *fsp = NULL;
3872 struct file_id fileid;
3873 struct ea_list *ea_list = NULL;
3874 char *lock_data = NULL;
3875 bool ms_dfs_link = false;
3876 TALLOC_CTX *ctx = talloc_tos();
3877 NTSTATUS status = NT_STATUS_OK;
3880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3884 ZERO_STRUCT(write_time_ts);
3886 if (tran_call == TRANSACT2_QFILEINFO) {
3887 if (total_params < 4) {
3888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3893 call_trans2qpipeinfo(conn, req, tran_call,
3894 pparams, total_params,
3900 fsp = file_fsp(req, SVAL(params,0));
3901 info_level = SVAL(params,2);
3903 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3905 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3906 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3910 /* Initial check for valid fsp ptr. */
3911 if (!check_fsp_open(conn, req, fsp)) {
3915 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3917 reply_nterror(req, NT_STATUS_NO_MEMORY);
3921 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
3923 if (!NT_STATUS_IS_OK(status)) {
3924 reply_nterror(req, status);
3928 if(fsp->fake_file_handle) {
3930 * This is actually for the QUOTA_FAKE_FILE --metze
3933 /* We know this name is ok, it's already passed the checks. */
3935 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3937 * This is actually a QFILEINFO on a directory
3938 * handle (returned from an NT SMB). NT5.0 seems
3939 * to do this call. JRA.
3942 if (INFO_LEVEL_IS_UNIX(info_level)) {
3943 /* Always do lstat for UNIX calls. */
3944 if (SMB_VFS_LSTAT(conn, smb_fname)) {
3945 DEBUG(3,("call_trans2qfilepathinfo: "
3946 "SMB_VFS_LSTAT of %s failed "
3948 smb_fname_str_dbg(smb_fname),
3950 reply_unixerror(req,ERRDOS,ERRbadpath);
3953 } else if (SMB_VFS_STAT(conn, smb_fname)) {
3954 DEBUG(3,("call_trans2qfilepathinfo: "
3955 "SMB_VFS_STAT of %s failed (%s)\n",
3956 smb_fname_str_dbg(smb_fname),
3958 reply_unixerror(req, ERRDOS, ERRbadpath);
3962 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
3963 get_file_infos(fileid, &delete_pending, &write_time_ts);
3966 * Original code - this is an open file.
3968 if (!check_fsp(conn, req, fsp)) {
3972 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
3973 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
3974 fsp->fnum, strerror(errno)));
3975 reply_unixerror(req, ERRDOS, ERRbadfid);
3978 pos = fsp->fh->position_information;
3979 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
3980 get_file_infos(fileid, &delete_pending, &write_time_ts);
3985 if (total_params < 7) {
3986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3990 info_level = SVAL(params,0);
3992 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3994 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3995 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3999 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
4001 STR_TERMINATE, &status);
4002 if (!NT_STATUS_IS_OK(status)) {
4003 reply_nterror(req, status);
4007 status = filename_convert(ctx,
4009 req->flags2 & FLAGS2_DFS_PATHNAMES,
4013 if (!NT_STATUS_IS_OK(status)) {
4014 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4015 reply_botherror(req,
4016 NT_STATUS_PATH_NOT_COVERED,
4017 ERRSRV, ERRbadpath);
4020 reply_nterror(req, status);
4024 /* If this is a stream, check if there is a delete_pending. */
4025 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4026 && is_ntfs_stream_smb_fname(smb_fname)) {
4027 struct smb_filename *smb_fname_base = NULL;
4029 /* Create an smb_filename with stream_name == NULL. */
4031 create_synthetic_smb_fname(talloc_tos(),
4032 smb_fname->base_name,
4035 if (!NT_STATUS_IS_OK(status)) {
4036 reply_nterror(req, status);
4040 if (INFO_LEVEL_IS_UNIX(info_level)) {
4041 /* Always do lstat for UNIX calls. */
4042 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4043 DEBUG(3,("call_trans2qfilepathinfo: "
4044 "SMB_VFS_LSTAT of %s failed "
4046 smb_fname_str_dbg(smb_fname_base),
4048 TALLOC_FREE(smb_fname_base);
4049 reply_unixerror(req,ERRDOS,ERRbadpath);
4053 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4054 DEBUG(3,("call_trans2qfilepathinfo: "
4055 "fileinfo of %s failed "
4057 smb_fname_str_dbg(smb_fname_base),
4059 TALLOC_FREE(smb_fname_base);
4060 reply_unixerror(req,ERRDOS,ERRbadpath);
4065 fileid = vfs_file_id_from_sbuf(conn,
4066 &smb_fname_base->st);
4067 TALLOC_FREE(smb_fname_base);
4068 get_file_infos(fileid, &delete_pending, NULL);
4069 if (delete_pending) {
4070 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4075 if (INFO_LEVEL_IS_UNIX(info_level)) {
4076 /* Always do lstat for UNIX calls. */
4077 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4078 DEBUG(3,("call_trans2qfilepathinfo: "
4079 "SMB_VFS_LSTAT of %s failed (%s)\n",
4080 smb_fname_str_dbg(smb_fname),
4082 reply_unixerror(req, ERRDOS, ERRbadpath);
4086 } else if (!VALID_STAT(smb_fname->st) &&
4087 SMB_VFS_STAT(conn, smb_fname) &&
4088 (info_level != SMB_INFO_IS_NAME_VALID)) {
4089 ms_dfs_link = check_msdfs_link(conn, fname,
4093 DEBUG(3,("call_trans2qfilepathinfo: "
4094 "SMB_VFS_STAT of %s failed (%s)\n",
4095 smb_fname_str_dbg(smb_fname),
4097 reply_unixerror(req, ERRDOS, ERRbadpath);
4102 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4103 get_file_infos(fileid, &delete_pending, &write_time_ts);
4104 if (delete_pending) {
4105 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4110 /* Set sbuf for use below. */
4111 sbuf = smb_fname->st;
4113 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4114 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4118 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4119 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4121 p = strrchr_m(fname,'/');
4128 mode = dos_mode_msdfs(conn,fname,&sbuf);
4130 mode = dos_mode(conn,fname,&sbuf);
4133 mode = FILE_ATTRIBUTE_NORMAL;
4135 nlink = sbuf.st_ex_nlink;
4137 if (nlink && (mode&aDIR)) {
4141 if ((nlink > 0) && delete_pending) {
4145 fullpathname = fname;
4147 file_size = get_file_size_stat(&sbuf);
4149 /* Pull out any data sent here before we realloc. */
4150 switch (info_level) {
4151 case SMB_INFO_QUERY_EAS_FROM_LIST:
4153 /* Pull any EA list from the data portion. */
4156 if (total_data < 4) {
4158 req, NT_STATUS_INVALID_PARAMETER);
4161 ea_size = IVAL(pdata,0);
4163 if (total_data > 0 && ea_size != total_data) {
4164 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4165 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4167 req, NT_STATUS_INVALID_PARAMETER);
4171 if (!lp_ea_support(SNUM(conn))) {
4172 reply_doserror(req, ERRDOS,
4173 ERReasnotsupported);
4177 /* Pull out the list of names. */
4178 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4181 req, NT_STATUS_INVALID_PARAMETER);
4187 case SMB_QUERY_POSIX_LOCK:
4189 if (fsp == NULL || fsp->fh->fd == -1) {
4190 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4194 if (total_data != POSIX_LOCK_DATA_SIZE) {
4196 req, NT_STATUS_INVALID_PARAMETER);
4200 /* Copy the lock range data. */
4201 lock_data = (char *)TALLOC_MEMDUP(
4202 ctx, pdata, total_data);
4204 reply_nterror(req, NT_STATUS_NO_MEMORY);
4212 *pparams = (char *)SMB_REALLOC(*pparams,2);
4213 if (*pparams == NULL) {
4214 reply_nterror(req, NT_STATUS_NO_MEMORY);
4219 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4220 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4221 if (*ppdata == NULL ) {
4222 reply_nterror(req, NT_STATUS_NO_MEMORY);
4227 dend = dstart + data_size - 1;
4229 create_time_ts = sbuf.st_ex_btime;
4230 mtime_ts = sbuf.st_ex_mtime;
4231 atime_ts = sbuf.st_ex_atime;
4233 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4236 /* Do we have this path open ? */
4238 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4239 fsp1 = file_find_di_first(fileid);
4240 if (fsp1 && fsp1->initial_allocation_size) {
4241 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4245 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4246 mtime_ts = write_time_ts;
4249 if (lp_dos_filetime_resolution(SNUM(conn))) {
4250 dos_filetime_timespec(&create_time_ts);
4251 dos_filetime_timespec(&mtime_ts);
4252 dos_filetime_timespec(&atime_ts);
4255 create_time = convert_timespec_to_time_t(create_time_ts);
4256 mtime = convert_timespec_to_time_t(mtime_ts);
4257 atime = convert_timespec_to_time_t(atime_ts);
4259 /* NT expects the name to be in an exact form of the *full*
4260 filename. See the trans2 torture test */
4261 if (ISDOT(base_name)) {
4262 dos_fname = talloc_strdup(ctx, "\\");
4264 reply_nterror(req, NT_STATUS_NO_MEMORY);
4268 dos_fname = talloc_asprintf(ctx,
4272 reply_nterror(req, NT_STATUS_NO_MEMORY);
4275 string_replace(dos_fname, '/', '\\');
4278 switch (info_level) {
4279 case SMB_INFO_STANDARD:
4280 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4282 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4283 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4284 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4285 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4286 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4287 SSVAL(pdata,l1_attrFile,mode);
4290 case SMB_INFO_QUERY_EA_SIZE:
4292 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4293 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4295 srv_put_dos_date2(pdata,0,create_time);
4296 srv_put_dos_date2(pdata,4,atime);
4297 srv_put_dos_date2(pdata,8,mtime); /* write time */
4298 SIVAL(pdata,12,(uint32)file_size);
4299 SIVAL(pdata,16,(uint32)allocation_size);
4300 SSVAL(pdata,20,mode);
4301 SIVAL(pdata,22,ea_size);
4305 case SMB_INFO_IS_NAME_VALID:
4306 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4307 if (tran_call == TRANSACT2_QFILEINFO) {
4308 /* os/2 needs this ? really ?*/
4309 reply_doserror(req, ERRDOS, ERRbadfunc);
4316 case SMB_INFO_QUERY_EAS_FROM_LIST:
4318 size_t total_ea_len = 0;
4319 struct ea_list *ea_file_list = NULL;
4321 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4323 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4324 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4326 if (!ea_list || (total_ea_len > data_size)) {
4328 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4332 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4336 case SMB_INFO_QUERY_ALL_EAS:
4338 /* We have data_size bytes to put EA's into. */
4339 size_t total_ea_len = 0;
4341 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4343 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4344 if (!ea_list || (total_ea_len > data_size)) {
4346 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4350 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4354 case SMB_FILE_BASIC_INFORMATION:
4355 case SMB_QUERY_FILE_BASIC_INFO:
4357 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4358 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4359 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4361 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4365 put_long_date_timespec(pdata,create_time_ts);
4366 put_long_date_timespec(pdata+8,atime_ts);
4367 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4368 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4369 SIVAL(pdata,32,mode);
4371 DEBUG(5,("SMB_QFBI - "));
4372 DEBUG(5,("create: %s ", ctime(&create_time)));
4373 DEBUG(5,("access: %s ", ctime(&atime)));
4374 DEBUG(5,("write: %s ", ctime(&mtime)));
4375 DEBUG(5,("change: %s ", ctime(&mtime)));
4376 DEBUG(5,("mode: %x\n", mode));
4379 case SMB_FILE_STANDARD_INFORMATION:
4380 case SMB_QUERY_FILE_STANDARD_INFO:
4382 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4384 SOFF_T(pdata,0,allocation_size);
4385 SOFF_T(pdata,8,file_size);
4386 SIVAL(pdata,16,nlink);
4387 SCVAL(pdata,20,delete_pending?1:0);
4388 SCVAL(pdata,21,(mode&aDIR)?1:0);
4389 SSVAL(pdata,22,0); /* Padding. */
4392 case SMB_FILE_EA_INFORMATION:
4393 case SMB_QUERY_FILE_EA_INFO:
4395 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4396 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4398 SIVAL(pdata,0,ea_size);
4402 /* Get the 8.3 name - used if NT SMB was negotiated. */
4403 case SMB_QUERY_FILE_ALT_NAME_INFO:
4404 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4406 char mangled_name[13];
4407 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4408 if (!name_to_8_3(base_name,mangled_name,
4409 True,conn->params)) {
4412 NT_STATUS_NO_MEMORY);
4414 len = srvstr_push(dstart, req->flags2,
4415 pdata+4, mangled_name,
4416 PTR_DIFF(dend, pdata+4),
4418 data_size = 4 + len;
4423 case SMB_QUERY_FILE_NAME_INFO:
4425 this must be *exactly* right for ACLs on mapped drives to work
4427 len = srvstr_push(dstart, req->flags2,
4429 PTR_DIFF(dend, pdata+4),
4431 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4432 data_size = 4 + len;
4436 case SMB_FILE_ALLOCATION_INFORMATION:
4437 case SMB_QUERY_FILE_ALLOCATION_INFO:
4438 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4440 SOFF_T(pdata,0,allocation_size);
4443 case SMB_FILE_END_OF_FILE_INFORMATION:
4444 case SMB_QUERY_FILE_END_OF_FILEINFO:
4445 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4447 SOFF_T(pdata,0,file_size);
4450 case SMB_QUERY_FILE_ALL_INFO:
4451 case SMB_FILE_ALL_INFORMATION:
4453 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4454 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4455 put_long_date_timespec(pdata,create_time_ts);
4456 put_long_date_timespec(pdata+8,atime_ts);
4457 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4458 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4459 SIVAL(pdata,32,mode);
4460 SIVAL(pdata,36,0); /* padding. */
4462 SOFF_T(pdata,0,allocation_size);
4463 SOFF_T(pdata,8,file_size);
4464 SIVAL(pdata,16,nlink);
4465 SCVAL(pdata,20,delete_pending);
4466 SCVAL(pdata,21,(mode&aDIR)?1:0);
4469 SIVAL(pdata,0,ea_size);
4470 pdata += 4; /* EA info */
4471 len = srvstr_push(dstart, req->flags2,
4473 PTR_DIFF(dend, pdata+4),
4477 data_size = PTR_DIFF(pdata,(*ppdata));
4480 case SMB_FILE_INTERNAL_INFORMATION:
4481 /* This should be an index number - looks like
4484 I think this causes us to fail the IFSKIT
4485 BasicFileInformationTest. -tpot */
4487 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4488 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4489 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4493 case SMB_FILE_ACCESS_INFORMATION:
4494 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4496 SIVAL(pdata,0,fsp->access_mask);
4498 /* GENERIC_EXECUTE mapping from Windows */
4499 SIVAL(pdata,0,0x12019F);
4504 case SMB_FILE_NAME_INFORMATION:
4505 /* Pathname with leading '\'. */
4508 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4509 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4510 SIVAL(pdata,0,byte_len);
4511 data_size = 4 + byte_len;
4515 case SMB_FILE_DISPOSITION_INFORMATION:
4516 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4518 SCVAL(pdata,0,delete_pending);
4521 case SMB_FILE_POSITION_INFORMATION:
4522 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4524 SOFF_T(pdata,0,pos);
4527 case SMB_FILE_MODE_INFORMATION:
4528 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4529 SIVAL(pdata,0,mode);
4533 case SMB_FILE_ALIGNMENT_INFORMATION:
4534 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4535 SIVAL(pdata,0,0); /* No alignment needed. */
4540 * NT4 server just returns "invalid query" to this - if we try
4541 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4544 /* The first statement above is false - verified using Thursby
4545 * client against NT4 -- gcolley.
4547 case SMB_QUERY_FILE_STREAM_INFO:
4548 case SMB_FILE_STREAM_INFORMATION: {
4549 unsigned int num_streams;
4550 struct stream_struct *streams;
4552 DEBUG(10,("call_trans2qfilepathinfo: "
4553 "SMB_FILE_STREAM_INFORMATION\n"));
4555 status = SMB_VFS_STREAMINFO(
4556 conn, fsp, fname, talloc_tos(),
4557 &num_streams, &streams);
4559 if (!NT_STATUS_IS_OK(status)) {
4560 DEBUG(10, ("could not get stream info: %s\n",
4561 nt_errstr(status)));
4562 reply_nterror(req, status);
4566 status = marshall_stream_info(num_streams, streams,
4567 pdata, max_data_bytes,
4570 if (!NT_STATUS_IS_OK(status)) {
4571 DEBUG(10, ("marshall_stream_info failed: %s\n",
4572 nt_errstr(status)));
4573 reply_nterror(req, status);
4577 TALLOC_FREE(streams);
4581 case SMB_QUERY_COMPRESSION_INFO:
4582 case SMB_FILE_COMPRESSION_INFORMATION:
4583 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4584 SOFF_T(pdata,0,file_size);
4585 SIVAL(pdata,8,0); /* ??? */
4586 SIVAL(pdata,12,0); /* ??? */
4590 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4591 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4592 put_long_date_timespec(pdata,create_time_ts);
4593 put_long_date_timespec(pdata+8,atime_ts);
4594 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4595 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4596 SOFF_T(pdata,32,allocation_size);
4597 SOFF_T(pdata,40,file_size);
4598 SIVAL(pdata,48,mode);
4599 SIVAL(pdata,52,0); /* ??? */
4603 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4604 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4605 SIVAL(pdata,0,mode);
4611 * CIFS UNIX Extensions.
4614 case SMB_QUERY_FILE_UNIX_BASIC:
4616 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4617 data_size = PTR_DIFF(pdata,(*ppdata));
4621 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4623 for (i=0; i<100; i++)
4624 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4630 case SMB_QUERY_FILE_UNIX_INFO2:
4632 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4633 data_size = PTR_DIFF(pdata,(*ppdata));
4637 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4639 for (i=0; i<100; i++)
4640 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4646 case SMB_QUERY_FILE_UNIX_LINK:
4648 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4651 reply_nterror(req, NT_STATUS_NO_MEMORY);
4655 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4657 if(!S_ISLNK(sbuf.st_ex_mode)) {
4658 reply_unixerror(req, ERRSRV,
4663 reply_unixerror(req, ERRDOS, ERRbadlink);
4666 len = SMB_VFS_READLINK(conn,fullpathname,
4669 reply_unixerror(req, ERRDOS,
4674 len = srvstr_push(dstart, req->flags2,
4676 PTR_DIFF(dend, pdata),
4679 data_size = PTR_DIFF(pdata,(*ppdata));
4684 #if defined(HAVE_POSIX_ACLS)
4685 case SMB_QUERY_POSIX_ACL:
4687 SMB_ACL_T file_acl = NULL;
4688 SMB_ACL_T def_acl = NULL;
4689 uint16 num_file_acls = 0;
4690 uint16 num_def_acls = 0;
4692 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4693 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4695 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4698 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4699 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4703 NT_STATUS_NOT_IMPLEMENTED);
4707 if (S_ISDIR(sbuf.st_ex_mode)) {
4708 if (fsp && fsp->is_directory) {
4709 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4711 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4713 def_acl = free_empty_sys_acl(conn, def_acl);
4716 num_file_acls = count_acl_entries(conn, file_acl);
4717 num_def_acls = count_acl_entries(conn, def_acl);
4719 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4720 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4722 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4723 SMB_POSIX_ACL_HEADER_SIZE) ));
4725 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4728 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4732 NT_STATUS_BUFFER_TOO_SMALL);
4736 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4737 SSVAL(pdata,2,num_file_acls);
4738 SSVAL(pdata,4,num_def_acls);
4739 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4741 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4744 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4747 req, NT_STATUS_INTERNAL_ERROR);
4750 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4752 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4755 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4759 NT_STATUS_INTERNAL_ERROR);
4764 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4767 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4769 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4775 case SMB_QUERY_POSIX_LOCK:
4780 enum brl_type lock_type;
4782 if (total_data != POSIX_LOCK_DATA_SIZE) {
4784 req, NT_STATUS_INVALID_PARAMETER);
4788 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4789 case POSIX_LOCK_TYPE_READ:
4790 lock_type = READ_LOCK;
4792 case POSIX_LOCK_TYPE_WRITE:
4793 lock_type = WRITE_LOCK;
4795 case POSIX_LOCK_TYPE_UNLOCK:
4797 /* There's no point in asking for an unlock... */
4800 NT_STATUS_INVALID_PARAMETER);
4804 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4805 #if defined(HAVE_LONGLONG)
4806 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4807 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4808 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4809 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4810 #else /* HAVE_LONGLONG */
4811 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4812 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4813 #endif /* HAVE_LONGLONG */
4815 status = query_lock(fsp,
4822 if (ERROR_WAS_LOCK_DENIED(status)) {
4823 /* Here we need to report who has it locked... */
4824 data_size = POSIX_LOCK_DATA_SIZE;
4826 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4827 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4828 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4829 #if defined(HAVE_LONGLONG)
4830 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4831 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4832 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4833 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4834 #else /* HAVE_LONGLONG */
4835 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4836 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4837 #endif /* HAVE_LONGLONG */
4839 } else if (NT_STATUS_IS_OK(status)) {
4840 /* For success we just return a copy of what we sent
4841 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4842 data_size = POSIX_LOCK_DATA_SIZE;
4843 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4844 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4846 reply_nterror(req, status);
4853 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4857 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4863 /****************************************************************************
4864 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4866 ****************************************************************************/
4868 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4869 connection_struct *conn,
4870 const struct smb_filename *smb_fname_old,
4871 const struct smb_filename *smb_fname_new)
4873 char *oldname = NULL;
4874 char *newname = NULL;
4875 NTSTATUS status = NT_STATUS_OK;
4877 /* source must already exist. */
4878 if (!VALID_STAT(smb_fname_old->st)) {
4879 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4882 /* Disallow if newname already exists. */
4883 if (VALID_STAT(smb_fname_new->st)) {
4884 return NT_STATUS_OBJECT_NAME_COLLISION;
4887 /* No links from a directory. */
4888 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
4889 return NT_STATUS_FILE_IS_A_DIRECTORY;
4892 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
4893 if (!NT_STATUS_IS_OK(status)) {
4896 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
4897 if (!NT_STATUS_IS_OK(status)) {
4901 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4903 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4904 status = map_nt_error_from_unix(errno);
4905 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4906 nt_errstr(status), newname, oldname));
4909 TALLOC_FREE(newname);
4910 TALLOC_FREE(oldname);
4914 /****************************************************************************
4915 Deal with setting the time from any of the setfilepathinfo functions.
4916 ****************************************************************************/
4918 NTSTATUS smb_set_file_time(connection_struct *conn,
4921 const SMB_STRUCT_STAT *psbuf,
4922 struct smb_file_time *ft,
4923 bool setting_write_time)
4926 FILE_NOTIFY_CHANGE_LAST_ACCESS
4927 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4929 if (!VALID_STAT(*psbuf)) {
4930 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4933 /* get some defaults (no modifications) if any info is zero or -1. */
4934 if (null_timespec(ft->atime)) {
4935 ft->atime= psbuf->st_ex_atime;
4936 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4939 if (null_timespec(ft->mtime)) {
4940 ft->mtime = psbuf->st_ex_mtime;
4941 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4944 if (!setting_write_time) {
4945 /* ft->mtime comes from change time, not write time. */
4946 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4949 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4950 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4951 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4952 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4953 if (!null_timespec(ft->create_time)) {
4954 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4955 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4959 * Try and set the times of this file if
4960 * they are different from the current values.
4964 struct timespec mts = psbuf->st_ex_mtime;
4965 struct timespec ats = psbuf->st_ex_atime;
4966 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4967 (timespec_compare(&ft->mtime, &mts) == 0)) {
4968 return NT_STATUS_OK;
4972 if (setting_write_time) {
4974 * This was a setfileinfo on an open file.
4975 * NT does this a lot. We also need to
4976 * set the time here, as it can be read by
4977 * FindFirst/FindNext and with the patch for bug #2045
4978 * in smbd/fileio.c it ensures that this timestamp is
4979 * kept sticky even after a write. We save the request
4980 * away and will set it on file close and after a write. JRA.
4983 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4984 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4987 if (fsp->base_fsp) {
4988 set_sticky_write_time_fsp(fsp->base_fsp,
4991 set_sticky_write_time_fsp(fsp, ft->mtime);
4994 set_sticky_write_time_path(conn, fname,
4995 vfs_file_id_from_sbuf(conn, psbuf),
5000 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5002 if (fsp && fsp->base_fsp) {
5003 fname = fsp->base_fsp->fsp_name;
5006 if(file_ntimes(conn, fname, ft)!=0) {
5007 return map_nt_error_from_unix(errno);
5009 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
5011 return NT_STATUS_OK;
5014 /****************************************************************************
5015 Deal with setting the dosmode from any of the setfilepathinfo functions.
5016 ****************************************************************************/
5018 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5021 SMB_STRUCT_STAT *psbuf,
5024 if (!VALID_STAT(*psbuf)) {
5025 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5029 if (fsp->base_fsp) {
5030 fname = fsp->base_fsp->fsp_name;
5032 fname = fsp->fsp_name;
5037 if (S_ISDIR(psbuf->st_ex_mode)) {
5044 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5046 /* check the mode isn't different, before changing it */
5047 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5049 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5050 fname, (unsigned int)dosmode ));
5052 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5053 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5054 fname, strerror(errno)));
5055 return map_nt_error_from_unix(errno);
5058 return NT_STATUS_OK;
5061 /****************************************************************************
5062 Deal with setting the size from any of the setfilepathinfo functions.
5063 ****************************************************************************/
5065 static NTSTATUS smb_set_file_size(connection_struct *conn,
5066 struct smb_request *req,
5069 SMB_STRUCT_STAT *psbuf,
5072 struct smb_filename *smb_fname = NULL;
5073 NTSTATUS status = NT_STATUS_OK;
5074 files_struct *new_fsp = NULL;
5076 if (!VALID_STAT(*psbuf)) {
5077 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5080 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5082 if (size == get_file_size_stat(psbuf)) {
5083 return NT_STATUS_OK;
5086 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5087 fname, (double)size ));
5089 if (fsp && fsp->fh->fd != -1) {
5090 /* Handle based call. */
5091 if (vfs_set_filelen(fsp, size) == -1) {
5092 return map_nt_error_from_unix(errno);
5094 trigger_write_time_update_immediate(fsp);
5095 return NT_STATUS_OK;
5098 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5100 if (!NT_STATUS_IS_OK(status)) {
5104 status = SMB_VFS_CREATE_FILE(
5107 0, /* root_dir_fid */
5108 smb_fname, /* fname */
5109 FILE_WRITE_ATTRIBUTES, /* access_mask */
5110 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5112 FILE_OPEN, /* create_disposition*/
5113 0, /* create_options */
5114 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5115 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5116 0, /* allocation_size */
5119 &new_fsp, /* result */
5122 *psbuf = smb_fname->st;
5123 TALLOC_FREE(smb_fname);
5125 if (!NT_STATUS_IS_OK(status)) {
5126 /* NB. We check for open_was_deferred in the caller. */
5130 if (vfs_set_filelen(new_fsp, size) == -1) {
5131 status = map_nt_error_from_unix(errno);
5132 close_file(req, new_fsp,NORMAL_CLOSE);
5136 trigger_write_time_update_immediate(new_fsp);
5137 close_file(req, new_fsp,NORMAL_CLOSE);
5138 return NT_STATUS_OK;
5141 /****************************************************************************
5142 Deal with SMB_INFO_SET_EA.
5143 ****************************************************************************/
5145 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5151 struct ea_list *ea_list = NULL;
5152 TALLOC_CTX *ctx = NULL;
5153 NTSTATUS status = NT_STATUS_OK;
5155 if (total_data < 10) {
5157 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5158 length. They seem to have no effect. Bug #3212. JRA */
5160 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5161 /* We're done. We only get EA info in this call. */
5162 return NT_STATUS_OK;
5165 return NT_STATUS_INVALID_PARAMETER;
5168 if (IVAL(pdata,0) > total_data) {
5169 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5170 IVAL(pdata,0), (unsigned int)total_data));
5171 return NT_STATUS_INVALID_PARAMETER;
5175 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5177 return NT_STATUS_INVALID_PARAMETER;
5179 status = set_ea(conn, fsp, fname, ea_list);
5184 /****************************************************************************
5185 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5186 ****************************************************************************/
5188 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5193 SMB_STRUCT_STAT *psbuf)
5195 NTSTATUS status = NT_STATUS_OK;
5196 bool delete_on_close;
5199 if (total_data < 1) {
5200 return NT_STATUS_INVALID_PARAMETER;
5204 return NT_STATUS_INVALID_HANDLE;
5207 delete_on_close = (CVAL(pdata,0) ? True : False);
5208 dosmode = dos_mode(conn, fname, psbuf);
5210 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5211 "delete_on_close = %u\n",
5213 (unsigned int)dosmode,
5214 (unsigned int)delete_on_close ));
5216 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5218 if (!NT_STATUS_IS_OK(status)) {
5222 /* The set is across all open files on this dev/inode pair. */
5223 if (!set_delete_on_close(fsp, delete_on_close,
5224 &conn->server_info->utok)) {
5225 return NT_STATUS_ACCESS_DENIED;
5227 return NT_STATUS_OK;
5230 /****************************************************************************
5231 Deal with SMB_FILE_POSITION_INFORMATION.
5232 ****************************************************************************/
5234 static NTSTATUS smb_file_position_information(connection_struct *conn,
5239 uint64_t position_information;
5241 if (total_data < 8) {
5242 return NT_STATUS_INVALID_PARAMETER;
5246 /* Ignore on pathname based set. */
5247 return NT_STATUS_OK;
5250 position_information = (uint64_t)IVAL(pdata,0);
5251 #ifdef LARGE_SMB_OFF_T
5252 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5253 #else /* LARGE_SMB_OFF_T */
5254 if (IVAL(pdata,4) != 0) {
5255 /* more than 32 bits? */
5256 return NT_STATUS_INVALID_PARAMETER;
5258 #endif /* LARGE_SMB_OFF_T */
5260 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5261 fsp->fsp_name, (double)position_information ));
5262 fsp->fh->position_information = position_information;
5263 return NT_STATUS_OK;
5266 /****************************************************************************
5267 Deal with SMB_FILE_MODE_INFORMATION.
5268 ****************************************************************************/
5270 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5276 if (total_data < 4) {
5277 return NT_STATUS_INVALID_PARAMETER;
5279 mode = IVAL(pdata,0);
5280 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5281 return NT_STATUS_INVALID_PARAMETER;
5283 return NT_STATUS_OK;
5286 /****************************************************************************
5287 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5288 ****************************************************************************/
5290 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5291 struct smb_request *req,
5296 char *link_target = NULL;
5297 const char *newname = fname;
5298 NTSTATUS status = NT_STATUS_OK;
5299 TALLOC_CTX *ctx = talloc_tos();
5301 /* Set a symbolic link. */
5302 /* Don't allow this if follow links is false. */
5304 if (total_data == 0) {
5305 return NT_STATUS_INVALID_PARAMETER;
5308 if (!lp_symlinks(SNUM(conn))) {
5309 return NT_STATUS_ACCESS_DENIED;
5312 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5313 total_data, STR_TERMINATE);
5316 return NT_STATUS_INVALID_PARAMETER;
5319 /* !widelinks forces the target path to be within the share. */
5320 /* This means we can interpret the target as a pathname. */
5321 if (!lp_widelinks(SNUM(conn))) {
5322 char *rel_name = NULL;
5323 char *last_dirp = NULL;
5325 if (*link_target == '/') {
5326 /* No absolute paths allowed. */
5327 return NT_STATUS_ACCESS_DENIED;
5329 rel_name = talloc_strdup(ctx,newname);
5331 return NT_STATUS_NO_MEMORY;
5333 last_dirp = strrchr_m(rel_name, '/');
5335 last_dirp[1] = '\0';
5337 rel_name = talloc_strdup(ctx,"./");
5339 return NT_STATUS_NO_MEMORY;
5342 rel_name = talloc_asprintf_append(rel_name,
5346 return NT_STATUS_NO_MEMORY;
5349 status = check_name(conn, rel_name);
5350 if (!NT_STATUS_IS_OK(status)) {
5355 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5356 newname, link_target ));
5358 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5359 return map_nt_error_from_unix(errno);
5362 return NT_STATUS_OK;
5365 /****************************************************************************
5366 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5367 ****************************************************************************/
5369 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5370 struct smb_request *req,
5371 const char *pdata, int total_data,
5372 const struct smb_filename *smb_fname_new)
5374 char *oldname = NULL;
5375 struct smb_filename *smb_fname_old = NULL;
5376 TALLOC_CTX *ctx = talloc_tos();
5377 NTSTATUS status = NT_STATUS_OK;
5379 /* Set a hard link. */
5380 if (total_data == 0) {
5381 return NT_STATUS_INVALID_PARAMETER;
5384 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5385 total_data, STR_TERMINATE, &status);
5386 if (!NT_STATUS_IS_OK(status)) {
5390 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5391 smb_fname_str_dbg(smb_fname_new), oldname));
5393 status = filename_convert(ctx,
5395 req->flags2 & FLAGS2_DFS_PATHNAMES,
5399 if (!NT_STATUS_IS_OK(status)) {
5403 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5406 /****************************************************************************
5407 Deal with SMB_FILE_RENAME_INFORMATION.
5408 ****************************************************************************/
5410 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5411 struct smb_request *req,
5420 char *newname = NULL;
5421 char *base_name = NULL;
5422 struct smb_filename *smb_fname = NULL;
5423 bool dest_has_wcard = False;
5424 NTSTATUS status = NT_STATUS_OK;
5426 TALLOC_CTX *ctx = talloc_tos();
5428 if (total_data < 13) {
5429 return NT_STATUS_INVALID_PARAMETER;
5432 overwrite = (CVAL(pdata,0) ? True : False);
5433 root_fid = IVAL(pdata,4);
5434 len = IVAL(pdata,8);
5436 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5437 return NT_STATUS_INVALID_PARAMETER;
5440 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5443 if (!NT_STATUS_IS_OK(status)) {
5447 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5450 status = resolve_dfspath_wcard(ctx, conn,
5451 req->flags2 & FLAGS2_DFS_PATHNAMES,
5455 if (!NT_STATUS_IS_OK(status)) {
5459 /* Check the new name has no '/' characters. */
5460 if (strchr_m(newname, '/')) {
5461 return NT_STATUS_NOT_SUPPORTED;
5464 if (fsp && fsp->base_fsp) {
5465 /* newname must be a stream name. */
5466 if (newname[0] != ':') {
5467 return NT_STATUS_NOT_SUPPORTED;
5469 base_name = talloc_asprintf(ctx, "%s%s",
5470 fsp->base_fsp->fsp_name,
5473 return NT_STATUS_NO_MEMORY;
5476 /* newname must *not* be a stream name. */
5477 if (is_ntfs_stream_name(newname)) {
5478 return NT_STATUS_NOT_SUPPORTED;
5481 /* Create the base directory. */
5482 base_name = talloc_strdup(ctx, fname);
5484 return NT_STATUS_NO_MEMORY;
5486 p = strrchr_m(base_name, '/');
5490 base_name = talloc_strdup(ctx, "./");
5492 return NT_STATUS_NO_MEMORY;
5495 /* Append the new name. */
5496 base_name = talloc_asprintf_append(base_name,
5500 return NT_STATUS_NO_MEMORY;
5503 status = unix_convert(ctx, conn, newname, &smb_fname,
5506 /* If an error we expect this to be
5507 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5509 if (!NT_STATUS_IS_OK(status)
5510 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5517 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5518 fsp->fnum, fsp->fsp_name, base_name ));
5519 status = rename_internals_fsp(conn, fsp, base_name,
5521 smb_fname->original_lcomp : NULL,
5524 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5525 fname, base_name ));
5526 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5527 overwrite, False, dest_has_wcard,
5528 FILE_WRITE_ATTRIBUTES);
5531 TALLOC_FREE(smb_fname);
5535 /****************************************************************************
5536 Deal with SMB_SET_POSIX_ACL.
5537 ****************************************************************************/
5539 #if defined(HAVE_POSIX_ACLS)
5540 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5545 SMB_STRUCT_STAT *psbuf)
5547 uint16 posix_acl_version;
5548 uint16 num_file_acls;
5549 uint16 num_def_acls;
5550 bool valid_file_acls = True;
5551 bool valid_def_acls = True;
5553 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5554 return NT_STATUS_INVALID_PARAMETER;
5556 posix_acl_version = SVAL(pdata,0);
5557 num_file_acls = SVAL(pdata,2);
5558 num_def_acls = SVAL(pdata,4);
5560 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5561 valid_file_acls = False;
5565 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5566 valid_def_acls = False;
5570 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5571 return NT_STATUS_INVALID_PARAMETER;
5574 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5575 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5576 return NT_STATUS_INVALID_PARAMETER;
5579 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5580 fname ? fname : fsp->fsp_name,
5581 (unsigned int)num_file_acls,
5582 (unsigned int)num_def_acls));
5584 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5585 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5586 return map_nt_error_from_unix(errno);
5589 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5590 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5591 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5592 return map_nt_error_from_unix(errno);
5594 return NT_STATUS_OK;
5598 /****************************************************************************
5599 Deal with SMB_SET_POSIX_LOCK.
5600 ****************************************************************************/
5602 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5603 struct smb_request *req,
5611 bool blocking_lock = False;
5612 enum brl_type lock_type;
5614 NTSTATUS status = NT_STATUS_OK;
5616 if (fsp == NULL || fsp->fh->fd == -1) {
5617 return NT_STATUS_INVALID_HANDLE;
5620 if (total_data != POSIX_LOCK_DATA_SIZE) {
5621 return NT_STATUS_INVALID_PARAMETER;
5624 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5625 case POSIX_LOCK_TYPE_READ:
5626 lock_type = READ_LOCK;
5628 case POSIX_LOCK_TYPE_WRITE:
5629 /* Return the right POSIX-mappable error code for files opened read-only. */
5630 if (!fsp->can_write) {
5631 return NT_STATUS_INVALID_HANDLE;
5633 lock_type = WRITE_LOCK;
5635 case POSIX_LOCK_TYPE_UNLOCK:
5636 lock_type = UNLOCK_LOCK;
5639 return NT_STATUS_INVALID_PARAMETER;
5642 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5643 blocking_lock = False;
5644 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5645 blocking_lock = True;
5647 return NT_STATUS_INVALID_PARAMETER;
5650 if (!lp_blocking_locks(SNUM(conn))) {
5651 blocking_lock = False;
5654 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5655 #if defined(HAVE_LONGLONG)
5656 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5657 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5658 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5659 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5660 #else /* HAVE_LONGLONG */
5661 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5662 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5663 #endif /* HAVE_LONGLONG */
5665 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5666 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5668 (unsigned int)lock_type,
5669 (unsigned int)lock_pid,
5673 if (lock_type == UNLOCK_LOCK) {
5674 status = do_unlock(smbd_messaging_context(),
5681 uint32 block_smbpid;
5683 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5695 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5697 * A blocking lock was requested. Package up
5698 * this smb into a queued request and push it
5699 * onto the blocking lock queue.
5701 if(push_blocking_lock_request(br_lck,
5704 -1, /* infinite timeout. */
5712 TALLOC_FREE(br_lck);
5716 TALLOC_FREE(br_lck);
5722 /****************************************************************************
5723 Deal with SMB_INFO_STANDARD.
5724 ****************************************************************************/
5726 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5731 const SMB_STRUCT_STAT *psbuf)
5733 struct smb_file_time ft;
5736 if (total_data < 12) {
5737 return NT_STATUS_INVALID_PARAMETER;
5741 ft.create_time = interpret_long_date(pdata);
5744 ft.atime = interpret_long_date(pdata + 8);
5747 ft.mtime = interpret_long_date(pdata + 16);
5749 DEBUG(10,("smb_set_info_standard: file %s\n",
5750 fname ? fname : fsp->fsp_name ));
5752 return smb_set_file_time(conn,
5760 /****************************************************************************
5761 Deal with SMB_SET_FILE_BASIC_INFO.
5762 ****************************************************************************/
5764 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5769 SMB_STRUCT_STAT *psbuf)
5771 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5772 struct timespec write_time;
5773 struct timespec changed_time;
5774 struct smb_file_time ft;
5776 NTSTATUS status = NT_STATUS_OK;
5777 bool setting_write_time = true;
5781 if (total_data < 36) {
5782 return NT_STATUS_INVALID_PARAMETER;
5785 /* Set the attributes */
5786 dosmode = IVAL(pdata,32);
5787 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5788 if (!NT_STATUS_IS_OK(status)) {
5793 ft.atime = interpret_long_date(pdata+8);
5795 write_time = interpret_long_date(pdata+16);
5796 changed_time = interpret_long_date(pdata+24);
5799 ft.mtime = timespec_min(&write_time, &changed_time);
5802 ft.create_time = interpret_long_date(pdata);
5804 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5805 !null_timespec(write_time)) {
5806 ft.mtime = write_time;
5809 /* Prefer a defined time to an undefined one. */
5810 if (null_timespec(ft.mtime)) {
5811 if (null_timespec(write_time)) {
5812 ft.mtime = changed_time;
5813 setting_write_time = false;
5815 ft.mtime = write_time;
5819 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5820 fname ? fname : fsp->fsp_name ));
5822 return smb_set_file_time(conn,
5827 setting_write_time);
5830 /****************************************************************************
5831 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5832 ****************************************************************************/
5834 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5835 struct smb_request *req,
5840 SMB_STRUCT_STAT *psbuf)
5842 struct smb_filename *smb_fname = NULL;
5843 uint64_t allocation_size = 0;
5844 NTSTATUS status = NT_STATUS_OK;
5845 files_struct *new_fsp = NULL;
5847 if (!VALID_STAT(*psbuf)) {
5848 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5851 if (total_data < 8) {
5852 return NT_STATUS_INVALID_PARAMETER;
5855 allocation_size = (uint64_t)IVAL(pdata,0);
5856 #ifdef LARGE_SMB_OFF_T
5857 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5858 #else /* LARGE_SMB_OFF_T */
5859 if (IVAL(pdata,4) != 0) {
5860 /* more than 32 bits? */
5861 return NT_STATUS_INVALID_PARAMETER;
5863 #endif /* LARGE_SMB_OFF_T */
5865 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5866 fname, (double)allocation_size ));
5868 if (allocation_size) {
5869 allocation_size = smb_roundup(conn, allocation_size);
5872 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5873 fname, (double)allocation_size ));
5875 if (fsp && fsp->fh->fd != -1) {
5876 /* Open file handle. */
5877 /* Only change if needed. */
5878 if (allocation_size != get_file_size_stat(psbuf)) {
5879 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5880 return map_nt_error_from_unix(errno);
5883 /* But always update the time. */
5885 * This is equivalent to a write. Ensure it's seen immediately
5886 * if there are no pending writes.
5888 trigger_write_time_update_immediate(fsp);
5889 return NT_STATUS_OK;
5892 /* Pathname or stat or directory file. */
5894 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5896 if (!NT_STATUS_IS_OK(status)) {
5900 status = SMB_VFS_CREATE_FILE(
5903 0, /* root_dir_fid */
5904 smb_fname, /* fname */
5905 FILE_WRITE_DATA, /* access_mask */
5906 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5908 FILE_OPEN, /* create_disposition*/
5909 0, /* create_options */
5910 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5911 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5912 0, /* allocation_size */
5915 &new_fsp, /* result */
5918 *psbuf = smb_fname->st;
5919 TALLOC_FREE(smb_fname);
5921 if (!NT_STATUS_IS_OK(status)) {
5922 /* NB. We check for open_was_deferred in the caller. */
5926 /* Only change if needed. */
5927 if (allocation_size != get_file_size_stat(psbuf)) {
5928 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5929 status = map_nt_error_from_unix(errno);
5930 close_file(req, new_fsp, NORMAL_CLOSE);
5935 /* Changing the allocation size should set the last mod time. */
5937 * This is equivalent to a write. Ensure it's seen immediately
5938 * if there are no pending writes.
5940 trigger_write_time_update_immediate(new_fsp);
5942 close_file(req, new_fsp, NORMAL_CLOSE);
5943 return NT_STATUS_OK;
5946 /****************************************************************************
5947 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5948 ****************************************************************************/
5950 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5951 struct smb_request *req,
5956 SMB_STRUCT_STAT *psbuf)
5960 if (total_data < 8) {
5961 return NT_STATUS_INVALID_PARAMETER;
5964 size = IVAL(pdata,0);
5965 #ifdef LARGE_SMB_OFF_T
5966 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5967 #else /* LARGE_SMB_OFF_T */
5968 if (IVAL(pdata,4) != 0) {
5969 /* more than 32 bits? */
5970 return NT_STATUS_INVALID_PARAMETER;
5972 #endif /* LARGE_SMB_OFF_T */
5973 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5974 "file %s to %.0f\n", fname, (double)size ));
5976 return smb_set_file_size(conn, req,
5983 /****************************************************************************
5984 Allow a UNIX info mknod.
5985 ****************************************************************************/
5987 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5991 SMB_STRUCT_STAT *psbuf)
5993 uint32 file_type = IVAL(pdata,56);
5994 #if defined(HAVE_MAKEDEV)
5995 uint32 dev_major = IVAL(pdata,60);
5996 uint32 dev_minor = IVAL(pdata,68);
5998 SMB_DEV_T dev = (SMB_DEV_T)0;
5999 uint32 raw_unixmode = IVAL(pdata,84);
6003 if (total_data < 100) {
6004 return NT_STATUS_INVALID_PARAMETER;
6007 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
6008 if (!NT_STATUS_IS_OK(status)) {
6012 #if defined(HAVE_MAKEDEV)
6013 dev = makedev(dev_major, dev_minor);
6016 switch (file_type) {
6017 #if defined(S_IFIFO)
6018 case UNIX_TYPE_FIFO:
6019 unixmode |= S_IFIFO;
6022 #if defined(S_IFSOCK)
6023 case UNIX_TYPE_SOCKET:
6024 unixmode |= S_IFSOCK;
6027 #if defined(S_IFCHR)
6028 case UNIX_TYPE_CHARDEV:
6029 unixmode |= S_IFCHR;
6032 #if defined(S_IFBLK)
6033 case UNIX_TYPE_BLKDEV:
6034 unixmode |= S_IFBLK;
6038 return NT_STATUS_INVALID_PARAMETER;
6041 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6042 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6044 /* Ok - do the mknod. */
6045 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6046 return map_nt_error_from_unix(errno);
6049 /* If any of the other "set" calls fail we
6050 * don't want to end up with a half-constructed mknod.
6053 if (lp_inherit_perms(SNUM(conn))) {
6055 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6056 return NT_STATUS_NO_MEMORY;
6058 inherit_access_posix_acl(conn, parent, fname, unixmode);
6059 TALLOC_FREE(parent);
6062 if (vfs_stat_smb_fname(conn, fname, psbuf) != 0) {
6063 status = map_nt_error_from_unix(errno);
6064 SMB_VFS_UNLINK(conn,fname);
6067 return NT_STATUS_OK;
6070 /****************************************************************************
6071 Deal with SMB_SET_FILE_UNIX_BASIC.
6072 ****************************************************************************/
6074 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6075 struct smb_request *req,
6080 SMB_STRUCT_STAT *psbuf)
6082 struct smb_file_time ft;
6083 uint32 raw_unixmode;
6086 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6087 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6088 NTSTATUS status = NT_STATUS_OK;
6089 bool delete_on_fail = False;
6090 enum perm_type ptype;
6094 if (total_data < 100) {
6095 return NT_STATUS_INVALID_PARAMETER;
6098 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6099 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6100 size=IVAL(pdata,0); /* first 8 Bytes are size */
6101 #ifdef LARGE_SMB_OFF_T
6102 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6103 #else /* LARGE_SMB_OFF_T */
6104 if (IVAL(pdata,4) != 0) {
6105 /* more than 32 bits? */
6106 return NT_STATUS_INVALID_PARAMETER;
6108 #endif /* LARGE_SMB_OFF_T */
6111 ft.atime = interpret_long_date(pdata+24); /* access_time */
6112 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6113 set_owner = (uid_t)IVAL(pdata,40);
6114 set_grp = (gid_t)IVAL(pdata,48);
6115 raw_unixmode = IVAL(pdata,84);
6117 if (VALID_STAT(*psbuf)) {
6118 if (S_ISDIR(psbuf->st_ex_mode)) {
6119 ptype = PERM_EXISTING_DIR;
6121 ptype = PERM_EXISTING_FILE;
6124 ptype = PERM_NEW_FILE;
6127 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6128 if (!NT_STATUS_IS_OK(status)) {
6132 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6133 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6134 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6136 if (!VALID_STAT(*psbuf)) {
6138 * The only valid use of this is to create character and block
6139 * devices, and named pipes. This is deprecated (IMHO) and
6140 * a new info level should be used for mknod. JRA.
6143 status = smb_unix_mknod(conn,
6148 if (!NT_STATUS_IS_OK(status)) {
6152 /* Ensure we don't try and change anything else. */
6153 raw_unixmode = SMB_MODE_NO_CHANGE;
6154 size = get_file_size_stat(psbuf);
6155 ft.atime = psbuf->st_ex_atime;
6156 ft.mtime = psbuf->st_ex_mtime;
6158 * We continue here as we might want to change the
6161 delete_on_fail = True;
6165 /* Horrible backwards compatibility hack as an old server bug
6166 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6170 size = get_file_size_stat(psbuf);
6175 * Deal with the UNIX specific mode set.
6178 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6179 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6180 (unsigned int)unixmode, fname ));
6181 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6182 return map_nt_error_from_unix(errno);
6187 * Deal with the UNIX specific uid set.
6190 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_ex_uid != set_owner)) {
6193 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6194 (unsigned int)set_owner, fname ));
6196 if (S_ISLNK(psbuf->st_ex_mode)) {
6197 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6199 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6203 status = map_nt_error_from_unix(errno);
6204 if (delete_on_fail) {
6205 SMB_VFS_UNLINK(conn,fname);
6212 * Deal with the UNIX specific gid set.
6215 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_ex_gid != set_grp)) {
6216 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6217 (unsigned int)set_owner, fname ));
6218 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6219 status = map_nt_error_from_unix(errno);
6220 if (delete_on_fail) {
6221 SMB_VFS_UNLINK(conn,fname);
6227 /* Deal with any size changes. */
6229 status = smb_set_file_size(conn, req,
6234 if (!NT_STATUS_IS_OK(status)) {
6238 /* Deal with any time changes. */
6240 return smb_set_file_time(conn,
6248 /****************************************************************************
6249 Deal with SMB_SET_FILE_UNIX_INFO2.
6250 ****************************************************************************/
6252 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6253 struct smb_request *req,
6258 SMB_STRUCT_STAT *psbuf)
6264 if (total_data < 116) {
6265 return NT_STATUS_INVALID_PARAMETER;
6268 /* Start by setting all the fields that are common between UNIX_BASIC
6271 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6273 if (!NT_STATUS_IS_OK(status)) {
6277 smb_fflags = IVAL(pdata, 108);
6278 smb_fmask = IVAL(pdata, 112);
6280 /* NB: We should only attempt to alter the file flags if the client
6281 * sends a non-zero mask.
6283 if (smb_fmask != 0) {
6284 int stat_fflags = 0;
6286 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6288 /* Client asked to alter a flag we don't understand. */
6289 return NT_STATUS_INVALID_PARAMETER;
6292 if (fsp && fsp->fh->fd != -1) {
6293 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6294 return NT_STATUS_NOT_SUPPORTED;
6296 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6297 return map_nt_error_from_unix(errno);
6302 /* XXX: need to add support for changing the create_time here. You
6303 * can do this for paths on Darwin with setattrlist(2). The right way
6304 * to hook this up is probably by extending the VFS utimes interface.
6307 return NT_STATUS_OK;
6310 /****************************************************************************
6311 Create a directory with POSIX semantics.
6312 ****************************************************************************/
6314 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6315 struct smb_request *req,
6319 SMB_STRUCT_STAT *psbuf,
6320 int *pdata_return_size)
6322 struct smb_filename *smb_fname;
6323 NTSTATUS status = NT_STATUS_OK;
6324 uint32 raw_unixmode = 0;
6325 uint32 mod_unixmode = 0;
6326 mode_t unixmode = (mode_t)0;
6327 files_struct *fsp = NULL;
6328 uint16 info_level_return = 0;
6330 char *pdata = *ppdata;
6332 if (total_data < 18) {
6333 return NT_STATUS_INVALID_PARAMETER;
6336 raw_unixmode = IVAL(pdata,8);
6337 /* Next 4 bytes are not yet defined. */
6339 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6340 if (!NT_STATUS_IS_OK(status)) {
6344 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6346 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6347 fname, (unsigned int)unixmode ));
6349 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6351 if (!NT_STATUS_IS_OK(status)) {
6355 status = SMB_VFS_CREATE_FILE(
6358 0, /* root_dir_fid */
6359 smb_fname, /* fname */
6360 FILE_READ_ATTRIBUTES, /* access_mask */
6361 FILE_SHARE_NONE, /* share_access */
6362 FILE_CREATE, /* create_disposition*/
6363 FILE_DIRECTORY_FILE, /* create_options */
6364 mod_unixmode, /* file_attributes */
6365 0, /* oplock_request */
6366 0, /* allocation_size */
6372 *psbuf = smb_fname->st;
6373 TALLOC_FREE(smb_fname);
6375 if (NT_STATUS_IS_OK(status)) {
6376 close_file(req, fsp, NORMAL_CLOSE);
6379 info_level_return = SVAL(pdata,16);
6381 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6382 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6383 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6384 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6386 *pdata_return_size = 12;
6389 /* Realloc the data size */
6390 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6391 if (*ppdata == NULL) {
6392 *pdata_return_size = 0;
6393 return NT_STATUS_NO_MEMORY;
6397 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6398 SSVAL(pdata,2,0); /* No fnum. */
6399 SIVAL(pdata,4,info); /* Was directory created. */
6401 switch (info_level_return) {
6402 case SMB_QUERY_FILE_UNIX_BASIC:
6403 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6404 SSVAL(pdata,10,0); /* Padding. */
6405 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6407 case SMB_QUERY_FILE_UNIX_INFO2:
6408 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6409 SSVAL(pdata,10,0); /* Padding. */
6410 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6413 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6414 SSVAL(pdata,10,0); /* Padding. */
6421 /****************************************************************************
6422 Open/Create a file with POSIX semantics.
6423 ****************************************************************************/
6425 static NTSTATUS smb_posix_open(connection_struct *conn,
6426 struct smb_request *req,
6430 SMB_STRUCT_STAT *psbuf,
6431 int *pdata_return_size)
6433 struct smb_filename *smb_fname = NULL;
6434 bool extended_oplock_granted = False;
6435 char *pdata = *ppdata;
6437 uint32 wire_open_mode = 0;
6438 uint32 raw_unixmode = 0;
6439 uint32 mod_unixmode = 0;
6440 uint32 create_disp = 0;
6441 uint32 access_mask = 0;
6442 uint32 create_options = 0;
6443 NTSTATUS status = NT_STATUS_OK;
6444 mode_t unixmode = (mode_t)0;
6445 files_struct *fsp = NULL;
6446 int oplock_request = 0;
6448 uint16 info_level_return = 0;
6450 if (total_data < 18) {
6451 return NT_STATUS_INVALID_PARAMETER;
6454 flags = IVAL(pdata,0);
6455 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6456 if (oplock_request) {
6457 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6460 wire_open_mode = IVAL(pdata,4);
6462 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6463 return smb_posix_mkdir(conn, req,
6471 switch (wire_open_mode & SMB_ACCMODE) {
6473 access_mask = FILE_READ_DATA;
6476 access_mask = FILE_WRITE_DATA;
6479 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6482 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6483 (unsigned int)wire_open_mode ));
6484 return NT_STATUS_INVALID_PARAMETER;
6487 wire_open_mode &= ~SMB_ACCMODE;
6489 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6490 create_disp = FILE_CREATE;
6491 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6492 create_disp = FILE_OVERWRITE_IF;
6493 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6494 create_disp = FILE_OPEN_IF;
6495 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6496 create_disp = FILE_OPEN;
6498 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6499 (unsigned int)wire_open_mode ));
6500 return NT_STATUS_INVALID_PARAMETER;
6503 raw_unixmode = IVAL(pdata,8);
6504 /* Next 4 bytes are not yet defined. */
6506 status = unix_perms_from_wire(conn,
6509 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6512 if (!NT_STATUS_IS_OK(status)) {
6516 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6518 if (wire_open_mode & SMB_O_SYNC) {
6519 create_options |= FILE_WRITE_THROUGH;
6521 if (wire_open_mode & SMB_O_APPEND) {
6522 access_mask |= FILE_APPEND_DATA;
6524 if (wire_open_mode & SMB_O_DIRECT) {
6525 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6528 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6530 (unsigned int)wire_open_mode,
6531 (unsigned int)unixmode ));
6533 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6535 if (!NT_STATUS_IS_OK(status)) {
6539 status = SMB_VFS_CREATE_FILE(
6542 0, /* root_dir_fid */
6543 smb_fname, /* fname */
6544 access_mask, /* access_mask */
6545 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6547 create_disp, /* create_disposition*/
6548 FILE_NON_DIRECTORY_FILE, /* create_options */
6549 mod_unixmode, /* file_attributes */
6550 oplock_request, /* oplock_request */
6551 0, /* allocation_size */
6557 *psbuf = smb_fname->st;
6558 TALLOC_FREE(smb_fname);
6560 if (!NT_STATUS_IS_OK(status)) {
6564 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6565 extended_oplock_granted = True;
6568 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6569 extended_oplock_granted = True;
6572 info_level_return = SVAL(pdata,16);
6574 /* Allocate the correct return size. */
6576 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6577 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6578 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6579 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6581 *pdata_return_size = 12;
6584 /* Realloc the data size */
6585 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6586 if (*ppdata == NULL) {
6587 close_file(req, fsp, ERROR_CLOSE);
6588 *pdata_return_size = 0;
6589 return NT_STATUS_NO_MEMORY;
6593 if (extended_oplock_granted) {
6594 if (flags & REQUEST_BATCH_OPLOCK) {
6595 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6597 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6599 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6600 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6602 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6605 SSVAL(pdata,2,fsp->fnum);
6606 SIVAL(pdata,4,info); /* Was file created etc. */
6608 switch (info_level_return) {
6609 case SMB_QUERY_FILE_UNIX_BASIC:
6610 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6611 SSVAL(pdata,10,0); /* padding. */
6612 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6614 case SMB_QUERY_FILE_UNIX_INFO2:
6615 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6616 SSVAL(pdata,10,0); /* padding. */
6617 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6620 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6621 SSVAL(pdata,10,0); /* padding. */
6624 return NT_STATUS_OK;
6627 /****************************************************************************
6628 Delete a file with POSIX semantics.
6629 ****************************************************************************/
6631 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6632 struct smb_request *req,
6636 SMB_STRUCT_STAT *psbuf)
6638 struct smb_filename *smb_fname = NULL;
6639 NTSTATUS status = NT_STATUS_OK;
6640 files_struct *fsp = NULL;
6644 int create_options = 0;
6646 struct share_mode_lock *lck = NULL;
6648 if (total_data < 2) {
6649 return NT_STATUS_INVALID_PARAMETER;
6652 flags = SVAL(pdata,0);
6654 if (!VALID_STAT(*psbuf)) {
6655 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6658 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6659 !VALID_STAT_OF_DIR(*psbuf)) {
6660 return NT_STATUS_NOT_A_DIRECTORY;
6663 DEBUG(10,("smb_posix_unlink: %s %s\n",
6664 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6667 if (VALID_STAT_OF_DIR(*psbuf)) {
6668 create_options |= FILE_DIRECTORY_FILE;
6671 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6673 if (!NT_STATUS_IS_OK(status)) {
6677 status = SMB_VFS_CREATE_FILE(
6680 0, /* root_dir_fid */
6681 smb_fname, /* fname */
6682 DELETE_ACCESS, /* access_mask */
6683 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6685 FILE_OPEN, /* create_disposition*/
6686 create_options, /* create_options */
6687 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6688 0, /* oplock_request */
6689 0, /* allocation_size */
6695 *psbuf = smb_fname->st;
6696 TALLOC_FREE(smb_fname);
6698 if (!NT_STATUS_IS_OK(status)) {
6703 * Don't lie to client. If we can't really delete due to
6704 * non-POSIX opens return SHARING_VIOLATION.
6707 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6710 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6711 "lock for file %s\n", fsp->fsp_name));
6712 close_file(req, fsp, NORMAL_CLOSE);
6713 return NT_STATUS_INVALID_PARAMETER;
6717 * See if others still have the file open. If this is the case, then
6718 * don't delete. If all opens are POSIX delete we can set the delete
6719 * on close disposition.
6721 for (i=0; i<lck->num_share_modes; i++) {
6722 struct share_mode_entry *e = &lck->share_modes[i];
6723 if (is_valid_share_mode_entry(e)) {
6724 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6727 /* Fail with sharing violation. */
6728 close_file(req, fsp, NORMAL_CLOSE);
6730 return NT_STATUS_SHARING_VIOLATION;
6735 * Set the delete on close.
6737 status = smb_set_file_disposition_info(conn,
6744 if (!NT_STATUS_IS_OK(status)) {
6745 close_file(req, fsp, NORMAL_CLOSE);
6750 return close_file(req, fsp, NORMAL_CLOSE);
6753 /****************************************************************************
6754 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6755 ****************************************************************************/
6757 static void call_trans2setfilepathinfo(connection_struct *conn,
6758 struct smb_request *req,
6759 unsigned int tran_call,
6760 char **pparams, int total_params,
6761 char **ppdata, int total_data,
6762 unsigned int max_data_bytes)
6764 char *params = *pparams;
6765 char *pdata = *ppdata;
6767 SMB_STRUCT_STAT sbuf;
6769 struct smb_filename *smb_fname = NULL;
6770 files_struct *fsp = NULL;
6771 NTSTATUS status = NT_STATUS_OK;
6772 int data_return_size = 0;
6773 TALLOC_CTX *ctx = talloc_tos();
6776 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6780 if (tran_call == TRANSACT2_SETFILEINFO) {
6781 if (total_params < 4) {
6782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6786 fsp = file_fsp(req, SVAL(params,0));
6787 /* Basic check for non-null fsp. */
6788 if (!check_fsp_open(conn, req, fsp)) {
6791 info_level = SVAL(params,2);
6793 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6795 reply_nterror(req, NT_STATUS_NO_MEMORY);
6799 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
6801 if (!NT_STATUS_IS_OK(status)) {
6802 reply_nterror(req, status);
6806 if(fsp->is_directory || fsp->fh->fd == -1) {
6808 * This is actually a SETFILEINFO on a directory
6809 * handle (returned from an NT SMB). NT5.0 seems
6810 * to do this call. JRA.
6812 if (INFO_LEVEL_IS_UNIX(info_level)) {
6813 /* Always do lstat for UNIX calls. */
6814 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6815 DEBUG(3,("call_trans2setfilepathinfo: "
6816 "SMB_VFS_LSTAT of %s failed "
6818 smb_fname_str_dbg(smb_fname),
6820 reply_unixerror(req,ERRDOS,ERRbadpath);
6824 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6825 DEBUG(3,("call_trans2setfilepathinfo: "
6826 "fileinfo of %s failed (%s)\n",
6827 smb_fname_str_dbg(smb_fname),
6829 reply_unixerror(req,ERRDOS,ERRbadpath);
6833 } else if (fsp->print_file) {
6835 * Doing a DELETE_ON_CLOSE should cancel a print job.
6837 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6838 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6840 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6843 send_trans2_replies(conn, req, params, 2,
6848 reply_unixerror(req, ERRDOS, ERRbadpath);
6853 * Original code - this is an open file.
6855 if (!check_fsp(conn, req, fsp)) {
6859 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6860 DEBUG(3,("call_trans2setfilepathinfo: fstat "
6861 "of fnum %d failed (%s)\n", fsp->fnum,
6863 reply_unixerror(req, ERRDOS, ERRbadfid);
6869 if (total_params < 7) {
6870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6874 info_level = SVAL(params,0);
6875 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6876 total_params - 6, STR_TERMINATE,
6878 if (!NT_STATUS_IS_OK(status)) {
6879 reply_nterror(req, status);
6883 status = filename_convert(ctx, conn,
6884 req->flags2 & FLAGS2_DFS_PATHNAMES,
6888 if (!NT_STATUS_IS_OK(status)) {
6889 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6890 reply_botherror(req,
6891 NT_STATUS_PATH_NOT_COVERED,
6892 ERRSRV, ERRbadpath);
6895 reply_nterror(req, status);
6899 if (INFO_LEVEL_IS_UNIX(info_level)) {
6901 * For CIFS UNIX extensions the target name may not exist.
6904 /* Always do lstat for UNIX calls. */
6905 SMB_VFS_LSTAT(conn, smb_fname);
6907 } else if (!VALID_STAT(smb_fname->st) &&
6908 SMB_VFS_STAT(conn, smb_fname)) {
6909 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
6911 smb_fname_str_dbg(smb_fname),
6913 reply_unixerror(req, ERRDOS, ERRbadpath);
6918 /* Set sbuf for use below. */
6919 sbuf = smb_fname->st;
6921 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6922 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6926 if (!CAN_WRITE(conn)) {
6927 /* Allow POSIX opens. The open path will deny
6928 * any non-readonly opens. */
6929 if (info_level != SMB_POSIX_PATH_OPEN) {
6930 reply_doserror(req, ERRSRV, ERRaccess);
6935 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6936 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6938 /* Realloc the parameter size */
6939 *pparams = (char *)SMB_REALLOC(*pparams,2);
6940 if (*pparams == NULL) {
6941 reply_nterror(req, NT_STATUS_NO_MEMORY);
6948 switch (info_level) {
6950 case SMB_INFO_STANDARD:
6952 status = smb_set_info_standard(conn,
6961 case SMB_INFO_SET_EA:
6963 status = smb_info_set_ea(conn,
6971 case SMB_SET_FILE_BASIC_INFO:
6972 case SMB_FILE_BASIC_INFORMATION:
6974 status = smb_set_file_basic_info(conn,
6983 case SMB_FILE_ALLOCATION_INFORMATION:
6984 case SMB_SET_FILE_ALLOCATION_INFO:
6986 status = smb_set_file_allocation_info(conn, req,
6995 case SMB_FILE_END_OF_FILE_INFORMATION:
6996 case SMB_SET_FILE_END_OF_FILE_INFO:
6998 status = smb_set_file_end_of_file_info(conn, req,
7007 case SMB_FILE_DISPOSITION_INFORMATION:
7008 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7011 /* JRA - We used to just ignore this on a path ?
7012 * Shouldn't this be invalid level on a pathname
7015 if (tran_call != TRANSACT2_SETFILEINFO) {
7016 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7019 status = smb_set_file_disposition_info(conn,
7028 case SMB_FILE_POSITION_INFORMATION:
7030 status = smb_file_position_information(conn,
7037 /* From tridge Samba4 :
7038 * MODE_INFORMATION in setfileinfo (I have no
7039 * idea what "mode information" on a file is - it takes a value of 0,
7040 * 2, 4 or 6. What could it be?).
7043 case SMB_FILE_MODE_INFORMATION:
7045 status = smb_file_mode_information(conn,
7052 * CIFS UNIX extensions.
7055 case SMB_SET_FILE_UNIX_BASIC:
7057 status = smb_set_file_unix_basic(conn, req,
7066 case SMB_SET_FILE_UNIX_INFO2:
7068 status = smb_set_file_unix_info2(conn, req,
7077 case SMB_SET_FILE_UNIX_LINK:
7079 if (tran_call != TRANSACT2_SETPATHINFO) {
7080 /* We must have a pathname for this. */
7081 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7084 status = smb_set_file_unix_link(conn, req, pdata,
7089 case SMB_SET_FILE_UNIX_HLINK:
7091 if (tran_call != TRANSACT2_SETPATHINFO || smb_fname == NULL) {
7092 /* We must have a pathname for this. */
7093 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7096 status = smb_set_file_unix_hlink(conn, req,
7102 case SMB_FILE_RENAME_INFORMATION:
7104 status = smb_file_rename_information(conn, req,
7110 #if defined(HAVE_POSIX_ACLS)
7111 case SMB_SET_POSIX_ACL:
7113 status = smb_set_posix_acl(conn,
7123 case SMB_SET_POSIX_LOCK:
7125 if (tran_call != TRANSACT2_SETFILEINFO) {
7126 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7129 status = smb_set_posix_lock(conn, req,
7130 pdata, total_data, fsp);
7134 case SMB_POSIX_PATH_OPEN:
7136 if (tran_call != TRANSACT2_SETPATHINFO) {
7137 /* We must have a pathname for this. */
7138 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7142 status = smb_posix_open(conn, req,
7151 case SMB_POSIX_PATH_UNLINK:
7153 if (tran_call != TRANSACT2_SETPATHINFO) {
7154 /* We must have a pathname for this. */
7155 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7159 status = smb_posix_unlink(conn, req,
7168 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7172 if (!NT_STATUS_IS_OK(status)) {
7173 if (open_was_deferred(req->mid)) {
7174 /* We have re-scheduled this call. */
7177 if (blocking_lock_was_deferred(req->mid)) {
7178 /* We have re-scheduled this call. */
7181 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7182 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7183 ERRSRV, ERRbadpath);
7186 if (info_level == SMB_POSIX_PATH_OPEN) {
7187 reply_openerror(req, status);
7191 reply_nterror(req, status);
7196 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7202 /****************************************************************************
7203 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7204 ****************************************************************************/
7206 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7207 char **pparams, int total_params,
7208 char **ppdata, int total_data,
7209 unsigned int max_data_bytes)
7211 struct smb_filename *smb_dname = NULL;
7212 char *params = *pparams;
7213 char *pdata = *ppdata;
7214 char *directory = NULL;
7215 NTSTATUS status = NT_STATUS_OK;
7216 struct ea_list *ea_list = NULL;
7217 TALLOC_CTX *ctx = talloc_tos();
7219 if (!CAN_WRITE(conn)) {
7220 reply_doserror(req, ERRSRV, ERRaccess);
7224 if (total_params < 5) {
7225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7229 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7230 total_params - 4, STR_TERMINATE,
7232 if (!NT_STATUS_IS_OK(status)) {
7233 reply_nterror(req, status);
7237 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7239 status = filename_convert(ctx,
7241 req->flags2 & FLAGS2_DFS_PATHNAMES,
7246 if (!NT_STATUS_IS_OK(status)) {
7247 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7248 reply_botherror(req,
7249 NT_STATUS_PATH_NOT_COVERED,
7250 ERRSRV, ERRbadpath);
7253 reply_nterror(req, status);
7257 /* Any data in this call is an EA list. */
7258 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7259 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7264 * OS/2 workplace shell seems to send SET_EA requests of "null"
7265 * length (4 bytes containing IVAL 4).
7266 * They seem to have no effect. Bug #3212. JRA.
7269 if (total_data != 4) {
7270 if (total_data < 10) {
7271 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7275 if (IVAL(pdata,0) > total_data) {
7276 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7277 IVAL(pdata,0), (unsigned int)total_data));
7278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7282 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7289 /* If total_data == 4 Windows doesn't care what values
7290 * are placed in that field, it just ignores them.
7291 * The System i QNTC IBM SMB client puts bad values here,
7292 * so ignore them. */
7294 status = create_directory(conn, req, smb_dname);
7296 if (!NT_STATUS_IS_OK(status)) {
7297 reply_nterror(req, status);
7301 /* Try and set any given EA. */
7303 status = set_ea(conn, NULL, smb_dname->base_name, ea_list);
7304 if (!NT_STATUS_IS_OK(status)) {
7305 reply_nterror(req, status);
7310 /* Realloc the parameter and data sizes */
7311 *pparams = (char *)SMB_REALLOC(*pparams,2);
7312 if(*pparams == NULL) {
7313 reply_nterror(req, NT_STATUS_NO_MEMORY);
7320 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7323 TALLOC_FREE(smb_dname);
7327 /****************************************************************************
7328 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7329 We don't actually do this - we just send a null response.
7330 ****************************************************************************/
7332 static void call_trans2findnotifyfirst(connection_struct *conn,
7333 struct smb_request *req,
7334 char **pparams, int total_params,
7335 char **ppdata, int total_data,
7336 unsigned int max_data_bytes)
7338 char *params = *pparams;
7341 if (total_params < 6) {
7342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7346 info_level = SVAL(params,4);
7347 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7349 switch (info_level) {
7354 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7358 /* Realloc the parameter and data sizes */
7359 *pparams = (char *)SMB_REALLOC(*pparams,6);
7360 if (*pparams == NULL) {
7361 reply_nterror(req, NT_STATUS_NO_MEMORY);
7366 SSVAL(params,0,fnf_handle);
7367 SSVAL(params,2,0); /* No changes */
7368 SSVAL(params,4,0); /* No EA errors */
7375 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7380 /****************************************************************************
7381 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7382 changes). Currently this does nothing.
7383 ****************************************************************************/
7385 static void call_trans2findnotifynext(connection_struct *conn,
7386 struct smb_request *req,
7387 char **pparams, int total_params,
7388 char **ppdata, int total_data,
7389 unsigned int max_data_bytes)
7391 char *params = *pparams;
7393 DEBUG(3,("call_trans2findnotifynext\n"));
7395 /* Realloc the parameter and data sizes */
7396 *pparams = (char *)SMB_REALLOC(*pparams,4);
7397 if (*pparams == NULL) {
7398 reply_nterror(req, NT_STATUS_NO_MEMORY);
7403 SSVAL(params,0,0); /* No changes */
7404 SSVAL(params,2,0); /* No EA errors */
7406 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7411 /****************************************************************************
7412 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7413 ****************************************************************************/
7415 static void call_trans2getdfsreferral(connection_struct *conn,
7416 struct smb_request *req,
7417 char **pparams, int total_params,
7418 char **ppdata, int total_data,
7419 unsigned int max_data_bytes)
7421 char *params = *pparams;
7422 char *pathname = NULL;
7424 int max_referral_level;
7425 NTSTATUS status = NT_STATUS_OK;
7426 TALLOC_CTX *ctx = talloc_tos();
7428 DEBUG(10,("call_trans2getdfsreferral\n"));
7430 if (total_params < 3) {
7431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7435 max_referral_level = SVAL(params,0);
7437 if(!lp_host_msdfs()) {
7438 reply_doserror(req, ERRDOS, ERRbadfunc);
7442 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7443 total_params - 2, STR_TERMINATE);
7445 reply_nterror(req, NT_STATUS_NOT_FOUND);
7448 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7449 ppdata,&status)) < 0) {
7450 reply_nterror(req, status);
7454 SSVAL(req->inbuf, smb_flg2,
7455 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7456 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7461 #define LMCAT_SPL 0x53
7462 #define LMFUNC_GETJOBID 0x60
7464 /****************************************************************************
7465 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7466 ****************************************************************************/
7468 static void call_trans2ioctl(connection_struct *conn,
7469 struct smb_request *req,
7470 char **pparams, int total_params,
7471 char **ppdata, int total_data,
7472 unsigned int max_data_bytes)
7474 char *pdata = *ppdata;
7475 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7477 /* check for an invalid fid before proceeding */
7480 reply_doserror(req, ERRDOS, ERRbadfid);
7484 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7485 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7486 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7487 if (*ppdata == NULL) {
7488 reply_nterror(req, NT_STATUS_NO_MEMORY);
7493 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7494 CAN ACCEPT THIS IN UNICODE. JRA. */
7496 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7497 srvstr_push(pdata, req->flags2, pdata + 2,
7498 global_myname(), 15,
7499 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7500 srvstr_push(pdata, req->flags2, pdata+18,
7501 lp_servicename(SNUM(conn)), 13,
7502 STR_ASCII|STR_TERMINATE); /* Service name */
7503 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7508 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7509 reply_doserror(req, ERRSRV, ERRerror);
7512 /****************************************************************************
7513 Reply to a SMBfindclose (stop trans2 directory search).
7514 ****************************************************************************/
7516 void reply_findclose(struct smb_request *req)
7520 START_PROFILE(SMBfindclose);
7523 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7524 END_PROFILE(SMBfindclose);
7528 dptr_num = SVALS(req->vwv+0, 0);
7530 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7532 dptr_close(&dptr_num);
7534 reply_outbuf(req, 0, 0);
7536 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7538 END_PROFILE(SMBfindclose);
7542 /****************************************************************************
7543 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7544 ****************************************************************************/
7546 void reply_findnclose(struct smb_request *req)
7550 START_PROFILE(SMBfindnclose);
7553 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7554 END_PROFILE(SMBfindnclose);
7558 dptr_num = SVAL(req->vwv+0, 0);
7560 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7562 /* We never give out valid handles for a
7563 findnotifyfirst - so any dptr_num is ok here.
7566 reply_outbuf(req, 0, 0);
7568 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7570 END_PROFILE(SMBfindnclose);
7574 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7575 struct trans_state *state)
7577 if (Protocol >= PROTOCOL_NT1) {
7578 req->flags2 |= 0x40; /* IS_LONG_NAME */
7579 SSVAL(req->inbuf,smb_flg2,req->flags2);
7582 if (conn->encrypt_level == Required && !req->encrypted) {
7583 if (state->call != TRANSACT2_QFSINFO &&
7584 state->call != TRANSACT2_SETFSINFO) {
7585 DEBUG(0,("handle_trans2: encryption required "
7587 (unsigned int)state->call));
7588 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7593 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7595 /* Now we must call the relevant TRANS2 function */
7596 switch(state->call) {
7597 case TRANSACT2_OPEN:
7599 START_PROFILE(Trans2_open);
7600 call_trans2open(conn, req,
7601 &state->param, state->total_param,
7602 &state->data, state->total_data,
7603 state->max_data_return);
7604 END_PROFILE(Trans2_open);
7608 case TRANSACT2_FINDFIRST:
7610 START_PROFILE(Trans2_findfirst);
7611 call_trans2findfirst(conn, req,
7612 &state->param, state->total_param,
7613 &state->data, state->total_data,
7614 state->max_data_return);
7615 END_PROFILE(Trans2_findfirst);
7619 case TRANSACT2_FINDNEXT:
7621 START_PROFILE(Trans2_findnext);
7622 call_trans2findnext(conn, req,
7623 &state->param, state->total_param,
7624 &state->data, state->total_data,
7625 state->max_data_return);
7626 END_PROFILE(Trans2_findnext);
7630 case TRANSACT2_QFSINFO:
7632 START_PROFILE(Trans2_qfsinfo);
7633 call_trans2qfsinfo(conn, req,
7634 &state->param, state->total_param,
7635 &state->data, state->total_data,
7636 state->max_data_return);
7637 END_PROFILE(Trans2_qfsinfo);
7641 case TRANSACT2_SETFSINFO:
7643 START_PROFILE(Trans2_setfsinfo);
7644 call_trans2setfsinfo(conn, req,
7645 &state->param, state->total_param,
7646 &state->data, state->total_data,
7647 state->max_data_return);
7648 END_PROFILE(Trans2_setfsinfo);
7652 case TRANSACT2_QPATHINFO:
7653 case TRANSACT2_QFILEINFO:
7655 START_PROFILE(Trans2_qpathinfo);
7656 call_trans2qfilepathinfo(conn, req, state->call,
7657 &state->param, state->total_param,
7658 &state->data, state->total_data,
7659 state->max_data_return);
7660 END_PROFILE(Trans2_qpathinfo);
7664 case TRANSACT2_SETPATHINFO:
7665 case TRANSACT2_SETFILEINFO:
7667 START_PROFILE(Trans2_setpathinfo);
7668 call_trans2setfilepathinfo(conn, req, state->call,
7669 &state->param, state->total_param,
7670 &state->data, state->total_data,
7671 state->max_data_return);
7672 END_PROFILE(Trans2_setpathinfo);
7676 case TRANSACT2_FINDNOTIFYFIRST:
7678 START_PROFILE(Trans2_findnotifyfirst);
7679 call_trans2findnotifyfirst(conn, req,
7680 &state->param, state->total_param,
7681 &state->data, state->total_data,
7682 state->max_data_return);
7683 END_PROFILE(Trans2_findnotifyfirst);
7687 case TRANSACT2_FINDNOTIFYNEXT:
7689 START_PROFILE(Trans2_findnotifynext);
7690 call_trans2findnotifynext(conn, req,
7691 &state->param, state->total_param,
7692 &state->data, state->total_data,
7693 state->max_data_return);
7694 END_PROFILE(Trans2_findnotifynext);
7698 case TRANSACT2_MKDIR:
7700 START_PROFILE(Trans2_mkdir);
7701 call_trans2mkdir(conn, req,
7702 &state->param, state->total_param,
7703 &state->data, state->total_data,
7704 state->max_data_return);
7705 END_PROFILE(Trans2_mkdir);
7709 case TRANSACT2_GET_DFS_REFERRAL:
7711 START_PROFILE(Trans2_get_dfs_referral);
7712 call_trans2getdfsreferral(conn, req,
7713 &state->param, state->total_param,
7714 &state->data, state->total_data,
7715 state->max_data_return);
7716 END_PROFILE(Trans2_get_dfs_referral);
7720 case TRANSACT2_IOCTL:
7722 START_PROFILE(Trans2_ioctl);
7723 call_trans2ioctl(conn, req,
7724 &state->param, state->total_param,
7725 &state->data, state->total_data,
7726 state->max_data_return);
7727 END_PROFILE(Trans2_ioctl);
7732 /* Error in request */
7733 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7734 reply_doserror(req, ERRSRV,ERRerror);
7738 /****************************************************************************
7739 Reply to a SMBtrans2.
7740 ****************************************************************************/
7742 void reply_trans2(struct smb_request *req)
7744 connection_struct *conn = req->conn;
7749 unsigned int tran_call;
7750 struct trans_state *state;
7753 START_PROFILE(SMBtrans2);
7755 if (req->wct < 14) {
7756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7757 END_PROFILE(SMBtrans2);
7761 dsoff = SVAL(req->vwv+12, 0);
7762 dscnt = SVAL(req->vwv+11, 0);
7763 psoff = SVAL(req->vwv+10, 0);
7764 pscnt = SVAL(req->vwv+9, 0);
7765 tran_call = SVAL(req->vwv+14, 0);
7767 result = allow_new_trans(conn->pending_trans, req->mid);
7768 if (!NT_STATUS_IS_OK(result)) {
7769 DEBUG(2, ("Got invalid trans2 request: %s\n",
7770 nt_errstr(result)));
7771 reply_nterror(req, result);
7772 END_PROFILE(SMBtrans2);
7777 switch (tran_call) {
7778 /* List the allowed trans2 calls on IPC$ */
7779 case TRANSACT2_OPEN:
7780 case TRANSACT2_GET_DFS_REFERRAL:
7781 case TRANSACT2_QFILEINFO:
7782 case TRANSACT2_QFSINFO:
7783 case TRANSACT2_SETFSINFO:
7786 reply_doserror(req, ERRSRV, ERRaccess);
7787 END_PROFILE(SMBtrans2);
7792 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7793 DEBUG(0, ("talloc failed\n"));
7794 reply_nterror(req, NT_STATUS_NO_MEMORY);
7795 END_PROFILE(SMBtrans2);
7799 state->cmd = SMBtrans2;
7801 state->mid = req->mid;
7802 state->vuid = req->vuid;
7803 state->setup_count = SVAL(req->vwv+13, 0);
7804 state->setup = NULL;
7805 state->total_param = SVAL(req->vwv+0, 0);
7806 state->param = NULL;
7807 state->total_data = SVAL(req->vwv+1, 0);
7809 state->max_param_return = SVAL(req->vwv+2, 0);
7810 state->max_data_return = SVAL(req->vwv+3, 0);
7811 state->max_setup_return = SVAL(req->vwv+4, 0);
7812 state->close_on_completion = BITSETW(req->vwv+5, 0);
7813 state->one_way = BITSETW(req->vwv+5, 1);
7815 state->call = tran_call;
7817 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7818 is so as a sanity check */
7819 if (state->setup_count != 1) {
7821 * Need to have rc=0 for ioctl to get job id for OS/2.
7822 * Network printing will fail if function is not successful.
7823 * Similar function in reply.c will be used if protocol
7824 * is LANMAN1.0 instead of LM1.2X002.
7825 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7826 * outbuf doesn't have to be set(only job id is used).
7828 if ( (state->setup_count == 4)
7829 && (tran_call == TRANSACT2_IOCTL)
7830 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7831 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7832 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7834 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7835 DEBUG(2,("Transaction is %d\n",tran_call));
7837 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7838 END_PROFILE(SMBtrans2);
7843 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7846 if (state->total_data) {
7848 if (trans_oob(state->total_data, 0, dscnt)
7849 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7853 /* Can't use talloc here, the core routines do realloc on the
7854 * params and data. */
7855 state->data = (char *)SMB_MALLOC(state->total_data);
7856 if (state->data == NULL) {
7857 DEBUG(0,("reply_trans2: data malloc fail for %u "
7858 "bytes !\n", (unsigned int)state->total_data));
7860 reply_nterror(req, NT_STATUS_NO_MEMORY);
7861 END_PROFILE(SMBtrans2);
7865 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7868 if (state->total_param) {
7870 if (trans_oob(state->total_param, 0, pscnt)
7871 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7875 /* Can't use talloc here, the core routines do realloc on the
7876 * params and data. */
7877 state->param = (char *)SMB_MALLOC(state->total_param);
7878 if (state->param == NULL) {
7879 DEBUG(0,("reply_trans: param malloc fail for %u "
7880 "bytes !\n", (unsigned int)state->total_param));
7881 SAFE_FREE(state->data);
7883 reply_nterror(req, NT_STATUS_NO_MEMORY);
7884 END_PROFILE(SMBtrans2);
7888 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7891 state->received_data = dscnt;
7892 state->received_param = pscnt;
7894 if ((state->received_param == state->total_param) &&
7895 (state->received_data == state->total_data)) {
7897 handle_trans2(conn, req, state);
7899 SAFE_FREE(state->data);
7900 SAFE_FREE(state->param);
7902 END_PROFILE(SMBtrans2);
7906 DLIST_ADD(conn->pending_trans, state);
7908 /* We need to send an interim response then receive the rest
7909 of the parameter/data bytes */
7910 reply_outbuf(req, 0, 0);
7911 show_msg((char *)req->outbuf);
7912 END_PROFILE(SMBtrans2);
7917 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7918 SAFE_FREE(state->data);
7919 SAFE_FREE(state->param);
7921 END_PROFILE(SMBtrans2);
7922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7926 /****************************************************************************
7927 Reply to a SMBtranss2
7928 ****************************************************************************/
7930 void reply_transs2(struct smb_request *req)
7932 connection_struct *conn = req->conn;
7933 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7934 struct trans_state *state;
7936 START_PROFILE(SMBtranss2);
7938 show_msg((char *)req->inbuf);
7941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7942 END_PROFILE(SMBtranss2);
7946 for (state = conn->pending_trans; state != NULL;
7947 state = state->next) {
7948 if (state->mid == req->mid) {
7953 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7955 END_PROFILE(SMBtranss2);
7959 /* Revise state->total_param and state->total_data in case they have
7960 changed downwards */
7962 if (SVAL(req->vwv+0, 0) < state->total_param)
7963 state->total_param = SVAL(req->vwv+0, 0);
7964 if (SVAL(req->vwv+1, 0) < state->total_data)
7965 state->total_data = SVAL(req->vwv+1, 0);
7967 pcnt = SVAL(req->vwv+2, 0);
7968 poff = SVAL(req->vwv+3, 0);
7969 pdisp = SVAL(req->vwv+4, 0);
7971 dcnt = SVAL(req->vwv+5, 0);
7972 doff = SVAL(req->vwv+6, 0);
7973 ddisp = SVAL(req->vwv+7, 0);
7975 state->received_param += pcnt;
7976 state->received_data += dcnt;
7978 if ((state->received_data > state->total_data) ||
7979 (state->received_param > state->total_param))
7983 if (trans_oob(state->total_param, pdisp, pcnt)
7984 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7987 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7991 if (trans_oob(state->total_data, ddisp, dcnt)
7992 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7995 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7998 if ((state->received_param < state->total_param) ||
7999 (state->received_data < state->total_data)) {
8000 END_PROFILE(SMBtranss2);
8004 handle_trans2(conn, req, state);
8006 DLIST_REMOVE(conn->pending_trans, state);
8007 SAFE_FREE(state->data);
8008 SAFE_FREE(state->param);
8011 END_PROFILE(SMBtranss2);
8016 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8017 DLIST_REMOVE(conn->pending_trans, state);
8018 SAFE_FREE(state->data);
8019 SAFE_FREE(state->param);
8021 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8022 END_PROFILE(SMBtranss2);