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 char *params = *pparams;
873 char *pdata = *ppdata;
878 bool return_additional_info;
889 SMB_STRUCT_STAT sbuf;
892 struct ea_list *ea_list = NULL;
897 uint32 create_disposition;
898 uint32 create_options = 0;
899 TALLOC_CTX *ctx = talloc_tos();
901 SET_STAT_INVALID(sbuf);
904 * Ensure we have enough parameters to perform the operation.
907 if (total_params < 29) {
908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
912 flags = SVAL(params, 0);
913 deny_mode = SVAL(params, 2);
914 open_attr = SVAL(params,6);
915 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
916 if (oplock_request) {
917 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
921 return_additional_info = BITSETW(params,0);
922 open_sattr = SVAL(params, 4);
923 open_time = make_unix_date3(params+8);
925 open_ofun = SVAL(params,12);
926 open_size = IVAL(params,14);
930 reply_doserror(req, ERRSRV, ERRaccess);
934 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
935 total_params - 28, STR_TERMINATE,
937 if (!NT_STATUS_IS_OK(status)) {
938 reply_nterror(req, status);
942 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
943 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
944 (unsigned int)open_ofun, open_size));
946 if (open_ofun == 0) {
947 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
951 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
956 reply_doserror(req, ERRDOS, ERRbadaccess);
960 /* Any data in this call is an EA list. */
961 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
962 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
966 if (total_data != 4) {
967 if (total_data < 10) {
968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
972 if (IVAL(pdata,0) > total_data) {
973 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
974 IVAL(pdata,0), (unsigned int)total_data));
975 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
979 ea_list = read_ea_list(talloc_tos(), pdata + 4,
982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
985 } else if (IVAL(pdata,0) != 4) {
986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
990 status = SMB_VFS_CREATE_FILE(
993 0, /* root_dir_fid */
995 CFF_DOS_PATH, /* create_file_flags */
996 access_mask, /* access_mask */
997 share_mode, /* share_access */
998 create_disposition, /* create_disposition*/
999 create_options, /* create_options */
1000 open_attr, /* file_attributes */
1001 oplock_request, /* oplock_request */
1002 open_size, /* allocation_size */
1004 ea_list, /* ea_list */
1006 &smb_action, /* pinfo */
1009 if (!NT_STATUS_IS_OK(status)) {
1010 if (open_was_deferred(req->mid)) {
1011 /* We have re-scheduled this call. */
1014 reply_openerror(req, status);
1018 size = get_file_size_stat(&sbuf);
1019 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1020 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1021 inode = sbuf.st_ex_ino;
1023 close_file(req, fsp, ERROR_CLOSE);
1024 reply_doserror(req, ERRDOS,ERRnoaccess);
1028 /* Realloc the size of parameters and data we will return */
1029 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1030 if(*pparams == NULL ) {
1031 reply_nterror(req, NT_STATUS_NO_MEMORY);
1036 SSVAL(params,0,fsp->fnum);
1037 SSVAL(params,2,fattr);
1038 srv_put_dos_date2(params,4, mtime);
1039 SIVAL(params,8, (uint32)size);
1040 SSVAL(params,12,deny_mode);
1041 SSVAL(params,14,0); /* open_type - file or directory. */
1042 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1044 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1045 smb_action |= EXTENDED_OPLOCK_GRANTED;
1048 SSVAL(params,18,smb_action);
1051 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1053 SIVAL(params,20,inode);
1054 SSVAL(params,24,0); /* Padding. */
1056 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1057 SIVAL(params, 26, ea_size);
1059 SIVAL(params, 26, 0);
1062 /* Send the required number of replies */
1063 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1066 /*********************************************************
1067 Routine to check if a given string matches exactly.
1068 as a special case a mask of "." does NOT match. That
1069 is required for correct wildcard semantics
1070 Case can be significant or not.
1071 **********************************************************/
1073 static bool exact_match(connection_struct *conn,
1077 if (mask[0] == '.' && mask[1] == 0)
1079 if (dptr_has_wild(conn->dirptr)) {
1082 if (conn->case_sensitive)
1083 return strcmp(str,mask)==0;
1085 return StrCaseCmp(str,mask) == 0;
1088 /****************************************************************************
1089 Return the filetype for UNIX extensions.
1090 ****************************************************************************/
1092 static uint32 unix_filetype(mode_t mode)
1095 return UNIX_TYPE_FILE;
1096 else if(S_ISDIR(mode))
1097 return UNIX_TYPE_DIR;
1099 else if(S_ISLNK(mode))
1100 return UNIX_TYPE_SYMLINK;
1103 else if(S_ISCHR(mode))
1104 return UNIX_TYPE_CHARDEV;
1107 else if(S_ISBLK(mode))
1108 return UNIX_TYPE_BLKDEV;
1111 else if(S_ISFIFO(mode))
1112 return UNIX_TYPE_FIFO;
1115 else if(S_ISSOCK(mode))
1116 return UNIX_TYPE_SOCKET;
1119 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1120 return UNIX_TYPE_UNKNOWN;
1123 /****************************************************************************
1124 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1125 ****************************************************************************/
1127 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1129 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1130 SMB_STRUCT_STAT *psbuf,
1132 enum perm_type ptype,
1137 if (perms == SMB_MODE_NO_CHANGE) {
1138 if (!VALID_STAT(*psbuf)) {
1139 return NT_STATUS_INVALID_PARAMETER;
1141 *ret_perms = psbuf->st_ex_mode;
1142 return NT_STATUS_OK;
1146 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1147 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1148 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1149 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1150 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1151 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1152 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1153 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1154 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1156 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1159 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1162 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1167 /* Apply mode mask */
1168 ret &= lp_create_mask(SNUM(conn));
1169 /* Add in force bits */
1170 ret |= lp_force_create_mode(SNUM(conn));
1173 ret &= lp_dir_mask(SNUM(conn));
1174 /* Add in force bits */
1175 ret |= lp_force_dir_mode(SNUM(conn));
1177 case PERM_EXISTING_FILE:
1178 /* Apply mode mask */
1179 ret &= lp_security_mask(SNUM(conn));
1180 /* Add in force bits */
1181 ret |= lp_force_security_mode(SNUM(conn));
1183 case PERM_EXISTING_DIR:
1184 /* Apply mode mask */
1185 ret &= lp_dir_security_mask(SNUM(conn));
1186 /* Add in force bits */
1187 ret |= lp_force_dir_security_mode(SNUM(conn));
1192 return NT_STATUS_OK;
1195 /****************************************************************************
1196 Needed to show the msdfs symlinks as directories. Modifies psbuf
1197 to be a directory if it's a msdfs link.
1198 ****************************************************************************/
1200 static bool check_msdfs_link(connection_struct *conn,
1201 const char *pathname,
1202 SMB_STRUCT_STAT *psbuf)
1204 int saved_errno = errno;
1205 if(lp_host_msdfs() &&
1206 lp_msdfs_root(SNUM(conn)) &&
1207 is_msdfs_link(conn, pathname, psbuf)) {
1209 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1212 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1213 errno = saved_errno;
1216 errno = saved_errno;
1221 /****************************************************************************
1222 Get a level dependent lanman2 dir entry.
1223 ****************************************************************************/
1225 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1226 connection_struct *conn,
1228 const char *path_mask,
1231 int requires_resume_key,
1237 int space_remaining,
1239 bool *got_exact_match,
1240 int *last_entry_off,
1241 struct ea_list *name_list)
1245 SMB_STRUCT_STAT sbuf;
1246 const char *mask = NULL;
1247 char *pathreal = NULL;
1249 char *p, *q, *pdata = *ppdata;
1253 SMB_OFF_T file_size = 0;
1254 uint64_t allocation_size = 0;
1256 struct timespec mdate_ts, adate_ts, create_date_ts;
1257 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1259 char *last_entry_ptr;
1261 uint32 nt_extmode; /* Used for NT connections instead of mode */
1262 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1263 bool check_mangled_names = lp_manglednames(conn->params);
1264 char mangled_name[13]; /* mangled 8.3 name. */
1266 *out_of_space = False;
1267 *got_exact_match = False;
1269 ZERO_STRUCT(mdate_ts);
1270 ZERO_STRUCT(adate_ts);
1271 ZERO_STRUCT(create_date_ts);
1273 if (!conn->dirptr) {
1277 p = strrchr_m(path_mask,'/');
1280 mask = talloc_strdup(ctx,"*.*");
1290 bool ms_dfs_link = False;
1292 /* Needed if we run out of space */
1293 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1294 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1297 * Due to bugs in NT client redirectors we are not using
1298 * resume keys any more - set them to zero.
1299 * Check out the related comments in findfirst/findnext.
1305 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1306 (long)conn->dirptr,curr_dirpos));
1313 * fname may get mangled, dname is never mangled.
1314 * Whenever we're accessing the filesystem we use
1315 * pathreal which is composed from dname.
1321 /* Mangle fname if it's an illegal name. */
1322 if (mangle_must_mangle(dname,conn->params)) {
1323 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1325 continue; /* Error - couldn't mangle. */
1327 fname = talloc_strdup(ctx, mangled_name);
1333 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1334 got_match = mask_match(fname, mask, conn->case_sensitive);
1337 if(!got_match && check_mangled_names &&
1338 !mangle_is_8_3(fname, False, conn->params)) {
1340 * It turns out that NT matches wildcards against
1341 * both long *and* short names. This may explain some
1342 * of the wildcard wierdness from old DOS clients
1343 * that some people have been seeing.... JRA.
1345 /* Force the mangling into 8.3. */
1346 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1348 continue; /* Error - couldn't mangle. */
1351 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1352 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1357 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1359 if (dont_descend && !isdots) {
1366 pathreal = talloc_asprintf(ctx,
1371 pathreal = talloc_asprintf(ctx,
1382 if (INFO_LEVEL_IS_UNIX(info_level)) {
1383 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1384 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1385 pathreal,strerror(errno)));
1386 TALLOC_FREE(pathreal);
1390 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1391 /* Needed to show the msdfs symlinks as
1394 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1396 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1397 pathreal,strerror(errno)));
1398 TALLOC_FREE(pathreal);
1405 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1407 mode = dos_mode(conn,pathreal,&sbuf);
1410 if (!dir_check_ftype(conn,mode,dirtype)) {
1411 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1412 TALLOC_FREE(pathreal);
1417 if (!(mode & aDIR)) {
1418 file_size = get_file_size_stat(&sbuf);
1420 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1422 mdate_ts = sbuf.st_ex_mtime;
1423 adate_ts = sbuf.st_ex_atime;
1424 create_date_ts = sbuf.st_ex_btime;
1426 if (ask_sharemode) {
1427 struct timespec write_time_ts;
1428 struct file_id fileid;
1430 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1431 get_file_infos(fileid, NULL, &write_time_ts);
1432 if (!null_timespec(write_time_ts)) {
1433 mdate_ts = write_time_ts;
1437 if (lp_dos_filetime_resolution(SNUM(conn))) {
1438 dos_filetime_timespec(&create_date_ts);
1439 dos_filetime_timespec(&mdate_ts);
1440 dos_filetime_timespec(&adate_ts);
1443 create_date = convert_timespec_to_time_t(create_date_ts);
1444 mdate = convert_timespec_to_time_t(mdate_ts);
1445 adate = convert_timespec_to_time_t(adate_ts);
1447 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1452 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1462 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1464 switch (info_level) {
1465 case SMB_FIND_INFO_STANDARD:
1466 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1467 if(requires_resume_key) {
1471 srv_put_dos_date2(p,0,create_date);
1472 srv_put_dos_date2(p,4,adate);
1473 srv_put_dos_date2(p,8,mdate);
1474 SIVAL(p,12,(uint32)file_size);
1475 SIVAL(p,16,(uint32)allocation_size);
1479 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1480 p += ucs2_align(base_data, p, 0);
1482 len = srvstr_push(base_data, flags2, p,
1483 fname, PTR_DIFF(end_data, p),
1485 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1487 SCVAL(nameptr, -1, len - 2);
1489 SCVAL(nameptr, -1, 0);
1493 SCVAL(nameptr, -1, len - 1);
1495 SCVAL(nameptr, -1, 0);
1501 case SMB_FIND_EA_SIZE:
1502 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1503 if(requires_resume_key) {
1507 srv_put_dos_date2(p,0,create_date);
1508 srv_put_dos_date2(p,4,adate);
1509 srv_put_dos_date2(p,8,mdate);
1510 SIVAL(p,12,(uint32)file_size);
1511 SIVAL(p,16,(uint32)allocation_size);
1514 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1515 SIVAL(p,22,ea_size); /* Extended attributes */
1519 len = srvstr_push(base_data, flags2,
1520 p, fname, PTR_DIFF(end_data, p),
1521 STR_TERMINATE | STR_NOALIGN);
1522 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1535 SCVAL(nameptr,0,len);
1537 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1540 case SMB_FIND_EA_LIST:
1542 struct ea_list *file_list = NULL;
1545 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1549 if(requires_resume_key) {
1553 srv_put_dos_date2(p,0,create_date);
1554 srv_put_dos_date2(p,4,adate);
1555 srv_put_dos_date2(p,8,mdate);
1556 SIVAL(p,12,(uint32)file_size);
1557 SIVAL(p,16,(uint32)allocation_size);
1559 p += 22; /* p now points to the EA area. */
1561 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1562 name_list = ea_list_union(name_list, file_list, &ea_len);
1564 /* We need to determine if this entry will fit in the space available. */
1565 /* Max string size is 255 bytes. */
1566 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1567 /* Move the dirptr back to prev_dirpos */
1568 dptr_SeekDir(conn->dirptr, prev_dirpos);
1569 *out_of_space = True;
1570 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1571 return False; /* Not finished - just out of space */
1574 /* Push the ea_data followed by the name. */
1575 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1577 len = srvstr_push(base_data, flags2,
1578 p + 1, fname, PTR_DIFF(end_data, p+1),
1579 STR_TERMINATE | STR_NOALIGN);
1580 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1593 SCVAL(nameptr,0,len);
1595 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1599 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1600 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1601 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1603 SIVAL(p,0,reskey); p += 4;
1604 put_long_date_timespec(p,create_date_ts); p += 8;
1605 put_long_date_timespec(p,adate_ts); p += 8;
1606 put_long_date_timespec(p,mdate_ts); p += 8;
1607 put_long_date_timespec(p,mdate_ts); p += 8;
1608 SOFF_T(p,0,file_size); p += 8;
1609 SOFF_T(p,0,allocation_size); p += 8;
1610 SIVAL(p,0,nt_extmode); p += 4;
1611 q = p; p += 4; /* q is placeholder for name length. */
1613 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1614 SIVAL(p,0,ea_size); /* Extended attributes */
1617 /* Clear the short name buffer. This is
1618 * IMPORTANT as not doing so will trigger
1619 * a Win2k client bug. JRA.
1621 if (!was_8_3 && check_mangled_names) {
1622 if (!name_to_8_3(fname,mangled_name,True,
1624 /* Error - mangle failed ! */
1625 memset(mangled_name,'\0',12);
1627 mangled_name[12] = 0;
1628 len = srvstr_push(base_data, flags2,
1629 p+2, mangled_name, 24,
1630 STR_UPPER|STR_UNICODE);
1632 memset(p + 2 + len,'\0',24 - len);
1639 len = srvstr_push(base_data, flags2, p,
1640 fname, PTR_DIFF(end_data, p),
1641 STR_TERMINATE_ASCII);
1644 SIVAL(p,0,0); /* Ensure any padding is null. */
1645 len = PTR_DIFF(p, pdata);
1646 len = (len + 3) & ~3;
1651 case SMB_FIND_FILE_DIRECTORY_INFO:
1652 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1654 SIVAL(p,0,reskey); p += 4;
1655 put_long_date_timespec(p,create_date_ts); p += 8;
1656 put_long_date_timespec(p,adate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 put_long_date_timespec(p,mdate_ts); p += 8;
1659 SOFF_T(p,0,file_size); p += 8;
1660 SOFF_T(p,0,allocation_size); p += 8;
1661 SIVAL(p,0,nt_extmode); p += 4;
1662 len = srvstr_push(base_data, flags2,
1663 p + 4, fname, PTR_DIFF(end_data, p+4),
1664 STR_TERMINATE_ASCII);
1667 SIVAL(p,0,0); /* Ensure any padding is null. */
1668 len = PTR_DIFF(p, pdata);
1669 len = (len + 3) & ~3;
1674 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1675 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1677 SIVAL(p,0,reskey); p += 4;
1678 put_long_date_timespec(p,create_date_ts); p += 8;
1679 put_long_date_timespec(p,adate_ts); p += 8;
1680 put_long_date_timespec(p,mdate_ts); p += 8;
1681 put_long_date_timespec(p,mdate_ts); p += 8;
1682 SOFF_T(p,0,file_size); p += 8;
1683 SOFF_T(p,0,allocation_size); p += 8;
1684 SIVAL(p,0,nt_extmode); p += 4;
1685 q = p; p += 4; /* q is placeholder for name length. */
1687 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1688 SIVAL(p,0,ea_size); /* Extended attributes */
1691 len = srvstr_push(base_data, flags2, p,
1692 fname, PTR_DIFF(end_data, p),
1693 STR_TERMINATE_ASCII);
1697 SIVAL(p,0,0); /* Ensure any padding is null. */
1698 len = PTR_DIFF(p, pdata);
1699 len = (len + 3) & ~3;
1704 case SMB_FIND_FILE_NAMES_INFO:
1705 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1707 SIVAL(p,0,reskey); p += 4;
1709 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1710 acl on a dir (tridge) */
1711 len = srvstr_push(base_data, flags2, p,
1712 fname, PTR_DIFF(end_data, p),
1713 STR_TERMINATE_ASCII);
1716 SIVAL(p,0,0); /* Ensure any padding is null. */
1717 len = PTR_DIFF(p, pdata);
1718 len = (len + 3) & ~3;
1723 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1724 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1726 SIVAL(p,0,reskey); p += 4;
1727 put_long_date_timespec(p,create_date_ts); p += 8;
1728 put_long_date_timespec(p,adate_ts); p += 8;
1729 put_long_date_timespec(p,mdate_ts); p += 8;
1730 put_long_date_timespec(p,mdate_ts); p += 8;
1731 SOFF_T(p,0,file_size); p += 8;
1732 SOFF_T(p,0,allocation_size); p += 8;
1733 SIVAL(p,0,nt_extmode); p += 4;
1734 q = p; p += 4; /* q is placeholder for name length. */
1736 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1737 SIVAL(p,0,ea_size); /* Extended attributes */
1740 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1741 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1742 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1743 len = srvstr_push(base_data, flags2, p,
1744 fname, PTR_DIFF(end_data, p),
1745 STR_TERMINATE_ASCII);
1748 SIVAL(p,0,0); /* Ensure any padding is null. */
1749 len = PTR_DIFF(p, pdata);
1750 len = (len + 3) & ~3;
1755 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1756 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1757 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1759 SIVAL(p,0,reskey); p += 4;
1760 put_long_date_timespec(p,create_date_ts); p += 8;
1761 put_long_date_timespec(p,adate_ts); p += 8;
1762 put_long_date_timespec(p,mdate_ts); p += 8;
1763 put_long_date_timespec(p,mdate_ts); p += 8;
1764 SOFF_T(p,0,file_size); p += 8;
1765 SOFF_T(p,0,allocation_size); p += 8;
1766 SIVAL(p,0,nt_extmode); p += 4;
1767 q = p; p += 4; /* q is placeholder for name length */
1769 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1770 SIVAL(p,0,ea_size); /* Extended attributes */
1773 /* Clear the short name buffer. This is
1774 * IMPORTANT as not doing so will trigger
1775 * a Win2k client bug. JRA.
1777 if (!was_8_3 && check_mangled_names) {
1778 if (!name_to_8_3(fname,mangled_name,True,
1780 /* Error - mangle failed ! */
1781 memset(mangled_name,'\0',12);
1783 mangled_name[12] = 0;
1784 len = srvstr_push(base_data, flags2,
1785 p+2, mangled_name, 24,
1786 STR_UPPER|STR_UNICODE);
1789 memset(p + 2 + len,'\0',24 - len);
1796 SSVAL(p,0,0); p += 2; /* Reserved ? */
1797 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1798 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1799 len = srvstr_push(base_data, flags2, p,
1800 fname, PTR_DIFF(end_data, p),
1801 STR_TERMINATE_ASCII);
1804 SIVAL(p,0,0); /* Ensure any padding is null. */
1805 len = PTR_DIFF(p, pdata);
1806 len = (len + 3) & ~3;
1811 /* CIFS UNIX Extension. */
1813 case SMB_FIND_FILE_UNIX:
1814 case SMB_FIND_FILE_UNIX_INFO2:
1816 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1818 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1820 if (info_level == SMB_FIND_FILE_UNIX) {
1821 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1822 p = store_file_unix_basic(conn, p,
1824 len = srvstr_push(base_data, flags2, p,
1825 fname, PTR_DIFF(end_data, p),
1828 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1829 p = store_file_unix_basic_info2(conn, p,
1833 len = srvstr_push(base_data, flags2, p, fname,
1834 PTR_DIFF(end_data, p), 0);
1835 SIVAL(nameptr, 0, len);
1839 SIVAL(p,0,0); /* Ensure any padding is null. */
1841 len = PTR_DIFF(p, pdata);
1842 len = (len + 3) & ~3;
1843 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1845 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1855 if (PTR_DIFF(p,pdata) > space_remaining) {
1856 /* Move the dirptr back to prev_dirpos */
1857 dptr_SeekDir(conn->dirptr, prev_dirpos);
1858 *out_of_space = True;
1859 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1860 return False; /* Not finished - just out of space */
1863 /* Setup the last entry pointer, as an offset from base_data */
1864 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1865 /* Advance the data pointer to the next slot */
1871 /****************************************************************************
1872 Reply to a TRANS2_FINDFIRST.
1873 ****************************************************************************/
1875 static void call_trans2findfirst(connection_struct *conn,
1876 struct smb_request *req,
1877 char **pparams, int total_params,
1878 char **ppdata, int total_data,
1879 unsigned int max_data_bytes)
1881 /* We must be careful here that we don't return more than the
1882 allowed number of data bytes. If this means returning fewer than
1883 maxentries then so be it. We assume that the redirector has
1884 enough room for the fixed number of parameter bytes it has
1886 struct smb_filename *smb_dname = NULL;
1887 char *params = *pparams;
1888 char *pdata = *ppdata;
1892 uint16 findfirst_flags;
1893 bool close_after_first;
1895 bool requires_resume_key;
1897 char *directory = NULL;
1900 int last_entry_off=0;
1904 bool finished = False;
1905 bool dont_descend = False;
1906 bool out_of_space = False;
1907 int space_remaining;
1908 bool mask_contains_wcard = False;
1909 struct ea_list *ea_list = NULL;
1910 NTSTATUS ntstatus = NT_STATUS_OK;
1911 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1912 TALLOC_CTX *ctx = talloc_tos();
1914 if (total_params < 13) {
1915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1919 dirtype = SVAL(params,0);
1920 maxentries = SVAL(params,2);
1921 findfirst_flags = SVAL(params,4);
1922 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1923 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1924 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1925 info_level = SVAL(params,6);
1927 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1928 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1929 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1930 info_level, max_data_bytes));
1933 /* W2K3 seems to treat zero as 1. */
1937 switch (info_level) {
1938 case SMB_FIND_INFO_STANDARD:
1939 case SMB_FIND_EA_SIZE:
1940 case SMB_FIND_EA_LIST:
1941 case SMB_FIND_FILE_DIRECTORY_INFO:
1942 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1943 case SMB_FIND_FILE_NAMES_INFO:
1944 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1945 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1946 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1948 case SMB_FIND_FILE_UNIX:
1949 case SMB_FIND_FILE_UNIX_INFO2:
1950 /* Always use filesystem for UNIX mtime query. */
1951 ask_sharemode = false;
1952 if (!lp_unix_extensions()) {
1953 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1958 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1962 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1963 params+12, total_params - 12,
1964 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1965 if (!NT_STATUS_IS_OK(ntstatus)) {
1966 reply_nterror(req, ntstatus);
1970 ntstatus = resolve_dfspath_wcard(ctx, conn,
1971 req->flags2 & FLAGS2_DFS_PATHNAMES,
1974 &mask_contains_wcard);
1975 if (!NT_STATUS_IS_OK(ntstatus)) {
1976 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1977 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1978 ERRSRV, ERRbadpath);
1981 reply_nterror(req, ntstatus);
1985 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
1986 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
1987 if (!NT_STATUS_IS_OK(ntstatus)) {
1988 reply_nterror(req, ntstatus);
1992 mask = smb_dname->original_lcomp;
1994 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
1995 TALLOC_FREE(smb_dname);
1996 if (!NT_STATUS_IS_OK(ntstatus)) {
1997 reply_nterror(req, ntstatus);
2001 ntstatus = check_name(conn, directory);
2002 if (!NT_STATUS_IS_OK(ntstatus)) {
2003 reply_nterror(req, ntstatus);
2007 p = strrchr_m(directory,'/');
2009 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2010 if((directory[0] == '.') && (directory[1] == '\0')) {
2011 mask = talloc_strdup(ctx,"*");
2013 reply_nterror(req, NT_STATUS_NO_MEMORY);
2016 mask_contains_wcard = True;
2018 directory = talloc_strdup(talloc_tos(), "./");
2020 reply_nterror(req, NT_STATUS_NO_MEMORY);
2027 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2029 if (info_level == SMB_FIND_EA_LIST) {
2032 if (total_data < 4) {
2033 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2037 ea_size = IVAL(pdata,0);
2038 if (ea_size != total_data) {
2039 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2040 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2045 if (!lp_ea_support(SNUM(conn))) {
2046 reply_doserror(req, ERRDOS, ERReasnotsupported);
2050 /* Pull out the list of names. */
2051 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2058 *ppdata = (char *)SMB_REALLOC(
2059 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2060 if(*ppdata == NULL ) {
2061 reply_nterror(req, NT_STATUS_NO_MEMORY);
2065 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2067 /* Realloc the params space */
2068 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2069 if (*pparams == NULL) {
2070 reply_nterror(req, NT_STATUS_NO_MEMORY);
2075 /* Save the wildcard match and attribs we are using on this directory -
2076 needed as lanman2 assumes these are being saved between calls */
2078 ntstatus = dptr_create(conn,
2084 mask_contains_wcard,
2088 if (!NT_STATUS_IS_OK(ntstatus)) {
2089 reply_nterror(req, ntstatus);
2093 dptr_num = dptr_dnum(conn->dirptr);
2094 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2096 /* Initialize per TRANS2_FIND_FIRST operation data */
2097 dptr_init_search_op(conn->dirptr);
2099 /* We don't need to check for VOL here as this is returned by
2100 a different TRANS2 call. */
2102 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2103 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2104 dont_descend = True;
2107 space_remaining = max_data_bytes;
2108 out_of_space = False;
2110 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2111 bool got_exact_match = False;
2113 /* this is a heuristic to avoid seeking the dirptr except when
2114 absolutely necessary. It allows for a filename of about 40 chars */
2115 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2116 out_of_space = True;
2119 finished = !get_lanman2_dir_entry(ctx,
2122 mask,dirtype,info_level,
2123 requires_resume_key,dont_descend,
2126 space_remaining, &out_of_space,
2128 &last_entry_off, ea_list);
2131 if (finished && out_of_space)
2134 if (!finished && !out_of_space)
2138 * As an optimisation if we know we aren't looking
2139 * for a wildcard name (ie. the name matches the wildcard exactly)
2140 * then we can finish on any (first) match.
2141 * This speeds up large directory searches. JRA.
2147 /* Ensure space_remaining never goes -ve. */
2148 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2149 space_remaining = 0;
2150 out_of_space = true;
2152 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2156 /* Check if we can close the dirptr */
2157 if(close_after_first || (finished && close_if_end)) {
2158 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2159 dptr_close(&dptr_num);
2163 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2164 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2165 * the protocol level is less than NT1. Tested with smbclient. JRA.
2166 * This should fix the OS/2 client bug #2335.
2169 if(numentries == 0) {
2170 dptr_close(&dptr_num);
2171 if (Protocol < PROTOCOL_NT1) {
2172 reply_doserror(req, ERRDOS, ERRnofiles);
2175 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2176 ERRDOS, ERRbadfile);
2181 /* At this point pdata points to numentries directory entries. */
2183 /* Set up the return parameter block */
2184 SSVAL(params,0,dptr_num);
2185 SSVAL(params,2,numentries);
2186 SSVAL(params,4,finished);
2187 SSVAL(params,6,0); /* Never an EA error */
2188 SSVAL(params,8,last_entry_off);
2190 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2193 if ((! *directory) && dptr_path(dptr_num)) {
2194 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2196 reply_nterror(req, NT_STATUS_NO_MEMORY);
2200 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2201 smb_fn_name(req->cmd),
2202 mask, directory, dirtype, numentries ) );
2205 * Force a name mangle here to ensure that the
2206 * mask as an 8.3 name is top of the mangled cache.
2207 * The reasons for this are subtle. Don't remove
2208 * this code unless you know what you are doing
2209 * (see PR#13758). JRA.
2212 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2213 char mangled_name[13];
2214 name_to_8_3(mask, mangled_name, True, conn->params);
2220 /****************************************************************************
2221 Reply to a TRANS2_FINDNEXT.
2222 ****************************************************************************/
2224 static void call_trans2findnext(connection_struct *conn,
2225 struct smb_request *req,
2226 char **pparams, int total_params,
2227 char **ppdata, int total_data,
2228 unsigned int max_data_bytes)
2230 /* We must be careful here that we don't return more than the
2231 allowed number of data bytes. If this means returning fewer than
2232 maxentries then so be it. We assume that the redirector has
2233 enough room for the fixed number of parameter bytes it has
2235 char *params = *pparams;
2236 char *pdata = *ppdata;
2242 uint16 findnext_flags;
2243 bool close_after_request;
2245 bool requires_resume_key;
2247 bool mask_contains_wcard = False;
2248 char *resume_name = NULL;
2249 const char *mask = NULL;
2250 const char *directory = NULL;
2254 int i, last_entry_off=0;
2255 bool finished = False;
2256 bool dont_descend = False;
2257 bool out_of_space = False;
2258 int space_remaining;
2259 struct ea_list *ea_list = NULL;
2260 NTSTATUS ntstatus = NT_STATUS_OK;
2261 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2262 TALLOC_CTX *ctx = talloc_tos();
2264 if (total_params < 13) {
2265 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2269 dptr_num = SVAL(params,0);
2270 maxentries = SVAL(params,2);
2271 info_level = SVAL(params,4);
2272 resume_key = IVAL(params,6);
2273 findnext_flags = SVAL(params,10);
2274 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2275 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2276 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2277 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2279 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2281 total_params - 12, STR_TERMINATE, &ntstatus,
2282 &mask_contains_wcard);
2283 if (!NT_STATUS_IS_OK(ntstatus)) {
2284 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2285 complain (it thinks we're asking for the directory above the shared
2286 path or an invalid name). Catch this as the resume name is only compared, never used in
2287 a file access. JRA. */
2288 srvstr_pull_talloc(ctx, params, req->flags2,
2289 &resume_name, params+12,
2293 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2294 reply_nterror(req, ntstatus);
2299 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2300 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2301 resume_key = %d resume name = %s continue=%d level = %d\n",
2302 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2303 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2306 /* W2K3 seems to treat zero as 1. */
2310 switch (info_level) {
2311 case SMB_FIND_INFO_STANDARD:
2312 case SMB_FIND_EA_SIZE:
2313 case SMB_FIND_EA_LIST:
2314 case SMB_FIND_FILE_DIRECTORY_INFO:
2315 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2316 case SMB_FIND_FILE_NAMES_INFO:
2317 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2318 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2319 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2321 case SMB_FIND_FILE_UNIX:
2322 case SMB_FIND_FILE_UNIX_INFO2:
2323 /* Always use filesystem for UNIX mtime query. */
2324 ask_sharemode = false;
2325 if (!lp_unix_extensions()) {
2326 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2331 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2335 if (info_level == SMB_FIND_EA_LIST) {
2338 if (total_data < 4) {
2339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2343 ea_size = IVAL(pdata,0);
2344 if (ea_size != total_data) {
2345 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2346 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2351 if (!lp_ea_support(SNUM(conn))) {
2352 reply_doserror(req, ERRDOS, ERReasnotsupported);
2356 /* Pull out the list of names. */
2357 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2359 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2364 *ppdata = (char *)SMB_REALLOC(
2365 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2366 if(*ppdata == NULL) {
2367 reply_nterror(req, NT_STATUS_NO_MEMORY);
2372 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2374 /* Realloc the params space */
2375 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2376 if(*pparams == NULL ) {
2377 reply_nterror(req, NT_STATUS_NO_MEMORY);
2383 /* Check that the dptr is valid */
2384 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2385 reply_doserror(req, ERRDOS, ERRnofiles);
2389 string_set(&conn->dirpath,dptr_path(dptr_num));
2391 /* Get the wildcard mask from the dptr */
2392 if((p = dptr_wcard(dptr_num))== NULL) {
2393 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2394 reply_doserror(req, ERRDOS, ERRnofiles);
2399 directory = conn->dirpath;
2401 /* Get the attr mask from the dptr */
2402 dirtype = dptr_attr(dptr_num);
2404 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2405 dptr_num, mask, dirtype,
2407 dptr_TellDir(conn->dirptr)));
2409 /* Initialize per TRANS2_FIND_NEXT operation data */
2410 dptr_init_search_op(conn->dirptr);
2412 /* We don't need to check for VOL here as this is returned by
2413 a different TRANS2 call. */
2415 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2416 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2417 dont_descend = True;
2420 space_remaining = max_data_bytes;
2421 out_of_space = False;
2424 * Seek to the correct position. We no longer use the resume key but
2425 * depend on the last file name instead.
2428 if(*resume_name && !continue_bit) {
2431 long current_pos = 0;
2433 * Remember, name_to_8_3 is called by
2434 * get_lanman2_dir_entry(), so the resume name
2435 * could be mangled. Ensure we check the unmangled name.
2438 if (mangle_is_mangled(resume_name, conn->params)) {
2439 char *new_resume_name = NULL;
2440 mangle_lookup_name_from_8_3(ctx,
2444 if (new_resume_name) {
2445 resume_name = new_resume_name;
2450 * Fix for NT redirector problem triggered by resume key indexes
2451 * changing between directory scans. We now return a resume key of 0
2452 * and instead look for the filename to continue from (also given
2453 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2454 * findfirst/findnext (as is usual) then the directory pointer
2455 * should already be at the correct place.
2458 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2459 } /* end if resume_name && !continue_bit */
2461 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2462 bool got_exact_match = False;
2464 /* this is a heuristic to avoid seeking the dirptr except when
2465 absolutely necessary. It allows for a filename of about 40 chars */
2466 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2467 out_of_space = True;
2470 finished = !get_lanman2_dir_entry(ctx,
2473 mask,dirtype,info_level,
2474 requires_resume_key,dont_descend,
2477 space_remaining, &out_of_space,
2479 &last_entry_off, ea_list);
2482 if (finished && out_of_space)
2485 if (!finished && !out_of_space)
2489 * As an optimisation if we know we aren't looking
2490 * for a wildcard name (ie. the name matches the wildcard exactly)
2491 * then we can finish on any (first) match.
2492 * This speeds up large directory searches. JRA.
2498 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2501 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2502 smb_fn_name(req->cmd),
2503 mask, directory, dirtype, numentries ) );
2505 /* Check if we can close the dirptr */
2506 if(close_after_request || (finished && close_if_end)) {
2507 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2508 dptr_close(&dptr_num); /* This frees up the saved mask */
2511 /* Set up the return parameter block */
2512 SSVAL(params,0,numentries);
2513 SSVAL(params,2,finished);
2514 SSVAL(params,4,0); /* Never an EA error */
2515 SSVAL(params,6,last_entry_off);
2517 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2523 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2525 E_md4hash(lp_servicename(SNUM(conn)),objid);
2529 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2531 SMB_ASSERT(extended_info != NULL);
2533 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2534 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2535 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2536 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2537 #ifdef SAMBA_VERSION_REVISION
2538 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2540 extended_info->samba_subversion = 0;
2541 #ifdef SAMBA_VERSION_RC_RELEASE
2542 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2544 #ifdef SAMBA_VERSION_PRE_RELEASE
2545 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2548 #ifdef SAMBA_VERSION_VENDOR_PATCH
2549 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2551 extended_info->samba_gitcommitdate = 0;
2552 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2553 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2556 memset(extended_info->samba_version_string, 0,
2557 sizeof(extended_info->samba_version_string));
2559 snprintf (extended_info->samba_version_string,
2560 sizeof(extended_info->samba_version_string),
2561 "%s", samba_version_string());
2564 /****************************************************************************
2565 Reply to a TRANS2_QFSINFO (query filesystem info).
2566 ****************************************************************************/
2568 static void call_trans2qfsinfo(connection_struct *conn,
2569 struct smb_request *req,
2570 char **pparams, int total_params,
2571 char **ppdata, int total_data,
2572 unsigned int max_data_bytes)
2574 char *pdata, *end_data;
2575 char *params = *pparams;
2579 const char *vname = volume_label(SNUM(conn));
2580 int snum = SNUM(conn);
2581 char *fstype = lp_fstype(SNUM(conn));
2582 uint32 additional_flags = 0;
2584 if (total_params < 2) {
2585 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2589 info_level = SVAL(params,0);
2592 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2593 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2594 "info level (0x%x) on IPC$.\n",
2595 (unsigned int)info_level));
2596 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2601 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2602 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2603 DEBUG(0,("call_trans2qfsinfo: encryption required "
2604 "and info level 0x%x sent.\n",
2605 (unsigned int)info_level));
2606 exit_server_cleanly("encryption required "
2612 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2614 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2615 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2616 reply_doserror(req, ERRSRV, ERRinvdevice);
2620 *ppdata = (char *)SMB_REALLOC(
2621 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2622 if (*ppdata == NULL ) {
2623 reply_nterror(req, NT_STATUS_NO_MEMORY);
2628 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2629 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2631 switch (info_level) {
2632 case SMB_INFO_ALLOCATION:
2634 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2636 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2637 reply_unixerror(req, ERRHRD, ERRgeneral);
2641 block_size = lp_block_size(snum);
2642 if (bsize < block_size) {
2643 uint64_t factor = block_size/bsize;
2648 if (bsize > block_size) {
2649 uint64_t factor = bsize/block_size;
2654 bytes_per_sector = 512;
2655 sectors_per_unit = bsize/bytes_per_sector;
2657 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2658 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2659 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2661 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2662 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2663 SIVAL(pdata,l1_cUnit,dsize);
2664 SIVAL(pdata,l1_cUnitAvail,dfree);
2665 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2669 case SMB_INFO_VOLUME:
2670 /* Return volume name */
2672 * Add volume serial number - hash of a combination of
2673 * the called hostname and the service name.
2675 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2677 * Win2k3 and previous mess this up by sending a name length
2678 * one byte short. I believe only older clients (OS/2 Win9x) use
2679 * this call so try fixing this by adding a terminating null to
2680 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2684 pdata+l2_vol_szVolLabel, vname,
2685 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2686 STR_NOALIGN|STR_TERMINATE);
2687 SCVAL(pdata,l2_vol_cch,len);
2688 data_len = l2_vol_szVolLabel + len;
2689 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2690 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2694 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2695 case SMB_FS_ATTRIBUTE_INFORMATION:
2697 additional_flags = 0;
2698 #if defined(HAVE_SYS_QUOTAS)
2699 additional_flags |= FILE_VOLUME_QUOTAS;
2702 if(lp_nt_acl_support(SNUM(conn))) {
2703 additional_flags |= FILE_PERSISTENT_ACLS;
2706 /* Capabilities are filled in at connection time through STATVFS call */
2707 additional_flags |= conn->fs_capabilities;
2709 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2710 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2711 additional_flags); /* FS ATTRIBUTES */
2713 SIVAL(pdata,4,255); /* Max filename component length */
2714 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2715 and will think we can't do long filenames */
2716 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2717 PTR_DIFF(end_data, pdata+12),
2720 data_len = 12 + len;
2723 case SMB_QUERY_FS_LABEL_INFO:
2724 case SMB_FS_LABEL_INFORMATION:
2725 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2726 PTR_DIFF(end_data, pdata+4), 0);
2731 case SMB_QUERY_FS_VOLUME_INFO:
2732 case SMB_FS_VOLUME_INFORMATION:
2735 * Add volume serial number - hash of a combination of
2736 * the called hostname and the service name.
2738 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2739 (str_checksum(get_local_machine_name())<<16));
2741 /* Max label len is 32 characters. */
2742 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2743 PTR_DIFF(end_data, pdata+18),
2745 SIVAL(pdata,12,len);
2748 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2749 (int)strlen(vname),vname, lp_servicename(snum)));
2752 case SMB_QUERY_FS_SIZE_INFO:
2753 case SMB_FS_SIZE_INFORMATION:
2755 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2757 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2758 reply_unixerror(req, ERRHRD, ERRgeneral);
2761 block_size = lp_block_size(snum);
2762 if (bsize < block_size) {
2763 uint64_t factor = block_size/bsize;
2768 if (bsize > block_size) {
2769 uint64_t factor = bsize/block_size;
2774 bytes_per_sector = 512;
2775 sectors_per_unit = bsize/bytes_per_sector;
2776 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2777 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2778 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2779 SBIG_UINT(pdata,0,dsize);
2780 SBIG_UINT(pdata,8,dfree);
2781 SIVAL(pdata,16,sectors_per_unit);
2782 SIVAL(pdata,20,bytes_per_sector);
2786 case SMB_FS_FULL_SIZE_INFORMATION:
2788 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2790 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2791 reply_unixerror(req, ERRHRD, ERRgeneral);
2794 block_size = lp_block_size(snum);
2795 if (bsize < block_size) {
2796 uint64_t factor = block_size/bsize;
2801 if (bsize > block_size) {
2802 uint64_t factor = bsize/block_size;
2807 bytes_per_sector = 512;
2808 sectors_per_unit = bsize/bytes_per_sector;
2809 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2810 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2811 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2812 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2813 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2814 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2815 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2816 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2820 case SMB_QUERY_FS_DEVICE_INFO:
2821 case SMB_FS_DEVICE_INFORMATION:
2823 SIVAL(pdata,0,0); /* dev type */
2824 SIVAL(pdata,4,0); /* characteristics */
2827 #ifdef HAVE_SYS_QUOTAS
2828 case SMB_FS_QUOTA_INFORMATION:
2830 * what we have to send --metze:
2832 * Unknown1: 24 NULL bytes
2833 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2834 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2835 * Quota Flags: 2 byte :
2836 * Unknown3: 6 NULL bytes
2840 * details for Quota Flags:
2842 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2843 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2844 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2845 * 0x0001 Enable Quotas: enable quota for this fs
2849 /* we need to fake up a fsp here,
2850 * because its not send in this call
2853 SMB_NTQUOTA_STRUCT quotas;
2856 ZERO_STRUCT(quotas);
2862 if (conn->server_info->utok.uid != 0) {
2863 DEBUG(0,("set_user_quota: access_denied "
2864 "service [%s] user [%s]\n",
2865 lp_servicename(SNUM(conn)),
2866 conn->server_info->unix_name));
2867 reply_doserror(req, ERRDOS, ERRnoaccess);
2871 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2872 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2873 reply_doserror(req, ERRSRV, ERRerror);
2879 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2881 /* Unknown1 24 NULL bytes*/
2882 SBIG_UINT(pdata,0,(uint64_t)0);
2883 SBIG_UINT(pdata,8,(uint64_t)0);
2884 SBIG_UINT(pdata,16,(uint64_t)0);
2886 /* Default Soft Quota 8 bytes */
2887 SBIG_UINT(pdata,24,quotas.softlim);
2889 /* Default Hard Quota 8 bytes */
2890 SBIG_UINT(pdata,32,quotas.hardlim);
2892 /* Quota flag 2 bytes */
2893 SSVAL(pdata,40,quotas.qflags);
2895 /* Unknown3 6 NULL bytes */
2901 #endif /* HAVE_SYS_QUOTAS */
2902 case SMB_FS_OBJECTID_INFORMATION:
2904 unsigned char objid[16];
2905 struct smb_extended_info extended_info;
2906 memcpy(pdata,create_volume_objectid(conn, objid),16);
2907 samba_extended_info_version (&extended_info);
2908 SIVAL(pdata,16,extended_info.samba_magic);
2909 SIVAL(pdata,20,extended_info.samba_version);
2910 SIVAL(pdata,24,extended_info.samba_subversion);
2911 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2912 memcpy(pdata+36,extended_info.samba_version_string,28);
2918 * Query the version and capabilities of the CIFS UNIX extensions
2922 case SMB_QUERY_CIFS_UNIX_INFO:
2924 bool large_write = lp_min_receive_file_size() &&
2925 !srv_is_signing_active(smbd_server_conn);
2926 bool large_read = !srv_is_signing_active(smbd_server_conn);
2927 int encrypt_caps = 0;
2929 if (!lp_unix_extensions()) {
2930 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2934 switch (conn->encrypt_level) {
2940 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2943 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2944 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2945 large_write = false;
2951 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2952 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2954 /* We have POSIX ACLs, pathname, encryption,
2955 * large read/write, and locking capability. */
2957 SBIG_UINT(pdata,4,((uint64_t)(
2958 CIFS_UNIX_POSIX_ACLS_CAP|
2959 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2960 CIFS_UNIX_FCNTL_LOCKS_CAP|
2961 CIFS_UNIX_EXTATTR_CAP|
2962 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2964 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2966 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2970 case SMB_QUERY_POSIX_FS_INFO:
2973 vfs_statvfs_struct svfs;
2975 if (!lp_unix_extensions()) {
2976 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2980 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2984 SIVAL(pdata,0,svfs.OptimalTransferSize);
2985 SIVAL(pdata,4,svfs.BlockSize);
2986 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2987 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2988 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2989 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2990 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2991 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2992 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2994 } else if (rc == EOPNOTSUPP) {
2995 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2997 #endif /* EOPNOTSUPP */
2999 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3000 reply_doserror(req, ERRSRV, ERRerror);
3006 case SMB_QUERY_POSIX_WHOAMI:
3012 if (!lp_unix_extensions()) {
3013 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3017 if (max_data_bytes < 40) {
3018 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3022 /* We ARE guest if global_sid_Builtin_Guests is
3023 * in our list of SIDs.
3025 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3026 conn->server_info->ptok)) {
3027 flags |= SMB_WHOAMI_GUEST;
3030 /* We are NOT guest if global_sid_Authenticated_Users
3031 * is in our list of SIDs.
3033 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3034 conn->server_info->ptok)) {
3035 flags &= ~SMB_WHOAMI_GUEST;
3038 /* NOTE: 8 bytes for UID/GID, irrespective of native
3039 * platform size. This matches
3040 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3042 data_len = 4 /* flags */
3049 + 4 /* pad/reserved */
3050 + (conn->server_info->utok.ngroups * 8)
3052 + (conn->server_info->ptok->num_sids *
3056 SIVAL(pdata, 0, flags);
3057 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3059 (uint64_t)conn->server_info->utok.uid);
3060 SBIG_UINT(pdata, 16,
3061 (uint64_t)conn->server_info->utok.gid);
3064 if (data_len >= max_data_bytes) {
3065 /* Potential overflow, skip the GIDs and SIDs. */
3067 SIVAL(pdata, 24, 0); /* num_groups */
3068 SIVAL(pdata, 28, 0); /* num_sids */
3069 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3070 SIVAL(pdata, 36, 0); /* reserved */
3076 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3077 SIVAL(pdata, 28, conn->server_info->num_sids);
3079 /* We walk the SID list twice, but this call is fairly
3080 * infrequent, and I don't expect that it's performance
3081 * sensitive -- jpeach
3083 for (i = 0, sid_bytes = 0;
3084 i < conn->server_info->ptok->num_sids; ++i) {
3085 sid_bytes += ndr_size_dom_sid(
3086 &conn->server_info->ptok->user_sids[i],
3091 /* SID list byte count */
3092 SIVAL(pdata, 32, sid_bytes);
3094 /* 4 bytes pad/reserved - must be zero */
3095 SIVAL(pdata, 36, 0);
3099 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3100 SBIG_UINT(pdata, data_len,
3101 (uint64_t)conn->server_info->utok.groups[i]);
3107 i < conn->server_info->ptok->num_sids; ++i) {
3108 int sid_len = ndr_size_dom_sid(
3109 &conn->server_info->ptok->user_sids[i],
3113 sid_linearize(pdata + data_len, sid_len,
3114 &conn->server_info->ptok->user_sids[i]);
3115 data_len += sid_len;
3121 case SMB_MAC_QUERY_FS_INFO:
3123 * Thursby MAC extension... ONLY on NTFS filesystems
3124 * once we do streams then we don't need this
3126 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3128 SIVAL(pdata,84,0x100); /* Don't support mac... */
3133 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3138 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3141 DEBUG( 4, ( "%s info_level = %d\n",
3142 smb_fn_name(req->cmd), info_level) );
3147 /****************************************************************************
3148 Reply to a TRANS2_SETFSINFO (set filesystem info).
3149 ****************************************************************************/
3151 static void call_trans2setfsinfo(connection_struct *conn,
3152 struct smb_request *req,
3153 char **pparams, int total_params,
3154 char **ppdata, int total_data,
3155 unsigned int max_data_bytes)
3157 char *pdata = *ppdata;
3158 char *params = *pparams;
3161 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3164 if (total_params < 4) {
3165 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3171 info_level = SVAL(params,2);
3174 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3175 info_level != SMB_SET_CIFS_UNIX_INFO) {
3176 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3177 "info level (0x%x) on IPC$.\n",
3178 (unsigned int)info_level));
3179 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3184 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3185 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3186 DEBUG(0,("call_trans2setfsinfo: encryption required "
3187 "and info level 0x%x sent.\n",
3188 (unsigned int)info_level));
3189 exit_server_cleanly("encryption required "
3195 switch(info_level) {
3196 case SMB_SET_CIFS_UNIX_INFO:
3198 uint16 client_unix_major;
3199 uint16 client_unix_minor;
3200 uint32 client_unix_cap_low;
3201 uint32 client_unix_cap_high;
3203 if (!lp_unix_extensions()) {
3205 NT_STATUS_INVALID_LEVEL);
3209 /* There should be 12 bytes of capabilities set. */
3210 if (total_data < 8) {
3213 NT_STATUS_INVALID_PARAMETER);
3216 client_unix_major = SVAL(pdata,0);
3217 client_unix_minor = SVAL(pdata,2);
3218 client_unix_cap_low = IVAL(pdata,4);
3219 client_unix_cap_high = IVAL(pdata,8);
3220 /* Just print these values for now. */
3221 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3222 cap_low = 0x%x, cap_high = 0x%x\n",
3223 (unsigned int)client_unix_major,
3224 (unsigned int)client_unix_minor,
3225 (unsigned int)client_unix_cap_low,
3226 (unsigned int)client_unix_cap_high ));
3228 /* Here is where we must switch to posix pathname processing... */
3229 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3230 lp_set_posix_pathnames();
3231 mangle_change_to_posix();
3234 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3235 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3236 /* Client that knows how to do posix locks,
3237 * but not posix open/mkdir operations. Set a
3238 * default type for read/write checks. */
3240 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3246 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3249 size_t param_len = 0;
3250 size_t data_len = total_data;
3252 if (!lp_unix_extensions()) {
3255 NT_STATUS_INVALID_LEVEL);
3259 if (lp_smb_encrypt(SNUM(conn)) == false) {
3262 NT_STATUS_NOT_SUPPORTED);
3266 DEBUG( 4,("call_trans2setfsinfo: "
3267 "request transport encryption.\n"));
3269 status = srv_request_encryption_setup(conn,
3270 (unsigned char **)ppdata,
3272 (unsigned char **)pparams,
3275 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3276 !NT_STATUS_IS_OK(status)) {
3277 reply_nterror(req, status);
3281 send_trans2_replies(conn, req,
3288 if (NT_STATUS_IS_OK(status)) {
3289 /* Server-side transport
3290 * encryption is now *on*. */
3291 status = srv_encryption_start(conn);
3292 if (!NT_STATUS_IS_OK(status)) {
3293 exit_server_cleanly(
3294 "Failure in setting "
3295 "up encrypted transport");
3301 case SMB_FS_QUOTA_INFORMATION:
3303 files_struct *fsp = NULL;
3304 SMB_NTQUOTA_STRUCT quotas;
3306 ZERO_STRUCT(quotas);
3309 if ((conn->server_info->utok.uid != 0)
3310 ||!CAN_WRITE(conn)) {
3311 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3312 lp_servicename(SNUM(conn)),
3313 conn->server_info->unix_name));
3314 reply_doserror(req, ERRSRV, ERRaccess);
3318 /* note: normaly there're 48 bytes,
3319 * but we didn't use the last 6 bytes for now
3322 fsp = file_fsp(req, SVAL(params,0));
3324 if (!check_fsp_ntquota_handle(conn, req,
3326 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3328 req, NT_STATUS_INVALID_HANDLE);
3332 if (total_data < 42) {
3333 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3337 NT_STATUS_INVALID_PARAMETER);
3341 /* unknown_1 24 NULL bytes in pdata*/
3343 /* the soft quotas 8 bytes (uint64_t)*/
3344 quotas.softlim = (uint64_t)IVAL(pdata,24);
3345 #ifdef LARGE_SMB_OFF_T
3346 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3347 #else /* LARGE_SMB_OFF_T */
3348 if ((IVAL(pdata,28) != 0)&&
3349 ((quotas.softlim != 0xFFFFFFFF)||
3350 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3351 /* more than 32 bits? */
3354 NT_STATUS_INVALID_PARAMETER);
3357 #endif /* LARGE_SMB_OFF_T */
3359 /* the hard quotas 8 bytes (uint64_t)*/
3360 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3361 #ifdef LARGE_SMB_OFF_T
3362 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3363 #else /* LARGE_SMB_OFF_T */
3364 if ((IVAL(pdata,36) != 0)&&
3365 ((quotas.hardlim != 0xFFFFFFFF)||
3366 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3367 /* more than 32 bits? */
3370 NT_STATUS_INVALID_PARAMETER);
3373 #endif /* LARGE_SMB_OFF_T */
3375 /* quota_flags 2 bytes **/
3376 quotas.qflags = SVAL(pdata,40);
3378 /* unknown_2 6 NULL bytes follow*/
3380 /* now set the quotas */
3381 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3382 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3383 reply_doserror(req, ERRSRV, ERRerror);
3390 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3392 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3398 * sending this reply works fine,
3399 * but I'm not sure it's the same
3400 * like windows do...
3403 reply_outbuf(req, 10, 0);
3406 #if defined(HAVE_POSIX_ACLS)
3407 /****************************************************************************
3408 Utility function to count the number of entries in a POSIX acl.
3409 ****************************************************************************/
3411 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3413 unsigned int ace_count = 0;
3414 int entry_id = SMB_ACL_FIRST_ENTRY;
3415 SMB_ACL_ENTRY_T entry;
3417 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3419 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3420 entry_id = SMB_ACL_NEXT_ENTRY;
3427 /****************************************************************************
3428 Utility function to marshall a POSIX acl into wire format.
3429 ****************************************************************************/
3431 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3433 int entry_id = SMB_ACL_FIRST_ENTRY;
3434 SMB_ACL_ENTRY_T entry;
3436 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3437 SMB_ACL_TAG_T tagtype;
3438 SMB_ACL_PERMSET_T permset;
3439 unsigned char perms = 0;
3440 unsigned int own_grp;
3443 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3444 entry_id = SMB_ACL_NEXT_ENTRY;
3447 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3448 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3452 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3453 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3457 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3458 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3459 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3461 SCVAL(pdata,1,perms);
3464 case SMB_ACL_USER_OBJ:
3465 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3466 own_grp = (unsigned int)pst->st_ex_uid;
3467 SIVAL(pdata,2,own_grp);
3472 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3474 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3477 own_grp = (unsigned int)*puid;
3478 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3479 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3480 SIVAL(pdata,2,own_grp);
3484 case SMB_ACL_GROUP_OBJ:
3485 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3486 own_grp = (unsigned int)pst->st_ex_gid;
3487 SIVAL(pdata,2,own_grp);
3492 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3494 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3497 own_grp = (unsigned int)*pgid;
3498 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3499 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3500 SIVAL(pdata,2,own_grp);
3505 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3506 SIVAL(pdata,2,0xFFFFFFFF);
3507 SIVAL(pdata,6,0xFFFFFFFF);
3510 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3511 SIVAL(pdata,2,0xFFFFFFFF);
3512 SIVAL(pdata,6,0xFFFFFFFF);
3515 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3518 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3525 /****************************************************************************
3526 Store the FILE_UNIX_BASIC info.
3527 ****************************************************************************/
3529 static char *store_file_unix_basic(connection_struct *conn,
3532 const SMB_STRUCT_STAT *psbuf)
3534 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3535 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3537 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3540 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3543 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3544 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3545 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3548 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3552 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3556 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3559 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3563 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3567 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3570 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3574 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3581 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3582 * the chflags(2) (or equivalent) flags.
3584 * XXX: this really should be behind the VFS interface. To do this, we would
3585 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3586 * Each VFS module could then implement its own mapping as appropriate for the
3587 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3589 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3593 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3597 { UF_IMMUTABLE, EXT_IMMUTABLE },
3601 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3605 { UF_HIDDEN, EXT_HIDDEN },
3608 /* Do not remove. We need to guarantee that this array has at least one
3609 * entry to build on HP-UX.
3615 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3616 uint32 *smb_fflags, uint32 *smb_fmask)
3620 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3621 *smb_fmask |= info2_flags_map[i].smb_fflag;
3622 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3623 *smb_fflags |= info2_flags_map[i].smb_fflag;
3628 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3629 const uint32 smb_fflags,
3630 const uint32 smb_fmask,
3633 uint32 max_fmask = 0;
3636 *stat_fflags = psbuf->st_ex_flags;
3638 /* For each flags requested in smb_fmask, check the state of the
3639 * corresponding flag in smb_fflags and set or clear the matching
3643 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3644 max_fmask |= info2_flags_map[i].smb_fflag;
3645 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3646 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3647 *stat_fflags |= info2_flags_map[i].stat_fflag;
3649 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3654 /* If smb_fmask is asking to set any bits that are not supported by
3655 * our flag mappings, we should fail.
3657 if ((smb_fmask & max_fmask) != smb_fmask) {
3665 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3666 * of file flags and birth (create) time.
3668 static char *store_file_unix_basic_info2(connection_struct *conn,
3671 const SMB_STRUCT_STAT *psbuf)
3673 uint32 file_flags = 0;
3674 uint32 flags_mask = 0;
3676 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3678 /* Create (birth) time 64 bit */
3679 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3682 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3683 SIVAL(pdata, 0, file_flags); /* flags */
3684 SIVAL(pdata, 4, flags_mask); /* mask */
3690 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3691 const struct stream_struct *streams,
3693 unsigned int max_data_bytes,
3694 unsigned int *data_size)
3697 unsigned int ofs = 0;
3699 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3700 unsigned int next_offset;
3702 smb_ucs2_t *namebuf;
3704 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3705 streams[i].name, &namelen) ||
3708 return NT_STATUS_INVALID_PARAMETER;
3712 * name_buf is now null-terminated, we need to marshall as not
3718 SIVAL(data, ofs+4, namelen);
3719 SOFF_T(data, ofs+8, streams[i].size);
3720 SOFF_T(data, ofs+16, streams[i].alloc_size);
3721 memcpy(data+ofs+24, namebuf, namelen);
3722 TALLOC_FREE(namebuf);
3724 next_offset = ofs + 24 + namelen;
3726 if (i == num_streams-1) {
3727 SIVAL(data, ofs, 0);
3730 unsigned int align = ndr_align_size(next_offset, 8);
3732 memset(data+next_offset, 0, align);
3733 next_offset += align;
3735 SIVAL(data, ofs, next_offset - ofs);
3744 return NT_STATUS_OK;
3747 /****************************************************************************
3748 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3749 ****************************************************************************/
3751 static void call_trans2qpipeinfo(connection_struct *conn,
3752 struct smb_request *req,
3753 unsigned int tran_call,
3754 char **pparams, int total_params,
3755 char **ppdata, int total_data,
3756 unsigned int max_data_bytes)
3758 char *params = *pparams;
3759 char *pdata = *ppdata;
3760 unsigned int data_size = 0;
3761 unsigned int param_size = 2;
3766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3770 if (total_params < 4) {
3771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3775 fsp = file_fsp(req, SVAL(params,0));
3776 if (!fsp_is_np(fsp)) {
3777 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3781 info_level = SVAL(params,2);
3783 *pparams = (char *)SMB_REALLOC(*pparams,2);
3784 if (*pparams == NULL) {
3785 reply_nterror(req, NT_STATUS_NO_MEMORY);
3790 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3791 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3792 if (*ppdata == NULL ) {
3793 reply_nterror(req, NT_STATUS_NO_MEMORY);
3798 switch (info_level) {
3799 case SMB_FILE_STANDARD_INFORMATION:
3801 SOFF_T(pdata,0,4096LL);
3808 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3812 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3818 /****************************************************************************
3819 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3820 file name or file id).
3821 ****************************************************************************/
3823 static void call_trans2qfilepathinfo(connection_struct *conn,
3824 struct smb_request *req,
3825 unsigned int tran_call,
3826 char **pparams, int total_params,
3827 char **ppdata, int total_data,
3828 unsigned int max_data_bytes)
3830 char *params = *pparams;
3831 char *pdata = *ppdata;
3832 char *dstart, *dend;
3836 SMB_OFF_T file_size=0;
3837 uint64_t allocation_size=0;
3838 unsigned int data_size = 0;
3839 unsigned int param_size = 2;
3840 SMB_STRUCT_STAT sbuf;
3841 char *dos_fname = NULL;
3843 struct smb_filename *smb_fname = NULL;
3848 bool delete_pending = False;
3850 time_t create_time, mtime, atime;
3851 struct timespec create_time_ts, mtime_ts, atime_ts;
3852 struct timespec write_time_ts;
3853 files_struct *fsp = NULL;
3854 struct file_id fileid;
3855 struct ea_list *ea_list = NULL;
3856 char *lock_data = NULL;
3857 bool ms_dfs_link = false;
3858 TALLOC_CTX *ctx = talloc_tos();
3861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3866 ZERO_STRUCT(write_time_ts);
3868 if (tran_call == TRANSACT2_QFILEINFO) {
3869 if (total_params < 4) {
3870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3875 call_trans2qpipeinfo(conn, req, tran_call,
3876 pparams, total_params,
3882 fsp = file_fsp(req, SVAL(params,0));
3883 info_level = SVAL(params,2);
3885 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3887 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3888 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3892 /* Initial check for valid fsp ptr. */
3893 if (!check_fsp_open(conn, req, fsp)) {
3897 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3899 reply_nterror(req, NT_STATUS_NO_MEMORY);
3903 if(fsp->fake_file_handle) {
3905 * This is actually for the QUOTA_FAKE_FILE --metze
3908 /* We know this name is ok, it's already passed the checks. */
3910 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3912 * This is actually a QFILEINFO on a directory
3913 * handle (returned from an NT SMB). NT5.0 seems
3914 * to do this call. JRA.
3917 if (INFO_LEVEL_IS_UNIX(info_level)) {
3918 /* Always do lstat for UNIX calls. */
3919 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3920 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3921 reply_unixerror(req,ERRDOS,ERRbadpath);
3924 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3925 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3926 reply_unixerror(req, ERRDOS, ERRbadpath);
3930 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3931 get_file_infos(fileid, &delete_pending, &write_time_ts);
3934 * Original code - this is an open file.
3936 if (!check_fsp(conn, req, fsp)) {
3940 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3941 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3942 reply_unixerror(req, ERRDOS, ERRbadfid);
3945 pos = fsp->fh->position_information;
3946 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3947 get_file_infos(fileid, &delete_pending, &write_time_ts);
3951 NTSTATUS status = NT_STATUS_OK;
3954 if (total_params < 7) {
3955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3959 info_level = SVAL(params,0);
3961 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3963 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3964 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3968 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3970 STR_TERMINATE, &status);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 reply_nterror(req, status);
3976 status = resolve_dfspath(ctx,
3978 req->flags2 & FLAGS2_DFS_PATHNAMES,
3981 if (!NT_STATUS_IS_OK(status)) {
3982 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3983 reply_botherror(req,
3984 NT_STATUS_PATH_NOT_COVERED,
3985 ERRSRV, ERRbadpath);
3987 reply_nterror(req, status);
3991 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
3992 if (!NT_STATUS_IS_OK(status)) {
3993 reply_nterror(req, status);
3996 sbuf = smb_fname->st;
3998 status = get_full_smb_filename(ctx, smb_fname, &fname);
3999 TALLOC_FREE(smb_fname);
4000 if (!NT_STATUS_IS_OK(status)) {
4001 reply_nterror(req, status);
4005 status = check_name(conn, fname);
4006 if (!NT_STATUS_IS_OK(status)) {
4007 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
4008 reply_nterror(req, status);
4012 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4013 && is_ntfs_stream_name(fname)) {
4015 SMB_STRUCT_STAT bsbuf;
4017 status = split_ntfs_stream_name(talloc_tos(), fname,
4019 if (!NT_STATUS_IS_OK(status)) {
4020 DEBUG(10, ("create_file_unixpath: "
4021 "split_ntfs_stream_name failed: %s\n",
4022 nt_errstr(status)));
4023 reply_nterror(req, status);
4027 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4029 if (INFO_LEVEL_IS_UNIX(info_level)) {
4030 /* Always do lstat for UNIX calls. */
4031 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4032 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4033 reply_unixerror(req,ERRDOS,ERRbadpath);
4037 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4038 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4039 reply_unixerror(req,ERRDOS,ERRbadpath);
4044 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4045 get_file_infos(fileid, &delete_pending, NULL);
4046 if (delete_pending) {
4047 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4052 if (INFO_LEVEL_IS_UNIX(info_level)) {
4053 /* Always do lstat for UNIX calls. */
4054 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4055 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4056 reply_unixerror(req, ERRDOS, ERRbadpath);
4060 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4061 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4064 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4065 reply_unixerror(req, ERRDOS, ERRbadpath);
4070 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4071 get_file_infos(fileid, &delete_pending, &write_time_ts);
4072 if (delete_pending) {
4073 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4078 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4079 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4083 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4084 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4086 p = strrchr_m(fname,'/');
4093 mode = dos_mode_msdfs(conn,fname,&sbuf);
4095 mode = dos_mode(conn,fname,&sbuf);
4098 mode = FILE_ATTRIBUTE_NORMAL;
4100 nlink = sbuf.st_ex_nlink;
4102 if (nlink && (mode&aDIR)) {
4106 if ((nlink > 0) && delete_pending) {
4110 fullpathname = fname;
4112 file_size = get_file_size_stat(&sbuf);
4114 /* Pull out any data sent here before we realloc. */
4115 switch (info_level) {
4116 case SMB_INFO_QUERY_EAS_FROM_LIST:
4118 /* Pull any EA list from the data portion. */
4121 if (total_data < 4) {
4123 req, NT_STATUS_INVALID_PARAMETER);
4126 ea_size = IVAL(pdata,0);
4128 if (total_data > 0 && ea_size != total_data) {
4129 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4130 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4132 req, NT_STATUS_INVALID_PARAMETER);
4136 if (!lp_ea_support(SNUM(conn))) {
4137 reply_doserror(req, ERRDOS,
4138 ERReasnotsupported);
4142 /* Pull out the list of names. */
4143 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4146 req, NT_STATUS_INVALID_PARAMETER);
4152 case SMB_QUERY_POSIX_LOCK:
4154 if (fsp == NULL || fsp->fh->fd == -1) {
4155 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4159 if (total_data != POSIX_LOCK_DATA_SIZE) {
4161 req, NT_STATUS_INVALID_PARAMETER);
4165 /* Copy the lock range data. */
4166 lock_data = (char *)TALLOC_MEMDUP(
4167 ctx, pdata, total_data);
4169 reply_nterror(req, NT_STATUS_NO_MEMORY);
4177 *pparams = (char *)SMB_REALLOC(*pparams,2);
4178 if (*pparams == NULL) {
4179 reply_nterror(req, NT_STATUS_NO_MEMORY);
4184 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4185 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4186 if (*ppdata == NULL ) {
4187 reply_nterror(req, NT_STATUS_NO_MEMORY);
4192 dend = dstart + data_size - 1;
4194 create_time_ts = sbuf.st_ex_btime;
4195 mtime_ts = sbuf.st_ex_mtime;
4196 atime_ts = sbuf.st_ex_atime;
4198 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4201 /* Do we have this path open ? */
4203 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4204 fsp1 = file_find_di_first(fileid);
4205 if (fsp1 && fsp1->initial_allocation_size) {
4206 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4210 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4211 mtime_ts = write_time_ts;
4214 if (lp_dos_filetime_resolution(SNUM(conn))) {
4215 dos_filetime_timespec(&create_time_ts);
4216 dos_filetime_timespec(&mtime_ts);
4217 dos_filetime_timespec(&atime_ts);
4220 create_time = convert_timespec_to_time_t(create_time_ts);
4221 mtime = convert_timespec_to_time_t(mtime_ts);
4222 atime = convert_timespec_to_time_t(atime_ts);
4224 /* NT expects the name to be in an exact form of the *full*
4225 filename. See the trans2 torture test */
4226 if (ISDOT(base_name)) {
4227 dos_fname = talloc_strdup(ctx, "\\");
4229 reply_nterror(req, NT_STATUS_NO_MEMORY);
4233 dos_fname = talloc_asprintf(ctx,
4237 reply_nterror(req, NT_STATUS_NO_MEMORY);
4240 string_replace(dos_fname, '/', '\\');
4243 switch (info_level) {
4244 case SMB_INFO_STANDARD:
4245 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4247 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4248 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4249 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4250 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4251 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4252 SSVAL(pdata,l1_attrFile,mode);
4255 case SMB_INFO_QUERY_EA_SIZE:
4257 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4258 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4260 srv_put_dos_date2(pdata,0,create_time);
4261 srv_put_dos_date2(pdata,4,atime);
4262 srv_put_dos_date2(pdata,8,mtime); /* write time */
4263 SIVAL(pdata,12,(uint32)file_size);
4264 SIVAL(pdata,16,(uint32)allocation_size);
4265 SSVAL(pdata,20,mode);
4266 SIVAL(pdata,22,ea_size);
4270 case SMB_INFO_IS_NAME_VALID:
4271 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4272 if (tran_call == TRANSACT2_QFILEINFO) {
4273 /* os/2 needs this ? really ?*/
4274 reply_doserror(req, ERRDOS, ERRbadfunc);
4281 case SMB_INFO_QUERY_EAS_FROM_LIST:
4283 size_t total_ea_len = 0;
4284 struct ea_list *ea_file_list = NULL;
4286 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4288 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4289 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4291 if (!ea_list || (total_ea_len > data_size)) {
4293 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4297 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4301 case SMB_INFO_QUERY_ALL_EAS:
4303 /* We have data_size bytes to put EA's into. */
4304 size_t total_ea_len = 0;
4306 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4308 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4309 if (!ea_list || (total_ea_len > data_size)) {
4311 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4315 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4319 case SMB_FILE_BASIC_INFORMATION:
4320 case SMB_QUERY_FILE_BASIC_INFO:
4322 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4323 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4324 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4326 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4330 put_long_date_timespec(pdata,create_time_ts);
4331 put_long_date_timespec(pdata+8,atime_ts);
4332 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4333 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4334 SIVAL(pdata,32,mode);
4336 DEBUG(5,("SMB_QFBI - "));
4337 DEBUG(5,("create: %s ", ctime(&create_time)));
4338 DEBUG(5,("access: %s ", ctime(&atime)));
4339 DEBUG(5,("write: %s ", ctime(&mtime)));
4340 DEBUG(5,("change: %s ", ctime(&mtime)));
4341 DEBUG(5,("mode: %x\n", mode));
4344 case SMB_FILE_STANDARD_INFORMATION:
4345 case SMB_QUERY_FILE_STANDARD_INFO:
4347 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4349 SOFF_T(pdata,0,allocation_size);
4350 SOFF_T(pdata,8,file_size);
4351 SIVAL(pdata,16,nlink);
4352 SCVAL(pdata,20,delete_pending?1:0);
4353 SCVAL(pdata,21,(mode&aDIR)?1:0);
4354 SSVAL(pdata,22,0); /* Padding. */
4357 case SMB_FILE_EA_INFORMATION:
4358 case SMB_QUERY_FILE_EA_INFO:
4360 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4361 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4363 SIVAL(pdata,0,ea_size);
4367 /* Get the 8.3 name - used if NT SMB was negotiated. */
4368 case SMB_QUERY_FILE_ALT_NAME_INFO:
4369 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4371 char mangled_name[13];
4372 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4373 if (!name_to_8_3(base_name,mangled_name,
4374 True,conn->params)) {
4377 NT_STATUS_NO_MEMORY);
4379 len = srvstr_push(dstart, req->flags2,
4380 pdata+4, mangled_name,
4381 PTR_DIFF(dend, pdata+4),
4383 data_size = 4 + len;
4388 case SMB_QUERY_FILE_NAME_INFO:
4390 this must be *exactly* right for ACLs on mapped drives to work
4392 len = srvstr_push(dstart, req->flags2,
4394 PTR_DIFF(dend, pdata+4),
4396 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4397 data_size = 4 + len;
4401 case SMB_FILE_ALLOCATION_INFORMATION:
4402 case SMB_QUERY_FILE_ALLOCATION_INFO:
4403 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4405 SOFF_T(pdata,0,allocation_size);
4408 case SMB_FILE_END_OF_FILE_INFORMATION:
4409 case SMB_QUERY_FILE_END_OF_FILEINFO:
4410 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4412 SOFF_T(pdata,0,file_size);
4415 case SMB_QUERY_FILE_ALL_INFO:
4416 case SMB_FILE_ALL_INFORMATION:
4418 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4419 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4420 put_long_date_timespec(pdata,create_time_ts);
4421 put_long_date_timespec(pdata+8,atime_ts);
4422 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4423 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4424 SIVAL(pdata,32,mode);
4425 SIVAL(pdata,36,0); /* padding. */
4427 SOFF_T(pdata,0,allocation_size);
4428 SOFF_T(pdata,8,file_size);
4429 SIVAL(pdata,16,nlink);
4430 SCVAL(pdata,20,delete_pending);
4431 SCVAL(pdata,21,(mode&aDIR)?1:0);
4434 SIVAL(pdata,0,ea_size);
4435 pdata += 4; /* EA info */
4436 len = srvstr_push(dstart, req->flags2,
4438 PTR_DIFF(dend, pdata+4),
4442 data_size = PTR_DIFF(pdata,(*ppdata));
4445 case SMB_FILE_INTERNAL_INFORMATION:
4446 /* This should be an index number - looks like
4449 I think this causes us to fail the IFSKIT
4450 BasicFileInformationTest. -tpot */
4452 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4453 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4454 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4458 case SMB_FILE_ACCESS_INFORMATION:
4459 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4461 SIVAL(pdata,0,fsp->access_mask);
4463 /* GENERIC_EXECUTE mapping from Windows */
4464 SIVAL(pdata,0,0x12019F);
4469 case SMB_FILE_NAME_INFORMATION:
4470 /* Pathname with leading '\'. */
4473 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4474 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4475 SIVAL(pdata,0,byte_len);
4476 data_size = 4 + byte_len;
4480 case SMB_FILE_DISPOSITION_INFORMATION:
4481 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4483 SCVAL(pdata,0,delete_pending);
4486 case SMB_FILE_POSITION_INFORMATION:
4487 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4489 SOFF_T(pdata,0,pos);
4492 case SMB_FILE_MODE_INFORMATION:
4493 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4494 SIVAL(pdata,0,mode);
4498 case SMB_FILE_ALIGNMENT_INFORMATION:
4499 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4500 SIVAL(pdata,0,0); /* No alignment needed. */
4505 * NT4 server just returns "invalid query" to this - if we try
4506 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4509 /* The first statement above is false - verified using Thursby
4510 * client against NT4 -- gcolley.
4512 case SMB_QUERY_FILE_STREAM_INFO:
4513 case SMB_FILE_STREAM_INFORMATION: {
4514 unsigned int num_streams;
4515 struct stream_struct *streams;
4518 DEBUG(10,("call_trans2qfilepathinfo: "
4519 "SMB_FILE_STREAM_INFORMATION\n"));
4521 status = SMB_VFS_STREAMINFO(
4522 conn, fsp, fname, talloc_tos(),
4523 &num_streams, &streams);
4525 if (!NT_STATUS_IS_OK(status)) {
4526 DEBUG(10, ("could not get stream info: %s\n",
4527 nt_errstr(status)));
4528 reply_nterror(req, status);
4532 status = marshall_stream_info(num_streams, streams,
4533 pdata, max_data_bytes,
4536 if (!NT_STATUS_IS_OK(status)) {
4537 DEBUG(10, ("marshall_stream_info failed: %s\n",
4538 nt_errstr(status)));
4539 reply_nterror(req, status);
4543 TALLOC_FREE(streams);
4547 case SMB_QUERY_COMPRESSION_INFO:
4548 case SMB_FILE_COMPRESSION_INFORMATION:
4549 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4550 SOFF_T(pdata,0,file_size);
4551 SIVAL(pdata,8,0); /* ??? */
4552 SIVAL(pdata,12,0); /* ??? */
4556 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4557 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4558 put_long_date_timespec(pdata,create_time_ts);
4559 put_long_date_timespec(pdata+8,atime_ts);
4560 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4561 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4562 SOFF_T(pdata,32,allocation_size);
4563 SOFF_T(pdata,40,file_size);
4564 SIVAL(pdata,48,mode);
4565 SIVAL(pdata,52,0); /* ??? */
4569 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4570 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4571 SIVAL(pdata,0,mode);
4577 * CIFS UNIX Extensions.
4580 case SMB_QUERY_FILE_UNIX_BASIC:
4582 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4583 data_size = PTR_DIFF(pdata,(*ppdata));
4587 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4589 for (i=0; i<100; i++)
4590 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4596 case SMB_QUERY_FILE_UNIX_INFO2:
4598 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4599 data_size = PTR_DIFF(pdata,(*ppdata));
4603 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4605 for (i=0; i<100; i++)
4606 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4612 case SMB_QUERY_FILE_UNIX_LINK:
4614 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4617 reply_nterror(req, NT_STATUS_NO_MEMORY);
4621 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4623 if(!S_ISLNK(sbuf.st_ex_mode)) {
4624 reply_unixerror(req, ERRSRV,
4629 reply_unixerror(req, ERRDOS, ERRbadlink);
4632 len = SMB_VFS_READLINK(conn,fullpathname,
4635 reply_unixerror(req, ERRDOS,
4640 len = srvstr_push(dstart, req->flags2,
4642 PTR_DIFF(dend, pdata),
4645 data_size = PTR_DIFF(pdata,(*ppdata));
4650 #if defined(HAVE_POSIX_ACLS)
4651 case SMB_QUERY_POSIX_ACL:
4653 SMB_ACL_T file_acl = NULL;
4654 SMB_ACL_T def_acl = NULL;
4655 uint16 num_file_acls = 0;
4656 uint16 num_def_acls = 0;
4658 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4659 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4661 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4664 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4665 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4669 NT_STATUS_NOT_IMPLEMENTED);
4673 if (S_ISDIR(sbuf.st_ex_mode)) {
4674 if (fsp && fsp->is_directory) {
4675 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4677 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4679 def_acl = free_empty_sys_acl(conn, def_acl);
4682 num_file_acls = count_acl_entries(conn, file_acl);
4683 num_def_acls = count_acl_entries(conn, def_acl);
4685 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4686 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4688 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4689 SMB_POSIX_ACL_HEADER_SIZE) ));
4691 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4694 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4698 NT_STATUS_BUFFER_TOO_SMALL);
4702 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4703 SSVAL(pdata,2,num_file_acls);
4704 SSVAL(pdata,4,num_def_acls);
4705 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4707 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4710 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4713 req, NT_STATUS_INTERNAL_ERROR);
4716 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4718 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4721 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4725 NT_STATUS_INTERNAL_ERROR);
4730 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4733 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4735 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4741 case SMB_QUERY_POSIX_LOCK:
4743 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4747 enum brl_type lock_type;
4749 if (total_data != POSIX_LOCK_DATA_SIZE) {
4751 req, NT_STATUS_INVALID_PARAMETER);
4755 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4756 case POSIX_LOCK_TYPE_READ:
4757 lock_type = READ_LOCK;
4759 case POSIX_LOCK_TYPE_WRITE:
4760 lock_type = WRITE_LOCK;
4762 case POSIX_LOCK_TYPE_UNLOCK:
4764 /* There's no point in asking for an unlock... */
4767 NT_STATUS_INVALID_PARAMETER);
4771 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4772 #if defined(HAVE_LONGLONG)
4773 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4774 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4775 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4776 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4777 #else /* HAVE_LONGLONG */
4778 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4779 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4780 #endif /* HAVE_LONGLONG */
4782 status = query_lock(fsp,
4789 if (ERROR_WAS_LOCK_DENIED(status)) {
4790 /* Here we need to report who has it locked... */
4791 data_size = POSIX_LOCK_DATA_SIZE;
4793 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4794 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4795 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4796 #if defined(HAVE_LONGLONG)
4797 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4798 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4799 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4800 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4801 #else /* HAVE_LONGLONG */
4802 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4803 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4804 #endif /* HAVE_LONGLONG */
4806 } else if (NT_STATUS_IS_OK(status)) {
4807 /* For success we just return a copy of what we sent
4808 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4809 data_size = POSIX_LOCK_DATA_SIZE;
4810 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4811 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4813 reply_nterror(req, status);
4820 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4824 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4830 /****************************************************************************
4831 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4833 ****************************************************************************/
4835 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4836 connection_struct *conn,
4837 const char *oldname_in,
4838 const char *newname_in)
4840 struct smb_filename *smb_fname = NULL;
4841 struct smb_filename *smb_fname_new = NULL;
4842 char *oldname = NULL;
4843 char *newname = NULL;
4844 NTSTATUS status = NT_STATUS_OK;
4846 status = unix_convert(ctx, conn, oldname_in, &smb_fname, 0);
4847 if (!NT_STATUS_IS_OK(status)) {
4851 status = get_full_smb_filename(ctx, smb_fname, &oldname);
4852 if (!NT_STATUS_IS_OK(status)) {
4856 status = check_name(conn, oldname);
4857 if (!NT_STATUS_IS_OK(status)) {
4861 /* source must already exist. */
4862 if (!VALID_STAT(smb_fname->st)) {
4863 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4867 status = unix_convert(ctx, conn, newname_in, &smb_fname_new, 0);
4868 if (!NT_STATUS_IS_OK(status)) {
4872 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
4873 if (!NT_STATUS_IS_OK(status)) {
4877 status = check_name(conn, newname);
4878 if (!NT_STATUS_IS_OK(status)) {
4882 /* Disallow if newname already exists. */
4883 if (VALID_STAT(smb_fname_new->st)) {
4884 status = NT_STATUS_OBJECT_NAME_COLLISION;
4888 /* No links from a directory. */
4889 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
4890 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4894 /* Ensure this is within the share. */
4895 status = check_reduced_name(conn, oldname);
4896 if (!NT_STATUS_IS_OK(status)) {
4900 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4902 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4903 status = map_nt_error_from_unix(errno);
4904 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4905 nt_errstr(status), newname, oldname));
4908 TALLOC_FREE(smb_fname);
4909 TALLOC_FREE(smb_fname_new);
4913 /****************************************************************************
4914 Deal with setting the time from any of the setfilepathinfo functions.
4915 ****************************************************************************/
4917 NTSTATUS smb_set_file_time(connection_struct *conn,
4920 const SMB_STRUCT_STAT *psbuf,
4921 struct smb_file_time *ft,
4922 bool setting_write_time)
4925 FILE_NOTIFY_CHANGE_LAST_ACCESS
4926 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4928 if (!VALID_STAT(*psbuf)) {
4929 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4932 /* get some defaults (no modifications) if any info is zero or -1. */
4933 if (null_timespec(ft->atime)) {
4934 ft->atime= psbuf->st_ex_atime;
4935 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4938 if (null_timespec(ft->mtime)) {
4939 ft->mtime = psbuf->st_ex_mtime;
4940 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4943 if (!setting_write_time) {
4944 /* ft->mtime comes from change time, not write time. */
4945 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4948 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4949 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4950 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4951 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4952 if (!null_timespec(ft->create_time)) {
4953 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4954 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4958 * Try and set the times of this file if
4959 * they are different from the current values.
4963 struct timespec mts = psbuf->st_ex_mtime;
4964 struct timespec ats = psbuf->st_ex_atime;
4965 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4966 (timespec_compare(&ft->mtime, &mts) == 0)) {
4967 return NT_STATUS_OK;
4971 if (setting_write_time) {
4973 * This was a setfileinfo on an open file.
4974 * NT does this a lot. We also need to
4975 * set the time here, as it can be read by
4976 * FindFirst/FindNext and with the patch for bug #2045
4977 * in smbd/fileio.c it ensures that this timestamp is
4978 * kept sticky even after a write. We save the request
4979 * away and will set it on file close and after a write. JRA.
4982 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4983 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4986 if (fsp->base_fsp) {
4987 set_sticky_write_time_fsp(fsp->base_fsp,
4990 set_sticky_write_time_fsp(fsp, ft->mtime);
4993 set_sticky_write_time_path(conn, fname,
4994 vfs_file_id_from_sbuf(conn, psbuf),
4999 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5001 if (fsp && fsp->base_fsp) {
5002 fname = fsp->base_fsp->fsp_name;
5005 if(file_ntimes(conn, fname, ft)!=0) {
5006 return map_nt_error_from_unix(errno);
5008 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
5010 return NT_STATUS_OK;
5013 /****************************************************************************
5014 Deal with setting the dosmode from any of the setfilepathinfo functions.
5015 ****************************************************************************/
5017 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5020 SMB_STRUCT_STAT *psbuf,
5023 if (!VALID_STAT(*psbuf)) {
5024 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5028 if (fsp->base_fsp) {
5029 fname = fsp->base_fsp->fsp_name;
5031 fname = fsp->fsp_name;
5036 if (S_ISDIR(psbuf->st_ex_mode)) {
5043 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5045 /* check the mode isn't different, before changing it */
5046 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5048 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5049 fname, (unsigned int)dosmode ));
5051 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5052 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5053 fname, strerror(errno)));
5054 return map_nt_error_from_unix(errno);
5057 return NT_STATUS_OK;
5060 /****************************************************************************
5061 Deal with setting the size from any of the setfilepathinfo functions.
5062 ****************************************************************************/
5064 static NTSTATUS smb_set_file_size(connection_struct *conn,
5065 struct smb_request *req,
5068 SMB_STRUCT_STAT *psbuf,
5071 NTSTATUS status = NT_STATUS_OK;
5072 files_struct *new_fsp = NULL;
5074 if (!VALID_STAT(*psbuf)) {
5075 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5078 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5080 if (size == get_file_size_stat(psbuf)) {
5081 return NT_STATUS_OK;
5084 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5085 fname, (double)size ));
5087 if (fsp && fsp->fh->fd != -1) {
5088 /* Handle based call. */
5089 if (vfs_set_filelen(fsp, size) == -1) {
5090 return map_nt_error_from_unix(errno);
5092 trigger_write_time_update_immediate(fsp);
5093 return NT_STATUS_OK;
5096 status = SMB_VFS_CREATE_FILE(
5099 0, /* root_dir_fid */
5101 0, /* create_file_flags */
5102 FILE_WRITE_ATTRIBUTES, /* access_mask */
5103 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5105 FILE_OPEN, /* create_disposition*/
5106 0, /* create_options */
5107 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5108 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5109 0, /* allocation_size */
5112 &new_fsp, /* result */
5116 if (!NT_STATUS_IS_OK(status)) {
5117 /* NB. We check for open_was_deferred in the caller. */
5121 if (vfs_set_filelen(new_fsp, size) == -1) {
5122 status = map_nt_error_from_unix(errno);
5123 close_file(req, new_fsp,NORMAL_CLOSE);
5127 trigger_write_time_update_immediate(new_fsp);
5128 close_file(req, new_fsp,NORMAL_CLOSE);
5129 return NT_STATUS_OK;
5132 /****************************************************************************
5133 Deal with SMB_INFO_SET_EA.
5134 ****************************************************************************/
5136 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5142 struct ea_list *ea_list = NULL;
5143 TALLOC_CTX *ctx = NULL;
5144 NTSTATUS status = NT_STATUS_OK;
5146 if (total_data < 10) {
5148 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5149 length. They seem to have no effect. Bug #3212. JRA */
5151 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5152 /* We're done. We only get EA info in this call. */
5153 return NT_STATUS_OK;
5156 return NT_STATUS_INVALID_PARAMETER;
5159 if (IVAL(pdata,0) > total_data) {
5160 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5161 IVAL(pdata,0), (unsigned int)total_data));
5162 return NT_STATUS_INVALID_PARAMETER;
5166 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5168 return NT_STATUS_INVALID_PARAMETER;
5170 status = set_ea(conn, fsp, fname, ea_list);
5175 /****************************************************************************
5176 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5177 ****************************************************************************/
5179 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5184 SMB_STRUCT_STAT *psbuf)
5186 NTSTATUS status = NT_STATUS_OK;
5187 bool delete_on_close;
5190 if (total_data < 1) {
5191 return NT_STATUS_INVALID_PARAMETER;
5195 return NT_STATUS_INVALID_HANDLE;
5198 delete_on_close = (CVAL(pdata,0) ? True : False);
5199 dosmode = dos_mode(conn, fname, psbuf);
5201 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5202 "delete_on_close = %u\n",
5204 (unsigned int)dosmode,
5205 (unsigned int)delete_on_close ));
5207 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5209 if (!NT_STATUS_IS_OK(status)) {
5213 /* The set is across all open files on this dev/inode pair. */
5214 if (!set_delete_on_close(fsp, delete_on_close,
5215 &conn->server_info->utok)) {
5216 return NT_STATUS_ACCESS_DENIED;
5218 return NT_STATUS_OK;
5221 /****************************************************************************
5222 Deal with SMB_FILE_POSITION_INFORMATION.
5223 ****************************************************************************/
5225 static NTSTATUS smb_file_position_information(connection_struct *conn,
5230 uint64_t position_information;
5232 if (total_data < 8) {
5233 return NT_STATUS_INVALID_PARAMETER;
5237 /* Ignore on pathname based set. */
5238 return NT_STATUS_OK;
5241 position_information = (uint64_t)IVAL(pdata,0);
5242 #ifdef LARGE_SMB_OFF_T
5243 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5244 #else /* LARGE_SMB_OFF_T */
5245 if (IVAL(pdata,4) != 0) {
5246 /* more than 32 bits? */
5247 return NT_STATUS_INVALID_PARAMETER;
5249 #endif /* LARGE_SMB_OFF_T */
5251 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5252 fsp->fsp_name, (double)position_information ));
5253 fsp->fh->position_information = position_information;
5254 return NT_STATUS_OK;
5257 /****************************************************************************
5258 Deal with SMB_FILE_MODE_INFORMATION.
5259 ****************************************************************************/
5261 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5267 if (total_data < 4) {
5268 return NT_STATUS_INVALID_PARAMETER;
5270 mode = IVAL(pdata,0);
5271 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5272 return NT_STATUS_INVALID_PARAMETER;
5274 return NT_STATUS_OK;
5277 /****************************************************************************
5278 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5279 ****************************************************************************/
5281 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5282 struct smb_request *req,
5287 char *link_target = NULL;
5288 const char *newname = fname;
5289 NTSTATUS status = NT_STATUS_OK;
5290 TALLOC_CTX *ctx = talloc_tos();
5292 /* Set a symbolic link. */
5293 /* Don't allow this if follow links is false. */
5295 if (total_data == 0) {
5296 return NT_STATUS_INVALID_PARAMETER;
5299 if (!lp_symlinks(SNUM(conn))) {
5300 return NT_STATUS_ACCESS_DENIED;
5303 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5304 total_data, STR_TERMINATE);
5307 return NT_STATUS_INVALID_PARAMETER;
5310 /* !widelinks forces the target path to be within the share. */
5311 /* This means we can interpret the target as a pathname. */
5312 if (!lp_widelinks(SNUM(conn))) {
5313 char *rel_name = NULL;
5314 char *last_dirp = NULL;
5316 if (*link_target == '/') {
5317 /* No absolute paths allowed. */
5318 return NT_STATUS_ACCESS_DENIED;
5320 rel_name = talloc_strdup(ctx,newname);
5322 return NT_STATUS_NO_MEMORY;
5324 last_dirp = strrchr_m(rel_name, '/');
5326 last_dirp[1] = '\0';
5328 rel_name = talloc_strdup(ctx,"./");
5330 return NT_STATUS_NO_MEMORY;
5333 rel_name = talloc_asprintf_append(rel_name,
5337 return NT_STATUS_NO_MEMORY;
5340 status = check_name(conn, rel_name);
5341 if (!NT_STATUS_IS_OK(status)) {
5346 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5347 newname, link_target ));
5349 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5350 return map_nt_error_from_unix(errno);
5353 return NT_STATUS_OK;
5356 /****************************************************************************
5357 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5358 ****************************************************************************/
5360 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5361 struct smb_request *req,
5362 const char *pdata, int total_data,
5365 char *oldname = NULL;
5366 TALLOC_CTX *ctx = talloc_tos();
5367 NTSTATUS status = NT_STATUS_OK;
5369 /* Set a hard link. */
5370 if (total_data == 0) {
5371 return NT_STATUS_INVALID_PARAMETER;
5374 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5375 total_data, STR_TERMINATE, &status);
5376 if (!NT_STATUS_IS_OK(status)) {
5380 status = resolve_dfspath(ctx, conn,
5381 req->flags2 & FLAGS2_DFS_PATHNAMES,
5384 if (!NT_STATUS_IS_OK(status)) {
5388 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5391 return hardlink_internals(ctx, conn, oldname, fname);
5394 /****************************************************************************
5395 Deal with SMB_FILE_RENAME_INFORMATION.
5396 ****************************************************************************/
5398 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5399 struct smb_request *req,
5408 char *newname = NULL;
5409 char *base_name = NULL;
5410 struct smb_filename *smb_fname = NULL;
5411 bool dest_has_wcard = False;
5412 NTSTATUS status = NT_STATUS_OK;
5414 TALLOC_CTX *ctx = talloc_tos();
5416 if (total_data < 13) {
5417 return NT_STATUS_INVALID_PARAMETER;
5420 overwrite = (CVAL(pdata,0) ? True : False);
5421 root_fid = IVAL(pdata,4);
5422 len = IVAL(pdata,8);
5424 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5425 return NT_STATUS_INVALID_PARAMETER;
5428 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5431 if (!NT_STATUS_IS_OK(status)) {
5435 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5438 status = resolve_dfspath_wcard(ctx, conn,
5439 req->flags2 & FLAGS2_DFS_PATHNAMES,
5443 if (!NT_STATUS_IS_OK(status)) {
5447 /* Check the new name has no '/' characters. */
5448 if (strchr_m(newname, '/')) {
5449 return NT_STATUS_NOT_SUPPORTED;
5452 if (fsp && fsp->base_fsp) {
5453 /* newname must be a stream name. */
5454 if (newname[0] != ':') {
5455 return NT_STATUS_NOT_SUPPORTED;
5457 base_name = talloc_asprintf(ctx, "%s%s",
5458 fsp->base_fsp->fsp_name,
5461 return NT_STATUS_NO_MEMORY;
5464 /* newname must *not* be a stream name. */
5465 if (is_ntfs_stream_name(newname)) {
5466 return NT_STATUS_NOT_SUPPORTED;
5469 /* Create the base directory. */
5470 base_name = talloc_strdup(ctx, fname);
5472 return NT_STATUS_NO_MEMORY;
5474 p = strrchr_m(base_name, '/');
5478 base_name = talloc_strdup(ctx, "./");
5480 return NT_STATUS_NO_MEMORY;
5483 /* Append the new name. */
5484 base_name = talloc_asprintf_append(base_name,
5488 return NT_STATUS_NO_MEMORY;
5491 status = unix_convert(ctx, conn, newname, &smb_fname,
5494 /* If an error we expect this to be
5495 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5497 if (!NT_STATUS_IS_OK(status)
5498 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5505 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5506 fsp->fnum, fsp->fsp_name, base_name ));
5507 status = rename_internals_fsp(conn, fsp, base_name,
5509 smb_fname->original_lcomp : NULL,
5512 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5513 fname, base_name ));
5514 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5515 overwrite, False, dest_has_wcard,
5516 FILE_WRITE_ATTRIBUTES);
5519 TALLOC_FREE(smb_fname);
5523 /****************************************************************************
5524 Deal with SMB_SET_POSIX_ACL.
5525 ****************************************************************************/
5527 #if defined(HAVE_POSIX_ACLS)
5528 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5533 SMB_STRUCT_STAT *psbuf)
5535 uint16 posix_acl_version;
5536 uint16 num_file_acls;
5537 uint16 num_def_acls;
5538 bool valid_file_acls = True;
5539 bool valid_def_acls = True;
5541 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5542 return NT_STATUS_INVALID_PARAMETER;
5544 posix_acl_version = SVAL(pdata,0);
5545 num_file_acls = SVAL(pdata,2);
5546 num_def_acls = SVAL(pdata,4);
5548 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5549 valid_file_acls = False;
5553 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5554 valid_def_acls = False;
5558 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5559 return NT_STATUS_INVALID_PARAMETER;
5562 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5563 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5564 return NT_STATUS_INVALID_PARAMETER;
5567 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5568 fname ? fname : fsp->fsp_name,
5569 (unsigned int)num_file_acls,
5570 (unsigned int)num_def_acls));
5572 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5573 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5574 return map_nt_error_from_unix(errno);
5577 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5578 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5579 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5580 return map_nt_error_from_unix(errno);
5582 return NT_STATUS_OK;
5586 /****************************************************************************
5587 Deal with SMB_SET_POSIX_LOCK.
5588 ****************************************************************************/
5590 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5591 struct smb_request *req,
5599 bool blocking_lock = False;
5600 enum brl_type lock_type;
5602 NTSTATUS status = NT_STATUS_OK;
5604 if (fsp == NULL || fsp->fh->fd == -1) {
5605 return NT_STATUS_INVALID_HANDLE;
5608 if (total_data != POSIX_LOCK_DATA_SIZE) {
5609 return NT_STATUS_INVALID_PARAMETER;
5612 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5613 case POSIX_LOCK_TYPE_READ:
5614 lock_type = READ_LOCK;
5616 case POSIX_LOCK_TYPE_WRITE:
5617 /* Return the right POSIX-mappable error code for files opened read-only. */
5618 if (!fsp->can_write) {
5619 return NT_STATUS_INVALID_HANDLE;
5621 lock_type = WRITE_LOCK;
5623 case POSIX_LOCK_TYPE_UNLOCK:
5624 lock_type = UNLOCK_LOCK;
5627 return NT_STATUS_INVALID_PARAMETER;
5630 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5631 blocking_lock = False;
5632 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5633 blocking_lock = True;
5635 return NT_STATUS_INVALID_PARAMETER;
5638 if (!lp_blocking_locks(SNUM(conn))) {
5639 blocking_lock = False;
5642 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5643 #if defined(HAVE_LONGLONG)
5644 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5645 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5646 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5647 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5648 #else /* HAVE_LONGLONG */
5649 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5650 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5651 #endif /* HAVE_LONGLONG */
5653 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5654 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5656 (unsigned int)lock_type,
5657 (unsigned int)lock_pid,
5661 if (lock_type == UNLOCK_LOCK) {
5662 status = do_unlock(smbd_messaging_context(),
5669 uint32 block_smbpid;
5671 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5683 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5685 * A blocking lock was requested. Package up
5686 * this smb into a queued request and push it
5687 * onto the blocking lock queue.
5689 if(push_blocking_lock_request(br_lck,
5692 -1, /* infinite timeout. */
5700 TALLOC_FREE(br_lck);
5704 TALLOC_FREE(br_lck);
5710 /****************************************************************************
5711 Deal with SMB_INFO_STANDARD.
5712 ****************************************************************************/
5714 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5719 const SMB_STRUCT_STAT *psbuf)
5721 struct smb_file_time ft;
5724 if (total_data < 12) {
5725 return NT_STATUS_INVALID_PARAMETER;
5729 ft.create_time = interpret_long_date(pdata);
5732 ft.atime = interpret_long_date(pdata + 8);
5735 ft.mtime = interpret_long_date(pdata + 16);
5737 DEBUG(10,("smb_set_info_standard: file %s\n",
5738 fname ? fname : fsp->fsp_name ));
5740 return smb_set_file_time(conn,
5748 /****************************************************************************
5749 Deal with SMB_SET_FILE_BASIC_INFO.
5750 ****************************************************************************/
5752 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5757 SMB_STRUCT_STAT *psbuf)
5759 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5760 struct timespec write_time;
5761 struct timespec changed_time;
5762 struct smb_file_time ft;
5764 NTSTATUS status = NT_STATUS_OK;
5765 bool setting_write_time = true;
5769 if (total_data < 36) {
5770 return NT_STATUS_INVALID_PARAMETER;
5773 /* Set the attributes */
5774 dosmode = IVAL(pdata,32);
5775 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5776 if (!NT_STATUS_IS_OK(status)) {
5781 ft.atime = interpret_long_date(pdata+8);
5783 write_time = interpret_long_date(pdata+16);
5784 changed_time = interpret_long_date(pdata+24);
5787 ft.mtime = timespec_min(&write_time, &changed_time);
5790 ft.create_time = interpret_long_date(pdata);
5792 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5793 !null_timespec(write_time)) {
5794 ft.mtime = write_time;
5797 /* Prefer a defined time to an undefined one. */
5798 if (null_timespec(ft.mtime)) {
5799 if (null_timespec(write_time)) {
5800 ft.mtime = changed_time;
5801 setting_write_time = false;
5803 ft.mtime = write_time;
5807 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5808 fname ? fname : fsp->fsp_name ));
5810 return smb_set_file_time(conn,
5815 setting_write_time);
5818 /****************************************************************************
5819 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5820 ****************************************************************************/
5822 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5823 struct smb_request *req,
5828 SMB_STRUCT_STAT *psbuf)
5830 uint64_t allocation_size = 0;
5831 NTSTATUS status = NT_STATUS_OK;
5832 files_struct *new_fsp = NULL;
5834 if (!VALID_STAT(*psbuf)) {
5835 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5838 if (total_data < 8) {
5839 return NT_STATUS_INVALID_PARAMETER;
5842 allocation_size = (uint64_t)IVAL(pdata,0);
5843 #ifdef LARGE_SMB_OFF_T
5844 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5845 #else /* LARGE_SMB_OFF_T */
5846 if (IVAL(pdata,4) != 0) {
5847 /* more than 32 bits? */
5848 return NT_STATUS_INVALID_PARAMETER;
5850 #endif /* LARGE_SMB_OFF_T */
5852 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5853 fname, (double)allocation_size ));
5855 if (allocation_size) {
5856 allocation_size = smb_roundup(conn, allocation_size);
5859 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5860 fname, (double)allocation_size ));
5862 if (fsp && fsp->fh->fd != -1) {
5863 /* Open file handle. */
5864 /* Only change if needed. */
5865 if (allocation_size != get_file_size_stat(psbuf)) {
5866 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5867 return map_nt_error_from_unix(errno);
5870 /* But always update the time. */
5872 * This is equivalent to a write. Ensure it's seen immediately
5873 * if there are no pending writes.
5875 trigger_write_time_update_immediate(fsp);
5876 return NT_STATUS_OK;
5879 /* Pathname or stat or directory file. */
5881 status = SMB_VFS_CREATE_FILE(
5884 0, /* root_dir_fid */
5886 0, /* create_file_flags */
5887 FILE_WRITE_DATA, /* access_mask */
5888 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5890 FILE_OPEN, /* create_disposition*/
5891 0, /* create_options */
5892 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5893 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5894 0, /* allocation_size */
5897 &new_fsp, /* result */
5901 if (!NT_STATUS_IS_OK(status)) {
5902 /* NB. We check for open_was_deferred in the caller. */
5906 /* Only change if needed. */
5907 if (allocation_size != get_file_size_stat(psbuf)) {
5908 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5909 status = map_nt_error_from_unix(errno);
5910 close_file(req, new_fsp, NORMAL_CLOSE);
5915 /* Changing the allocation size should set the last mod time. */
5917 * This is equivalent to a write. Ensure it's seen immediately
5918 * if there are no pending writes.
5920 trigger_write_time_update_immediate(new_fsp);
5922 close_file(req, new_fsp, NORMAL_CLOSE);
5923 return NT_STATUS_OK;
5926 /****************************************************************************
5927 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5928 ****************************************************************************/
5930 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5931 struct smb_request *req,
5936 SMB_STRUCT_STAT *psbuf)
5940 if (total_data < 8) {
5941 return NT_STATUS_INVALID_PARAMETER;
5944 size = IVAL(pdata,0);
5945 #ifdef LARGE_SMB_OFF_T
5946 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5947 #else /* LARGE_SMB_OFF_T */
5948 if (IVAL(pdata,4) != 0) {
5949 /* more than 32 bits? */
5950 return NT_STATUS_INVALID_PARAMETER;
5952 #endif /* LARGE_SMB_OFF_T */
5953 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5954 "file %s to %.0f\n", fname, (double)size ));
5956 return smb_set_file_size(conn, req,
5963 /****************************************************************************
5964 Allow a UNIX info mknod.
5965 ****************************************************************************/
5967 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5971 SMB_STRUCT_STAT *psbuf)
5973 uint32 file_type = IVAL(pdata,56);
5974 #if defined(HAVE_MAKEDEV)
5975 uint32 dev_major = IVAL(pdata,60);
5976 uint32 dev_minor = IVAL(pdata,68);
5978 SMB_DEV_T dev = (SMB_DEV_T)0;
5979 uint32 raw_unixmode = IVAL(pdata,84);
5983 if (total_data < 100) {
5984 return NT_STATUS_INVALID_PARAMETER;
5987 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5988 if (!NT_STATUS_IS_OK(status)) {
5992 #if defined(HAVE_MAKEDEV)
5993 dev = makedev(dev_major, dev_minor);
5996 switch (file_type) {
5997 #if defined(S_IFIFO)
5998 case UNIX_TYPE_FIFO:
5999 unixmode |= S_IFIFO;
6002 #if defined(S_IFSOCK)
6003 case UNIX_TYPE_SOCKET:
6004 unixmode |= S_IFSOCK;
6007 #if defined(S_IFCHR)
6008 case UNIX_TYPE_CHARDEV:
6009 unixmode |= S_IFCHR;
6012 #if defined(S_IFBLK)
6013 case UNIX_TYPE_BLKDEV:
6014 unixmode |= S_IFBLK;
6018 return NT_STATUS_INVALID_PARAMETER;
6021 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6022 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6024 /* Ok - do the mknod. */
6025 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6026 return map_nt_error_from_unix(errno);
6029 /* If any of the other "set" calls fail we
6030 * don't want to end up with a half-constructed mknod.
6033 if (lp_inherit_perms(SNUM(conn))) {
6035 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6036 return NT_STATUS_NO_MEMORY;
6038 inherit_access_posix_acl(conn, parent, fname, unixmode);
6039 TALLOC_FREE(parent);
6042 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6043 status = map_nt_error_from_unix(errno);
6044 SMB_VFS_UNLINK(conn,fname);
6047 return NT_STATUS_OK;
6050 /****************************************************************************
6051 Deal with SMB_SET_FILE_UNIX_BASIC.
6052 ****************************************************************************/
6054 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6055 struct smb_request *req,
6060 SMB_STRUCT_STAT *psbuf)
6062 struct smb_file_time ft;
6063 uint32 raw_unixmode;
6066 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6067 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6068 NTSTATUS status = NT_STATUS_OK;
6069 bool delete_on_fail = False;
6070 enum perm_type ptype;
6074 if (total_data < 100) {
6075 return NT_STATUS_INVALID_PARAMETER;
6078 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6079 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6080 size=IVAL(pdata,0); /* first 8 Bytes are size */
6081 #ifdef LARGE_SMB_OFF_T
6082 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6083 #else /* LARGE_SMB_OFF_T */
6084 if (IVAL(pdata,4) != 0) {
6085 /* more than 32 bits? */
6086 return NT_STATUS_INVALID_PARAMETER;
6088 #endif /* LARGE_SMB_OFF_T */
6091 ft.atime = interpret_long_date(pdata+24); /* access_time */
6092 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6093 set_owner = (uid_t)IVAL(pdata,40);
6094 set_grp = (gid_t)IVAL(pdata,48);
6095 raw_unixmode = IVAL(pdata,84);
6097 if (VALID_STAT(*psbuf)) {
6098 if (S_ISDIR(psbuf->st_ex_mode)) {
6099 ptype = PERM_EXISTING_DIR;
6101 ptype = PERM_EXISTING_FILE;
6104 ptype = PERM_NEW_FILE;
6107 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6108 if (!NT_STATUS_IS_OK(status)) {
6112 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6113 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6114 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6116 if (!VALID_STAT(*psbuf)) {
6118 * The only valid use of this is to create character and block
6119 * devices, and named pipes. This is deprecated (IMHO) and
6120 * a new info level should be used for mknod. JRA.
6123 status = smb_unix_mknod(conn,
6128 if (!NT_STATUS_IS_OK(status)) {
6132 /* Ensure we don't try and change anything else. */
6133 raw_unixmode = SMB_MODE_NO_CHANGE;
6134 size = get_file_size_stat(psbuf);
6135 ft.atime = psbuf->st_ex_atime;
6136 ft.mtime = psbuf->st_ex_mtime;
6138 * We continue here as we might want to change the
6141 delete_on_fail = True;
6145 /* Horrible backwards compatibility hack as an old server bug
6146 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6150 size = get_file_size_stat(psbuf);
6155 * Deal with the UNIX specific mode set.
6158 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6159 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6160 (unsigned int)unixmode, fname ));
6161 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6162 return map_nt_error_from_unix(errno);
6167 * Deal with the UNIX specific uid set.
6170 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_ex_uid != set_owner)) {
6173 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6174 (unsigned int)set_owner, fname ));
6176 if (S_ISLNK(psbuf->st_ex_mode)) {
6177 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6179 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6183 status = map_nt_error_from_unix(errno);
6184 if (delete_on_fail) {
6185 SMB_VFS_UNLINK(conn,fname);
6192 * Deal with the UNIX specific gid set.
6195 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_ex_gid != set_grp)) {
6196 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6197 (unsigned int)set_owner, fname ));
6198 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6199 status = map_nt_error_from_unix(errno);
6200 if (delete_on_fail) {
6201 SMB_VFS_UNLINK(conn,fname);
6207 /* Deal with any size changes. */
6209 status = smb_set_file_size(conn, req,
6214 if (!NT_STATUS_IS_OK(status)) {
6218 /* Deal with any time changes. */
6220 return smb_set_file_time(conn,
6228 /****************************************************************************
6229 Deal with SMB_SET_FILE_UNIX_INFO2.
6230 ****************************************************************************/
6232 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6233 struct smb_request *req,
6238 SMB_STRUCT_STAT *psbuf)
6244 if (total_data < 116) {
6245 return NT_STATUS_INVALID_PARAMETER;
6248 /* Start by setting all the fields that are common between UNIX_BASIC
6251 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6253 if (!NT_STATUS_IS_OK(status)) {
6257 smb_fflags = IVAL(pdata, 108);
6258 smb_fmask = IVAL(pdata, 112);
6260 /* NB: We should only attempt to alter the file flags if the client
6261 * sends a non-zero mask.
6263 if (smb_fmask != 0) {
6264 int stat_fflags = 0;
6266 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6268 /* Client asked to alter a flag we don't understand. */
6269 return NT_STATUS_INVALID_PARAMETER;
6272 if (fsp && fsp->fh->fd != -1) {
6273 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6274 return NT_STATUS_NOT_SUPPORTED;
6276 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6277 return map_nt_error_from_unix(errno);
6282 /* XXX: need to add support for changing the create_time here. You
6283 * can do this for paths on Darwin with setattrlist(2). The right way
6284 * to hook this up is probably by extending the VFS utimes interface.
6287 return NT_STATUS_OK;
6290 /****************************************************************************
6291 Create a directory with POSIX semantics.
6292 ****************************************************************************/
6294 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6295 struct smb_request *req,
6299 SMB_STRUCT_STAT *psbuf,
6300 int *pdata_return_size)
6302 NTSTATUS status = NT_STATUS_OK;
6303 uint32 raw_unixmode = 0;
6304 uint32 mod_unixmode = 0;
6305 mode_t unixmode = (mode_t)0;
6306 files_struct *fsp = NULL;
6307 uint16 info_level_return = 0;
6309 char *pdata = *ppdata;
6311 if (total_data < 18) {
6312 return NT_STATUS_INVALID_PARAMETER;
6315 raw_unixmode = IVAL(pdata,8);
6316 /* Next 4 bytes are not yet defined. */
6318 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6319 if (!NT_STATUS_IS_OK(status)) {
6323 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6325 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6326 fname, (unsigned int)unixmode ));
6328 status = SMB_VFS_CREATE_FILE(
6331 0, /* root_dir_fid */
6333 0, /* create_file_flags */
6334 FILE_READ_ATTRIBUTES, /* access_mask */
6335 FILE_SHARE_NONE, /* share_access */
6336 FILE_CREATE, /* create_disposition*/
6337 FILE_DIRECTORY_FILE, /* create_options */
6338 mod_unixmode, /* file_attributes */
6339 0, /* oplock_request */
6340 0, /* allocation_size */
6347 if (NT_STATUS_IS_OK(status)) {
6348 close_file(req, fsp, NORMAL_CLOSE);
6351 info_level_return = SVAL(pdata,16);
6353 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6354 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6355 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6356 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6358 *pdata_return_size = 12;
6361 /* Realloc the data size */
6362 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6363 if (*ppdata == NULL) {
6364 *pdata_return_size = 0;
6365 return NT_STATUS_NO_MEMORY;
6369 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6370 SSVAL(pdata,2,0); /* No fnum. */
6371 SIVAL(pdata,4,info); /* Was directory created. */
6373 switch (info_level_return) {
6374 case SMB_QUERY_FILE_UNIX_BASIC:
6375 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6376 SSVAL(pdata,10,0); /* Padding. */
6377 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6379 case SMB_QUERY_FILE_UNIX_INFO2:
6380 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6381 SSVAL(pdata,10,0); /* Padding. */
6382 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6385 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6386 SSVAL(pdata,10,0); /* Padding. */
6393 /****************************************************************************
6394 Open/Create a file with POSIX semantics.
6395 ****************************************************************************/
6397 static NTSTATUS smb_posix_open(connection_struct *conn,
6398 struct smb_request *req,
6402 SMB_STRUCT_STAT *psbuf,
6403 int *pdata_return_size)
6405 bool extended_oplock_granted = False;
6406 char *pdata = *ppdata;
6408 uint32 wire_open_mode = 0;
6409 uint32 raw_unixmode = 0;
6410 uint32 mod_unixmode = 0;
6411 uint32 create_disp = 0;
6412 uint32 access_mask = 0;
6413 uint32 create_options = 0;
6414 NTSTATUS status = NT_STATUS_OK;
6415 mode_t unixmode = (mode_t)0;
6416 files_struct *fsp = NULL;
6417 int oplock_request = 0;
6419 uint16 info_level_return = 0;
6421 if (total_data < 18) {
6422 return NT_STATUS_INVALID_PARAMETER;
6425 flags = IVAL(pdata,0);
6426 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6427 if (oplock_request) {
6428 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6431 wire_open_mode = IVAL(pdata,4);
6433 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6434 return smb_posix_mkdir(conn, req,
6442 switch (wire_open_mode & SMB_ACCMODE) {
6444 access_mask = FILE_READ_DATA;
6447 access_mask = FILE_WRITE_DATA;
6450 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6453 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6454 (unsigned int)wire_open_mode ));
6455 return NT_STATUS_INVALID_PARAMETER;
6458 wire_open_mode &= ~SMB_ACCMODE;
6460 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6461 create_disp = FILE_CREATE;
6462 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6463 create_disp = FILE_OVERWRITE_IF;
6464 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6465 create_disp = FILE_OPEN_IF;
6466 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6467 create_disp = FILE_OPEN;
6469 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6470 (unsigned int)wire_open_mode ));
6471 return NT_STATUS_INVALID_PARAMETER;
6474 raw_unixmode = IVAL(pdata,8);
6475 /* Next 4 bytes are not yet defined. */
6477 status = unix_perms_from_wire(conn,
6480 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6483 if (!NT_STATUS_IS_OK(status)) {
6487 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6489 if (wire_open_mode & SMB_O_SYNC) {
6490 create_options |= FILE_WRITE_THROUGH;
6492 if (wire_open_mode & SMB_O_APPEND) {
6493 access_mask |= FILE_APPEND_DATA;
6495 if (wire_open_mode & SMB_O_DIRECT) {
6496 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6499 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6501 (unsigned int)wire_open_mode,
6502 (unsigned int)unixmode ));
6504 status = SMB_VFS_CREATE_FILE(
6507 0, /* root_dir_fid */
6509 0, /* create_file_flags */
6510 access_mask, /* access_mask */
6511 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6513 create_disp, /* create_disposition*/
6514 FILE_NON_DIRECTORY_FILE, /* create_options */
6515 mod_unixmode, /* file_attributes */
6516 oplock_request, /* oplock_request */
6517 0, /* allocation_size */
6524 if (!NT_STATUS_IS_OK(status)) {
6528 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6529 extended_oplock_granted = True;
6532 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6533 extended_oplock_granted = True;
6536 info_level_return = SVAL(pdata,16);
6538 /* Allocate the correct return size. */
6540 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6541 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6542 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6543 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6545 *pdata_return_size = 12;
6548 /* Realloc the data size */
6549 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6550 if (*ppdata == NULL) {
6551 close_file(req, fsp, ERROR_CLOSE);
6552 *pdata_return_size = 0;
6553 return NT_STATUS_NO_MEMORY;
6557 if (extended_oplock_granted) {
6558 if (flags & REQUEST_BATCH_OPLOCK) {
6559 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6561 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6563 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6564 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6566 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6569 SSVAL(pdata,2,fsp->fnum);
6570 SIVAL(pdata,4,info); /* Was file created etc. */
6572 switch (info_level_return) {
6573 case SMB_QUERY_FILE_UNIX_BASIC:
6574 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6575 SSVAL(pdata,10,0); /* padding. */
6576 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6578 case SMB_QUERY_FILE_UNIX_INFO2:
6579 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6580 SSVAL(pdata,10,0); /* padding. */
6581 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6584 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6585 SSVAL(pdata,10,0); /* padding. */
6588 return NT_STATUS_OK;
6591 /****************************************************************************
6592 Delete a file with POSIX semantics.
6593 ****************************************************************************/
6595 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6596 struct smb_request *req,
6600 SMB_STRUCT_STAT *psbuf)
6602 NTSTATUS status = NT_STATUS_OK;
6603 files_struct *fsp = NULL;
6607 int create_options = 0;
6609 struct share_mode_lock *lck = NULL;
6611 if (total_data < 2) {
6612 return NT_STATUS_INVALID_PARAMETER;
6615 flags = SVAL(pdata,0);
6617 if (!VALID_STAT(*psbuf)) {
6618 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6621 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6622 !VALID_STAT_OF_DIR(*psbuf)) {
6623 return NT_STATUS_NOT_A_DIRECTORY;
6626 DEBUG(10,("smb_posix_unlink: %s %s\n",
6627 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6630 if (VALID_STAT_OF_DIR(*psbuf)) {
6631 create_options |= FILE_DIRECTORY_FILE;
6634 status = SMB_VFS_CREATE_FILE(
6637 0, /* root_dir_fid */
6639 0, /* create_file_flags */
6640 DELETE_ACCESS, /* access_mask */
6641 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6643 FILE_OPEN, /* create_disposition*/
6644 create_options, /* create_options */
6645 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6646 0, /* oplock_request */
6647 0, /* allocation_size */
6654 if (!NT_STATUS_IS_OK(status)) {
6659 * Don't lie to client. If we can't really delete due to
6660 * non-POSIX opens return SHARING_VIOLATION.
6663 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6666 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6667 "lock for file %s\n", fsp->fsp_name));
6668 close_file(req, fsp, NORMAL_CLOSE);
6669 return NT_STATUS_INVALID_PARAMETER;
6673 * See if others still have the file open. If this is the case, then
6674 * don't delete. If all opens are POSIX delete we can set the delete
6675 * on close disposition.
6677 for (i=0; i<lck->num_share_modes; i++) {
6678 struct share_mode_entry *e = &lck->share_modes[i];
6679 if (is_valid_share_mode_entry(e)) {
6680 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6683 /* Fail with sharing violation. */
6684 close_file(req, fsp, NORMAL_CLOSE);
6686 return NT_STATUS_SHARING_VIOLATION;
6691 * Set the delete on close.
6693 status = smb_set_file_disposition_info(conn,
6700 if (!NT_STATUS_IS_OK(status)) {
6701 close_file(req, fsp, NORMAL_CLOSE);
6706 return close_file(req, fsp, NORMAL_CLOSE);
6709 /****************************************************************************
6710 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6711 ****************************************************************************/
6713 static void call_trans2setfilepathinfo(connection_struct *conn,
6714 struct smb_request *req,
6715 unsigned int tran_call,
6716 char **pparams, int total_params,
6717 char **ppdata, int total_data,
6718 unsigned int max_data_bytes)
6720 char *params = *pparams;
6721 char *pdata = *ppdata;
6723 SMB_STRUCT_STAT sbuf;
6725 struct smb_filename *smb_fname = NULL;
6726 files_struct *fsp = NULL;
6727 NTSTATUS status = NT_STATUS_OK;
6728 int data_return_size = 0;
6729 TALLOC_CTX *ctx = talloc_tos();
6732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6738 if (tran_call == TRANSACT2_SETFILEINFO) {
6739 if (total_params < 4) {
6740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6744 fsp = file_fsp(req, SVAL(params,0));
6745 /* Basic check for non-null fsp. */
6746 if (!check_fsp_open(conn, req, fsp)) {
6749 info_level = SVAL(params,2);
6751 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6753 reply_nterror(req, NT_STATUS_NO_MEMORY);
6757 if(fsp->is_directory || fsp->fh->fd == -1) {
6759 * This is actually a SETFILEINFO on a directory
6760 * handle (returned from an NT SMB). NT5.0 seems
6761 * to do this call. JRA.
6763 if (INFO_LEVEL_IS_UNIX(info_level)) {
6764 /* Always do lstat for UNIX calls. */
6765 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6766 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6767 reply_unixerror(req,ERRDOS,ERRbadpath);
6771 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6772 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6773 reply_unixerror(req,ERRDOS,ERRbadpath);
6777 } else if (fsp->print_file) {
6779 * Doing a DELETE_ON_CLOSE should cancel a print job.
6781 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6782 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6784 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6787 send_trans2_replies(conn, req, params, 2,
6792 reply_unixerror(req, ERRDOS, ERRbadpath);
6797 * Original code - this is an open file.
6799 if (!check_fsp(conn, req, fsp)) {
6803 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6804 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6805 reply_unixerror(req, ERRDOS, ERRbadfid);
6811 if (total_params < 7) {
6812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6816 info_level = SVAL(params,0);
6817 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6818 total_params - 6, STR_TERMINATE,
6820 if (!NT_STATUS_IS_OK(status)) {
6821 reply_nterror(req, status);
6825 status = resolve_dfspath(ctx, conn,
6826 req->flags2 & FLAGS2_DFS_PATHNAMES,
6829 if (!NT_STATUS_IS_OK(status)) {
6830 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6831 reply_botherror(req,
6832 NT_STATUS_PATH_NOT_COVERED,
6833 ERRSRV, ERRbadpath);
6836 reply_nterror(req, status);
6840 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
6841 if (!NT_STATUS_IS_OK(status)) {
6842 reply_nterror(req, status);
6845 sbuf = smb_fname->st;
6847 status = get_full_smb_filename(ctx, smb_fname, &fname);
6848 TALLOC_FREE(smb_fname);
6849 if (!NT_STATUS_IS_OK(status)) {
6850 reply_nterror(req, status);
6854 status = check_name(conn, fname);
6855 if (!NT_STATUS_IS_OK(status)) {
6856 reply_nterror(req, status);
6860 if (INFO_LEVEL_IS_UNIX(info_level)) {
6862 * For CIFS UNIX extensions the target name may not exist.
6865 /* Always do lstat for UNIX calls. */
6866 SMB_VFS_LSTAT(conn,fname,&sbuf);
6868 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6869 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6870 reply_unixerror(req, ERRDOS, ERRbadpath);
6875 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6876 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6880 if (!CAN_WRITE(conn)) {
6881 /* Allow POSIX opens. The open path will deny
6882 * any non-readonly opens. */
6883 if (info_level != SMB_POSIX_PATH_OPEN) {
6884 reply_doserror(req, ERRSRV, ERRaccess);
6889 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6890 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6892 /* Realloc the parameter size */
6893 *pparams = (char *)SMB_REALLOC(*pparams,2);
6894 if (*pparams == NULL) {
6895 reply_nterror(req, NT_STATUS_NO_MEMORY);
6902 switch (info_level) {
6904 case SMB_INFO_STANDARD:
6906 status = smb_set_info_standard(conn,
6915 case SMB_INFO_SET_EA:
6917 status = smb_info_set_ea(conn,
6925 case SMB_SET_FILE_BASIC_INFO:
6926 case SMB_FILE_BASIC_INFORMATION:
6928 status = smb_set_file_basic_info(conn,
6937 case SMB_FILE_ALLOCATION_INFORMATION:
6938 case SMB_SET_FILE_ALLOCATION_INFO:
6940 status = smb_set_file_allocation_info(conn, req,
6949 case SMB_FILE_END_OF_FILE_INFORMATION:
6950 case SMB_SET_FILE_END_OF_FILE_INFO:
6952 status = smb_set_file_end_of_file_info(conn, req,
6961 case SMB_FILE_DISPOSITION_INFORMATION:
6962 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6965 /* JRA - We used to just ignore this on a path ?
6966 * Shouldn't this be invalid level on a pathname
6969 if (tran_call != TRANSACT2_SETFILEINFO) {
6970 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6973 status = smb_set_file_disposition_info(conn,
6982 case SMB_FILE_POSITION_INFORMATION:
6984 status = smb_file_position_information(conn,
6991 /* From tridge Samba4 :
6992 * MODE_INFORMATION in setfileinfo (I have no
6993 * idea what "mode information" on a file is - it takes a value of 0,
6994 * 2, 4 or 6. What could it be?).
6997 case SMB_FILE_MODE_INFORMATION:
6999 status = smb_file_mode_information(conn,
7006 * CIFS UNIX extensions.
7009 case SMB_SET_FILE_UNIX_BASIC:
7011 status = smb_set_file_unix_basic(conn, req,
7020 case SMB_SET_FILE_UNIX_INFO2:
7022 status = smb_set_file_unix_info2(conn, req,
7031 case SMB_SET_FILE_UNIX_LINK:
7033 if (tran_call != TRANSACT2_SETPATHINFO) {
7034 /* We must have a pathname for this. */
7035 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7038 status = smb_set_file_unix_link(conn, req, pdata,
7043 case SMB_SET_FILE_UNIX_HLINK:
7045 if (tran_call != TRANSACT2_SETPATHINFO) {
7046 /* We must have a pathname for this. */
7047 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7050 status = smb_set_file_unix_hlink(conn, req,
7056 case SMB_FILE_RENAME_INFORMATION:
7058 status = smb_file_rename_information(conn, req,
7064 #if defined(HAVE_POSIX_ACLS)
7065 case SMB_SET_POSIX_ACL:
7067 status = smb_set_posix_acl(conn,
7077 case SMB_SET_POSIX_LOCK:
7079 if (tran_call != TRANSACT2_SETFILEINFO) {
7080 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7083 status = smb_set_posix_lock(conn, req,
7084 pdata, total_data, fsp);
7088 case SMB_POSIX_PATH_OPEN:
7090 if (tran_call != TRANSACT2_SETPATHINFO) {
7091 /* We must have a pathname for this. */
7092 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7096 status = smb_posix_open(conn, req,
7105 case SMB_POSIX_PATH_UNLINK:
7107 if (tran_call != TRANSACT2_SETPATHINFO) {
7108 /* We must have a pathname for this. */
7109 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7113 status = smb_posix_unlink(conn, req,
7122 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7126 if (!NT_STATUS_IS_OK(status)) {
7127 if (open_was_deferred(req->mid)) {
7128 /* We have re-scheduled this call. */
7131 if (blocking_lock_was_deferred(req->mid)) {
7132 /* We have re-scheduled this call. */
7135 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7136 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7137 ERRSRV, ERRbadpath);
7140 if (info_level == SMB_POSIX_PATH_OPEN) {
7141 reply_openerror(req, status);
7145 reply_nterror(req, status);
7150 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7156 /****************************************************************************
7157 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7158 ****************************************************************************/
7160 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7161 char **pparams, int total_params,
7162 char **ppdata, int total_data,
7163 unsigned int max_data_bytes)
7165 struct smb_filename *smb_dname = NULL;
7166 char *params = *pparams;
7167 char *pdata = *ppdata;
7168 char *directory = NULL;
7169 NTSTATUS status = NT_STATUS_OK;
7170 struct ea_list *ea_list = NULL;
7171 TALLOC_CTX *ctx = talloc_tos();
7173 if (!CAN_WRITE(conn)) {
7174 reply_doserror(req, ERRSRV, ERRaccess);
7178 if (total_params < 5) {
7179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7183 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7184 total_params - 4, STR_TERMINATE,
7186 if (!NT_STATUS_IS_OK(status)) {
7187 reply_nterror(req, status);
7191 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7193 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
7194 if (!NT_STATUS_IS_OK(status)) {
7195 reply_nterror(req, status);
7199 status = get_full_smb_filename(ctx, smb_dname, &directory);
7200 if (!NT_STATUS_IS_OK(status)) {
7201 reply_nterror(req, status);
7205 status = check_name(conn, directory);
7206 if (!NT_STATUS_IS_OK(status)) {
7207 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7208 reply_nterror(req, status);
7212 /* Any data in this call is an EA list. */
7213 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7214 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7219 * OS/2 workplace shell seems to send SET_EA requests of "null"
7220 * length (4 bytes containing IVAL 4).
7221 * They seem to have no effect. Bug #3212. JRA.
7224 if (total_data != 4) {
7225 if (total_data < 10) {
7226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7230 if (IVAL(pdata,0) > total_data) {
7231 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7232 IVAL(pdata,0), (unsigned int)total_data));
7233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7237 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7244 /* If total_data == 4 Windows doesn't care what values
7245 * are placed in that field, it just ignores them.
7246 * The System i QNTC IBM SMB client puts bad values here,
7247 * so ignore them. */
7249 status = create_directory(conn, req, directory);
7251 if (!NT_STATUS_IS_OK(status)) {
7252 reply_nterror(req, status);
7256 /* Try and set any given EA. */
7258 status = set_ea(conn, NULL, directory, ea_list);
7259 if (!NT_STATUS_IS_OK(status)) {
7260 reply_nterror(req, status);
7265 /* Realloc the parameter and data sizes */
7266 *pparams = (char *)SMB_REALLOC(*pparams,2);
7267 if(*pparams == NULL) {
7268 reply_nterror(req, NT_STATUS_NO_MEMORY);
7275 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7280 /****************************************************************************
7281 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7282 We don't actually do this - we just send a null response.
7283 ****************************************************************************/
7285 static void call_trans2findnotifyfirst(connection_struct *conn,
7286 struct smb_request *req,
7287 char **pparams, int total_params,
7288 char **ppdata, int total_data,
7289 unsigned int max_data_bytes)
7291 char *params = *pparams;
7294 if (total_params < 6) {
7295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7299 info_level = SVAL(params,4);
7300 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7302 switch (info_level) {
7307 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7311 /* Realloc the parameter and data sizes */
7312 *pparams = (char *)SMB_REALLOC(*pparams,6);
7313 if (*pparams == NULL) {
7314 reply_nterror(req, NT_STATUS_NO_MEMORY);
7319 SSVAL(params,0,fnf_handle);
7320 SSVAL(params,2,0); /* No changes */
7321 SSVAL(params,4,0); /* No EA errors */
7328 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7333 /****************************************************************************
7334 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7335 changes). Currently this does nothing.
7336 ****************************************************************************/
7338 static void call_trans2findnotifynext(connection_struct *conn,
7339 struct smb_request *req,
7340 char **pparams, int total_params,
7341 char **ppdata, int total_data,
7342 unsigned int max_data_bytes)
7344 char *params = *pparams;
7346 DEBUG(3,("call_trans2findnotifynext\n"));
7348 /* Realloc the parameter and data sizes */
7349 *pparams = (char *)SMB_REALLOC(*pparams,4);
7350 if (*pparams == NULL) {
7351 reply_nterror(req, NT_STATUS_NO_MEMORY);
7356 SSVAL(params,0,0); /* No changes */
7357 SSVAL(params,2,0); /* No EA errors */
7359 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7364 /****************************************************************************
7365 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7366 ****************************************************************************/
7368 static void call_trans2getdfsreferral(connection_struct *conn,
7369 struct smb_request *req,
7370 char **pparams, int total_params,
7371 char **ppdata, int total_data,
7372 unsigned int max_data_bytes)
7374 char *params = *pparams;
7375 char *pathname = NULL;
7377 int max_referral_level;
7378 NTSTATUS status = NT_STATUS_OK;
7379 TALLOC_CTX *ctx = talloc_tos();
7381 DEBUG(10,("call_trans2getdfsreferral\n"));
7383 if (total_params < 3) {
7384 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7388 max_referral_level = SVAL(params,0);
7390 if(!lp_host_msdfs()) {
7391 reply_doserror(req, ERRDOS, ERRbadfunc);
7395 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7396 total_params - 2, STR_TERMINATE);
7398 reply_nterror(req, NT_STATUS_NOT_FOUND);
7401 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7402 ppdata,&status)) < 0) {
7403 reply_nterror(req, status);
7407 SSVAL(req->inbuf, smb_flg2,
7408 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7409 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7414 #define LMCAT_SPL 0x53
7415 #define LMFUNC_GETJOBID 0x60
7417 /****************************************************************************
7418 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7419 ****************************************************************************/
7421 static void call_trans2ioctl(connection_struct *conn,
7422 struct smb_request *req,
7423 char **pparams, int total_params,
7424 char **ppdata, int total_data,
7425 unsigned int max_data_bytes)
7427 char *pdata = *ppdata;
7428 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7430 /* check for an invalid fid before proceeding */
7433 reply_doserror(req, ERRDOS, ERRbadfid);
7437 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7438 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7439 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7440 if (*ppdata == NULL) {
7441 reply_nterror(req, NT_STATUS_NO_MEMORY);
7446 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7447 CAN ACCEPT THIS IN UNICODE. JRA. */
7449 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7450 srvstr_push(pdata, req->flags2, pdata + 2,
7451 global_myname(), 15,
7452 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7453 srvstr_push(pdata, req->flags2, pdata+18,
7454 lp_servicename(SNUM(conn)), 13,
7455 STR_ASCII|STR_TERMINATE); /* Service name */
7456 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7461 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7462 reply_doserror(req, ERRSRV, ERRerror);
7465 /****************************************************************************
7466 Reply to a SMBfindclose (stop trans2 directory search).
7467 ****************************************************************************/
7469 void reply_findclose(struct smb_request *req)
7473 START_PROFILE(SMBfindclose);
7476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7477 END_PROFILE(SMBfindclose);
7481 dptr_num = SVALS(req->vwv+0, 0);
7483 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7485 dptr_close(&dptr_num);
7487 reply_outbuf(req, 0, 0);
7489 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7491 END_PROFILE(SMBfindclose);
7495 /****************************************************************************
7496 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7497 ****************************************************************************/
7499 void reply_findnclose(struct smb_request *req)
7503 START_PROFILE(SMBfindnclose);
7506 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7507 END_PROFILE(SMBfindnclose);
7511 dptr_num = SVAL(req->vwv+0, 0);
7513 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7515 /* We never give out valid handles for a
7516 findnotifyfirst - so any dptr_num is ok here.
7519 reply_outbuf(req, 0, 0);
7521 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7523 END_PROFILE(SMBfindnclose);
7527 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7528 struct trans_state *state)
7530 if (Protocol >= PROTOCOL_NT1) {
7531 req->flags2 |= 0x40; /* IS_LONG_NAME */
7532 SSVAL(req->inbuf,smb_flg2,req->flags2);
7535 if (conn->encrypt_level == Required && !req->encrypted) {
7536 if (state->call != TRANSACT2_QFSINFO &&
7537 state->call != TRANSACT2_SETFSINFO) {
7538 DEBUG(0,("handle_trans2: encryption required "
7540 (unsigned int)state->call));
7541 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7546 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7548 /* Now we must call the relevant TRANS2 function */
7549 switch(state->call) {
7550 case TRANSACT2_OPEN:
7552 START_PROFILE(Trans2_open);
7553 call_trans2open(conn, req,
7554 &state->param, state->total_param,
7555 &state->data, state->total_data,
7556 state->max_data_return);
7557 END_PROFILE(Trans2_open);
7561 case TRANSACT2_FINDFIRST:
7563 START_PROFILE(Trans2_findfirst);
7564 call_trans2findfirst(conn, req,
7565 &state->param, state->total_param,
7566 &state->data, state->total_data,
7567 state->max_data_return);
7568 END_PROFILE(Trans2_findfirst);
7572 case TRANSACT2_FINDNEXT:
7574 START_PROFILE(Trans2_findnext);
7575 call_trans2findnext(conn, req,
7576 &state->param, state->total_param,
7577 &state->data, state->total_data,
7578 state->max_data_return);
7579 END_PROFILE(Trans2_findnext);
7583 case TRANSACT2_QFSINFO:
7585 START_PROFILE(Trans2_qfsinfo);
7586 call_trans2qfsinfo(conn, req,
7587 &state->param, state->total_param,
7588 &state->data, state->total_data,
7589 state->max_data_return);
7590 END_PROFILE(Trans2_qfsinfo);
7594 case TRANSACT2_SETFSINFO:
7596 START_PROFILE(Trans2_setfsinfo);
7597 call_trans2setfsinfo(conn, req,
7598 &state->param, state->total_param,
7599 &state->data, state->total_data,
7600 state->max_data_return);
7601 END_PROFILE(Trans2_setfsinfo);
7605 case TRANSACT2_QPATHINFO:
7606 case TRANSACT2_QFILEINFO:
7608 START_PROFILE(Trans2_qpathinfo);
7609 call_trans2qfilepathinfo(conn, req, state->call,
7610 &state->param, state->total_param,
7611 &state->data, state->total_data,
7612 state->max_data_return);
7613 END_PROFILE(Trans2_qpathinfo);
7617 case TRANSACT2_SETPATHINFO:
7618 case TRANSACT2_SETFILEINFO:
7620 START_PROFILE(Trans2_setpathinfo);
7621 call_trans2setfilepathinfo(conn, req, state->call,
7622 &state->param, state->total_param,
7623 &state->data, state->total_data,
7624 state->max_data_return);
7625 END_PROFILE(Trans2_setpathinfo);
7629 case TRANSACT2_FINDNOTIFYFIRST:
7631 START_PROFILE(Trans2_findnotifyfirst);
7632 call_trans2findnotifyfirst(conn, req,
7633 &state->param, state->total_param,
7634 &state->data, state->total_data,
7635 state->max_data_return);
7636 END_PROFILE(Trans2_findnotifyfirst);
7640 case TRANSACT2_FINDNOTIFYNEXT:
7642 START_PROFILE(Trans2_findnotifynext);
7643 call_trans2findnotifynext(conn, req,
7644 &state->param, state->total_param,
7645 &state->data, state->total_data,
7646 state->max_data_return);
7647 END_PROFILE(Trans2_findnotifynext);
7651 case TRANSACT2_MKDIR:
7653 START_PROFILE(Trans2_mkdir);
7654 call_trans2mkdir(conn, req,
7655 &state->param, state->total_param,
7656 &state->data, state->total_data,
7657 state->max_data_return);
7658 END_PROFILE(Trans2_mkdir);
7662 case TRANSACT2_GET_DFS_REFERRAL:
7664 START_PROFILE(Trans2_get_dfs_referral);
7665 call_trans2getdfsreferral(conn, req,
7666 &state->param, state->total_param,
7667 &state->data, state->total_data,
7668 state->max_data_return);
7669 END_PROFILE(Trans2_get_dfs_referral);
7673 case TRANSACT2_IOCTL:
7675 START_PROFILE(Trans2_ioctl);
7676 call_trans2ioctl(conn, req,
7677 &state->param, state->total_param,
7678 &state->data, state->total_data,
7679 state->max_data_return);
7680 END_PROFILE(Trans2_ioctl);
7685 /* Error in request */
7686 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7687 reply_doserror(req, ERRSRV,ERRerror);
7691 /****************************************************************************
7692 Reply to a SMBtrans2.
7693 ****************************************************************************/
7695 void reply_trans2(struct smb_request *req)
7697 connection_struct *conn = req->conn;
7702 unsigned int tran_call;
7703 struct trans_state *state;
7706 START_PROFILE(SMBtrans2);
7708 if (req->wct < 14) {
7709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7710 END_PROFILE(SMBtrans2);
7714 dsoff = SVAL(req->vwv+12, 0);
7715 dscnt = SVAL(req->vwv+11, 0);
7716 psoff = SVAL(req->vwv+10, 0);
7717 pscnt = SVAL(req->vwv+9, 0);
7718 tran_call = SVAL(req->vwv+14, 0);
7720 result = allow_new_trans(conn->pending_trans, req->mid);
7721 if (!NT_STATUS_IS_OK(result)) {
7722 DEBUG(2, ("Got invalid trans2 request: %s\n",
7723 nt_errstr(result)));
7724 reply_nterror(req, result);
7725 END_PROFILE(SMBtrans2);
7730 switch (tran_call) {
7731 /* List the allowed trans2 calls on IPC$ */
7732 case TRANSACT2_OPEN:
7733 case TRANSACT2_GET_DFS_REFERRAL:
7734 case TRANSACT2_QFILEINFO:
7735 case TRANSACT2_QFSINFO:
7736 case TRANSACT2_SETFSINFO:
7739 reply_doserror(req, ERRSRV, ERRaccess);
7740 END_PROFILE(SMBtrans2);
7745 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7746 DEBUG(0, ("talloc failed\n"));
7747 reply_nterror(req, NT_STATUS_NO_MEMORY);
7748 END_PROFILE(SMBtrans2);
7752 state->cmd = SMBtrans2;
7754 state->mid = req->mid;
7755 state->vuid = req->vuid;
7756 state->setup_count = SVAL(req->vwv+13, 0);
7757 state->setup = NULL;
7758 state->total_param = SVAL(req->vwv+0, 0);
7759 state->param = NULL;
7760 state->total_data = SVAL(req->vwv+1, 0);
7762 state->max_param_return = SVAL(req->vwv+2, 0);
7763 state->max_data_return = SVAL(req->vwv+3, 0);
7764 state->max_setup_return = SVAL(req->vwv+4, 0);
7765 state->close_on_completion = BITSETW(req->vwv+5, 0);
7766 state->one_way = BITSETW(req->vwv+5, 1);
7768 state->call = tran_call;
7770 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7771 is so as a sanity check */
7772 if (state->setup_count != 1) {
7774 * Need to have rc=0 for ioctl to get job id for OS/2.
7775 * Network printing will fail if function is not successful.
7776 * Similar function in reply.c will be used if protocol
7777 * is LANMAN1.0 instead of LM1.2X002.
7778 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7779 * outbuf doesn't have to be set(only job id is used).
7781 if ( (state->setup_count == 4)
7782 && (tran_call == TRANSACT2_IOCTL)
7783 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7784 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7785 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7787 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7788 DEBUG(2,("Transaction is %d\n",tran_call));
7790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7791 END_PROFILE(SMBtrans2);
7796 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7799 if (state->total_data) {
7801 if (trans_oob(state->total_data, 0, dscnt)
7802 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7806 /* Can't use talloc here, the core routines do realloc on the
7807 * params and data. */
7808 state->data = (char *)SMB_MALLOC(state->total_data);
7809 if (state->data == NULL) {
7810 DEBUG(0,("reply_trans2: data malloc fail for %u "
7811 "bytes !\n", (unsigned int)state->total_data));
7813 reply_nterror(req, NT_STATUS_NO_MEMORY);
7814 END_PROFILE(SMBtrans2);
7818 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7821 if (state->total_param) {
7823 if (trans_oob(state->total_param, 0, pscnt)
7824 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7828 /* Can't use talloc here, the core routines do realloc on the
7829 * params and data. */
7830 state->param = (char *)SMB_MALLOC(state->total_param);
7831 if (state->param == NULL) {
7832 DEBUG(0,("reply_trans: param malloc fail for %u "
7833 "bytes !\n", (unsigned int)state->total_param));
7834 SAFE_FREE(state->data);
7836 reply_nterror(req, NT_STATUS_NO_MEMORY);
7837 END_PROFILE(SMBtrans2);
7841 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7844 state->received_data = dscnt;
7845 state->received_param = pscnt;
7847 if ((state->received_param == state->total_param) &&
7848 (state->received_data == state->total_data)) {
7850 handle_trans2(conn, req, state);
7852 SAFE_FREE(state->data);
7853 SAFE_FREE(state->param);
7855 END_PROFILE(SMBtrans2);
7859 DLIST_ADD(conn->pending_trans, state);
7861 /* We need to send an interim response then receive the rest
7862 of the parameter/data bytes */
7863 reply_outbuf(req, 0, 0);
7864 show_msg((char *)req->outbuf);
7865 END_PROFILE(SMBtrans2);
7870 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7871 SAFE_FREE(state->data);
7872 SAFE_FREE(state->param);
7874 END_PROFILE(SMBtrans2);
7875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7879 /****************************************************************************
7880 Reply to a SMBtranss2
7881 ****************************************************************************/
7883 void reply_transs2(struct smb_request *req)
7885 connection_struct *conn = req->conn;
7886 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7887 struct trans_state *state;
7889 START_PROFILE(SMBtranss2);
7891 show_msg((char *)req->inbuf);
7894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7895 END_PROFILE(SMBtranss2);
7899 for (state = conn->pending_trans; state != NULL;
7900 state = state->next) {
7901 if (state->mid == req->mid) {
7906 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7908 END_PROFILE(SMBtranss2);
7912 /* Revise state->total_param and state->total_data in case they have
7913 changed downwards */
7915 if (SVAL(req->vwv+0, 0) < state->total_param)
7916 state->total_param = SVAL(req->vwv+0, 0);
7917 if (SVAL(req->vwv+1, 0) < state->total_data)
7918 state->total_data = SVAL(req->vwv+1, 0);
7920 pcnt = SVAL(req->vwv+2, 0);
7921 poff = SVAL(req->vwv+3, 0);
7922 pdisp = SVAL(req->vwv+4, 0);
7924 dcnt = SVAL(req->vwv+5, 0);
7925 doff = SVAL(req->vwv+6, 0);
7926 ddisp = SVAL(req->vwv+7, 0);
7928 state->received_param += pcnt;
7929 state->received_data += dcnt;
7931 if ((state->received_data > state->total_data) ||
7932 (state->received_param > state->total_param))
7936 if (trans_oob(state->total_param, pdisp, pcnt)
7937 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7940 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7944 if (trans_oob(state->total_data, ddisp, dcnt)
7945 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7948 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7951 if ((state->received_param < state->total_param) ||
7952 (state->received_data < state->total_data)) {
7953 END_PROFILE(SMBtranss2);
7957 handle_trans2(conn, req, state);
7959 DLIST_REMOVE(conn->pending_trans, state);
7960 SAFE_FREE(state->data);
7961 SAFE_FREE(state->param);
7964 END_PROFILE(SMBtranss2);
7969 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7970 DLIST_REMOVE(conn->pending_trans, state);
7971 SAFE_FREE(state->data);
7972 SAFE_FREE(state->param);
7974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7975 END_PROFILE(SMBtranss2);