2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
247 *pnum_names = num_names;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list *ea_list_head = NULL;
266 if (!lp_ea_support(SNUM(conn))) {
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
285 listp = TALLOC_P(mem_ctx, struct ea_list);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
346 if (ea_list->ea.value.length > 65535) {
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
372 size_t total_ea_len = 0;
373 TALLOC_CTX *mem_ctx = NULL;
375 if (!lp_ea_support(SNUM(conn))) {
378 mem_ctx = talloc_tos();
379 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
383 /****************************************************************************
384 Ensure the EA name is case insensitive by matching any existing EA name.
385 ****************************************************************************/
387 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
390 TALLOC_CTX *mem_ctx = talloc_tos();
391 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
393 for (; ea_list; ea_list = ea_list->next) {
394 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
395 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
396 &unix_ea_name[5], ea_list->ea.name));
397 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
403 /****************************************************************************
404 Set or delete an extended attribute.
405 ****************************************************************************/
407 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
409 if (!lp_ea_support(SNUM(conn))) {
410 return NT_STATUS_EAS_NOT_SUPPORTED;
413 for (;ea_list; ea_list = ea_list->next) {
415 fstring unix_ea_name;
417 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
418 fstrcat(unix_ea_name, ea_list->ea.name);
420 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
422 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
424 if (samba_private_attr_name(unix_ea_name)) {
425 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
426 return NT_STATUS_ACCESS_DENIED;
429 if (ea_list->ea.value.length == 0) {
430 /* Remove the attribute. */
431 if (fsp && (fsp->fh->fd != -1)) {
432 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
433 unix_ea_name, fsp->fsp_name));
434 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
436 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
437 unix_ea_name, fname));
438 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
441 /* Removing a non existent attribute always succeeds. */
442 if (ret == -1 && errno == ENOATTR) {
443 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
449 if (fsp && (fsp->fh->fd != -1)) {
450 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
451 unix_ea_name, fsp->fsp_name));
452 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
453 ea_list->ea.value.data, ea_list->ea.value.length, 0);
455 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
456 unix_ea_name, fname));
457 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
458 ea_list->ea.value.data, ea_list->ea.value.length, 0);
464 if (errno == ENOTSUP) {
465 return NT_STATUS_EAS_NOT_SUPPORTED;
468 return map_nt_error_from_unix(errno);
474 /****************************************************************************
475 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
476 ****************************************************************************/
478 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
480 struct ea_list *ea_list_head = NULL;
481 size_t converted_size, offset = 0;
483 while (offset + 2 < data_size) {
484 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
485 unsigned int namelen = CVAL(pdata,offset);
487 offset++; /* Go past the namelen byte. */
489 /* integer wrap paranioa. */
490 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
491 (offset > data_size) || (namelen > data_size) ||
492 (offset + namelen >= data_size)) {
495 /* Ensure the name is null terminated. */
496 if (pdata[offset + namelen] != '\0') {
499 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
501 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
502 "failed: %s", strerror(errno)));
508 offset += (namelen + 1); /* Go past the name + terminating zero. */
509 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
510 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
516 /****************************************************************************
517 Read one EA list entry from the buffer.
518 ****************************************************************************/
520 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
522 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
524 unsigned int namelen;
525 size_t converted_size;
535 eal->ea.flags = CVAL(pdata,0);
536 namelen = CVAL(pdata,1);
537 val_len = SVAL(pdata,2);
539 if (4 + namelen + 1 + val_len > data_size) {
543 /* Ensure the name is null terminated. */
544 if (pdata[namelen + 4] != '\0') {
547 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
548 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
555 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
556 if (!eal->ea.value.data) {
560 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
562 /* Ensure we're null terminated just in case we print the value. */
563 eal->ea.value.data[val_len] = '\0';
564 /* But don't count the null. */
565 eal->ea.value.length--;
568 *pbytes_used = 4 + namelen + 1 + val_len;
571 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
572 dump_data(10, eal->ea.value.data, eal->ea.value.length);
577 /****************************************************************************
578 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
579 ****************************************************************************/
581 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
583 struct ea_list *ea_list_head = NULL;
585 size_t bytes_used = 0;
587 while (offset < data_size) {
588 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
594 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
595 offset += bytes_used;
601 /****************************************************************************
602 Count the total EA size needed.
603 ****************************************************************************/
605 static size_t ea_list_size(struct ea_list *ealist)
608 struct ea_list *listp;
611 for (listp = ealist; listp; listp = listp->next) {
612 push_ascii_fstring(dos_ea_name, listp->ea.name);
613 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
615 /* Add on 4 for total length. */
623 /****************************************************************************
624 Return a union of EA's from a file list and a list of names.
625 The TALLOC context for the two lists *MUST* be identical as we steal
626 memory from one list to add to another. JRA.
627 ****************************************************************************/
629 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
631 struct ea_list *nlistp, *flistp;
633 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
634 for (flistp = file_list; flistp; flistp = flistp->next) {
635 if (strequal(nlistp->ea.name, flistp->ea.name)) {
641 /* Copy the data from this entry. */
642 nlistp->ea.flags = flistp->ea.flags;
643 nlistp->ea.value = flistp->ea.value;
646 nlistp->ea.flags = 0;
647 ZERO_STRUCT(nlistp->ea.value);
651 *total_ea_len = ea_list_size(name_list);
655 /****************************************************************************
656 Send the required number of replies back.
657 We assume all fields other than the data fields are
658 set correctly for the type of call.
659 HACK ! Always assumes smb_setup field is zero.
660 ****************************************************************************/
662 void send_trans2_replies(connection_struct *conn,
663 struct smb_request *req,
670 /* As we are using a protocol > LANMAN1 then the max_send
671 variable must have been set in the sessetupX call.
672 This takes precedence over the max_xmit field in the
673 global struct. These different max_xmit variables should
674 be merged as this is now too confusing */
676 int data_to_send = datasize;
677 int params_to_send = paramsize;
679 const char *pp = params;
680 const char *pd = pdata;
681 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
682 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
683 int data_alignment_offset = 0;
684 bool overflow = False;
685 struct smbd_server_connection *sconn = smbd_server_conn;
686 int max_send = sconn->smb1.sessions.max_send;
688 /* Modify the data_to_send and datasize and set the error if
689 we're trying to send more than max_data_bytes. We still send
690 the part of the packet(s) that fit. Strange, but needed
693 if (max_data_bytes > 0 && datasize > max_data_bytes) {
694 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
695 max_data_bytes, datasize ));
696 datasize = data_to_send = max_data_bytes;
700 /* If there genuinely are no parameters or data to send just send the empty packet */
702 if(params_to_send == 0 && data_to_send == 0) {
703 reply_outbuf(req, 10, 0);
704 show_msg((char *)req->outbuf);
708 /* When sending params and data ensure that both are nicely aligned */
709 /* Only do this alignment when there is also data to send - else
710 can cause NT redirector problems. */
712 if (((params_to_send % 4) != 0) && (data_to_send != 0))
713 data_alignment_offset = 4 - (params_to_send % 4);
715 /* Space is bufsize minus Netbios over TCP header minus SMB header */
716 /* The alignment_offset is to align the param bytes on an even byte
717 boundary. NT 4.0 Beta needs this to work correctly. */
719 useable_space = max_send - (smb_size
722 + data_alignment_offset);
724 if (useable_space < 0) {
725 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
726 "= %d!!!", useable_space));
727 exit_server_cleanly("send_trans2_replies: Not enough space");
730 while (params_to_send || data_to_send) {
731 /* Calculate whether we will totally or partially fill this packet */
733 total_sent_thistime = params_to_send + data_to_send;
735 /* We can never send more than useable_space */
737 * Note that 'useable_space' does not include the alignment offsets,
738 * but we must include the alignment offsets in the calculation of
739 * the length of the data we send over the wire, as the alignment offsets
740 * are sent here. Fix from Marc_Jacobsen@hp.com.
743 total_sent_thistime = MIN(total_sent_thistime, useable_space);
745 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
746 + data_alignment_offset);
749 * We might have SMBtrans2s in req which was transferred to
750 * the outbuf, fix that.
752 SCVAL(req->outbuf, smb_com, SMBtrans2);
754 /* Set total params and data to be sent */
755 SSVAL(req->outbuf,smb_tprcnt,paramsize);
756 SSVAL(req->outbuf,smb_tdrcnt,datasize);
758 /* Calculate how many parameters and data we can fit into
759 * this packet. Parameters get precedence
762 params_sent_thistime = MIN(params_to_send,useable_space);
763 data_sent_thistime = useable_space - params_sent_thistime;
764 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
766 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
768 /* smb_proff is the offset from the start of the SMB header to the
769 parameter bytes, however the first 4 bytes of outbuf are
770 the Netbios over TCP header. Thus use smb_base() to subtract
771 them from the calculation */
773 SSVAL(req->outbuf,smb_proff,
774 ((smb_buf(req->outbuf)+alignment_offset)
775 - smb_base(req->outbuf)));
777 if(params_sent_thistime == 0)
778 SSVAL(req->outbuf,smb_prdisp,0);
780 /* Absolute displacement of param bytes sent in this packet */
781 SSVAL(req->outbuf,smb_prdisp,pp - params);
783 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
784 if(data_sent_thistime == 0) {
785 SSVAL(req->outbuf,smb_droff,0);
786 SSVAL(req->outbuf,smb_drdisp, 0);
788 /* The offset of the data bytes is the offset of the
789 parameter bytes plus the number of parameters being sent this time */
790 SSVAL(req->outbuf, smb_droff,
791 ((smb_buf(req->outbuf)+alignment_offset)
792 - smb_base(req->outbuf))
793 + params_sent_thistime + data_alignment_offset);
794 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
797 /* Initialize the padding for alignment */
799 if (alignment_offset != 0) {
800 memset(smb_buf(req->outbuf), 0, alignment_offset);
803 /* Copy the param bytes into the packet */
805 if(params_sent_thistime) {
806 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
807 params_sent_thistime);
810 /* Copy in the data bytes */
811 if(data_sent_thistime) {
812 if (data_alignment_offset != 0) {
813 memset((smb_buf(req->outbuf)+alignment_offset+
814 params_sent_thistime), 0,
815 data_alignment_offset);
817 memcpy(smb_buf(req->outbuf)+alignment_offset
818 +params_sent_thistime+data_alignment_offset,
819 pd,data_sent_thistime);
822 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
823 params_sent_thistime, data_sent_thistime, useable_space));
824 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
825 params_to_send, data_to_send, paramsize, datasize));
828 error_packet_set((char *)req->outbuf,
829 ERRDOS,ERRbufferoverflow,
830 STATUS_BUFFER_OVERFLOW,
834 /* Send the packet */
835 show_msg((char *)req->outbuf);
836 if (!srv_send_smb(smbd_server_fd(),
839 IS_CONN_ENCRYPTED(conn),
841 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
843 TALLOC_FREE(req->outbuf);
845 pp += params_sent_thistime;
846 pd += data_sent_thistime;
848 params_to_send -= params_sent_thistime;
849 data_to_send -= data_sent_thistime;
852 if(params_to_send < 0 || data_to_send < 0) {
853 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
854 params_to_send, data_to_send));
862 /****************************************************************************
863 Reply to a TRANSACT2_OPEN.
864 ****************************************************************************/
866 static void call_trans2open(connection_struct *conn,
867 struct smb_request *req,
868 char **pparams, int total_params,
869 char **ppdata, int total_data,
870 unsigned int max_data_bytes)
872 struct smb_filename *smb_fname = NULL;
873 char *params = *pparams;
874 char *pdata = *ppdata;
879 bool return_additional_info;
892 struct ea_list *ea_list = NULL;
897 uint32 create_disposition;
898 uint32 create_options = 0;
899 TALLOC_CTX *ctx = talloc_tos();
902 * Ensure we have enough parameters to perform the operation.
905 if (total_params < 29) {
906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
910 flags = SVAL(params, 0);
911 deny_mode = SVAL(params, 2);
912 open_attr = SVAL(params,6);
913 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
914 if (oplock_request) {
915 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
919 return_additional_info = BITSETW(params,0);
920 open_sattr = SVAL(params, 4);
921 open_time = make_unix_date3(params+8);
923 open_ofun = SVAL(params,12);
924 open_size = IVAL(params,14);
928 reply_doserror(req, ERRSRV, ERRaccess);
932 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
933 total_params - 28, STR_TERMINATE,
935 if (!NT_STATUS_IS_OK(status)) {
936 reply_nterror(req, status);
940 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
941 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
942 (unsigned int)open_ofun, open_size));
944 if (open_ofun == 0) {
945 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
949 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
954 reply_doserror(req, ERRDOS, ERRbadaccess);
958 /* Any data in this call is an EA list. */
959 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
960 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
964 if (total_data != 4) {
965 if (total_data < 10) {
966 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
970 if (IVAL(pdata,0) > total_data) {
971 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
972 IVAL(pdata,0), (unsigned int)total_data));
973 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
977 ea_list = read_ea_list(talloc_tos(), pdata + 4,
980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
983 } else if (IVAL(pdata,0) != 4) {
984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
988 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
989 if (!NT_STATUS_IS_OK(status)) {
990 reply_nterror(req, status);
994 status = get_full_smb_filename(ctx, smb_fname, &fname);
995 if (!NT_STATUS_IS_OK(status)) {
996 reply_nterror(req, status);
1000 status = SMB_VFS_CREATE_FILE(
1003 0, /* root_dir_fid */
1005 0, /* create_file_flags */
1006 access_mask, /* access_mask */
1007 share_mode, /* share_access */
1008 create_disposition, /* create_disposition*/
1009 create_options, /* create_options */
1010 open_attr, /* file_attributes */
1011 oplock_request, /* oplock_request */
1012 open_size, /* allocation_size */
1014 ea_list, /* ea_list */
1016 &smb_action, /* pinfo */
1017 &smb_fname->st); /* psbuf */
1019 if (!NT_STATUS_IS_OK(status)) {
1020 if (open_was_deferred(req->mid)) {
1021 /* We have re-scheduled this call. */
1024 reply_openerror(req, status);
1028 size = get_file_size_stat(&smb_fname->st);
1029 fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st);
1030 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1031 inode = smb_fname->st.st_ex_ino;
1033 close_file(req, fsp, ERROR_CLOSE);
1034 reply_doserror(req, ERRDOS,ERRnoaccess);
1038 /* Realloc the size of parameters and data we will return */
1039 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1040 if(*pparams == NULL ) {
1041 reply_nterror(req, NT_STATUS_NO_MEMORY);
1046 SSVAL(params,0,fsp->fnum);
1047 SSVAL(params,2,fattr);
1048 srv_put_dos_date2(params,4, mtime);
1049 SIVAL(params,8, (uint32)size);
1050 SSVAL(params,12,deny_mode);
1051 SSVAL(params,14,0); /* open_type - file or directory. */
1052 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1054 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1055 smb_action |= EXTENDED_OPLOCK_GRANTED;
1058 SSVAL(params,18,smb_action);
1061 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1063 SIVAL(params,20,inode);
1064 SSVAL(params,24,0); /* Padding. */
1066 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1067 SIVAL(params, 26, ea_size);
1069 SIVAL(params, 26, 0);
1072 /* Send the required number of replies */
1073 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1075 TALLOC_FREE(smb_fname);
1078 /*********************************************************
1079 Routine to check if a given string matches exactly.
1080 as a special case a mask of "." does NOT match. That
1081 is required for correct wildcard semantics
1082 Case can be significant or not.
1083 **********************************************************/
1085 static bool exact_match(connection_struct *conn,
1089 if (mask[0] == '.' && mask[1] == 0)
1091 if (dptr_has_wild(conn->dirptr)) {
1094 if (conn->case_sensitive)
1095 return strcmp(str,mask)==0;
1097 return StrCaseCmp(str,mask) == 0;
1100 /****************************************************************************
1101 Return the filetype for UNIX extensions.
1102 ****************************************************************************/
1104 static uint32 unix_filetype(mode_t mode)
1107 return UNIX_TYPE_FILE;
1108 else if(S_ISDIR(mode))
1109 return UNIX_TYPE_DIR;
1111 else if(S_ISLNK(mode))
1112 return UNIX_TYPE_SYMLINK;
1115 else if(S_ISCHR(mode))
1116 return UNIX_TYPE_CHARDEV;
1119 else if(S_ISBLK(mode))
1120 return UNIX_TYPE_BLKDEV;
1123 else if(S_ISFIFO(mode))
1124 return UNIX_TYPE_FIFO;
1127 else if(S_ISSOCK(mode))
1128 return UNIX_TYPE_SOCKET;
1131 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1132 return UNIX_TYPE_UNKNOWN;
1135 /****************************************************************************
1136 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1137 ****************************************************************************/
1139 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1141 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1142 SMB_STRUCT_STAT *psbuf,
1144 enum perm_type ptype,
1149 if (perms == SMB_MODE_NO_CHANGE) {
1150 if (!VALID_STAT(*psbuf)) {
1151 return NT_STATUS_INVALID_PARAMETER;
1153 *ret_perms = psbuf->st_ex_mode;
1154 return NT_STATUS_OK;
1158 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1159 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1160 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1161 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1162 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1163 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1164 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1165 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1166 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1168 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1171 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1174 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1179 /* Apply mode mask */
1180 ret &= lp_create_mask(SNUM(conn));
1181 /* Add in force bits */
1182 ret |= lp_force_create_mode(SNUM(conn));
1185 ret &= lp_dir_mask(SNUM(conn));
1186 /* Add in force bits */
1187 ret |= lp_force_dir_mode(SNUM(conn));
1189 case PERM_EXISTING_FILE:
1190 /* Apply mode mask */
1191 ret &= lp_security_mask(SNUM(conn));
1192 /* Add in force bits */
1193 ret |= lp_force_security_mode(SNUM(conn));
1195 case PERM_EXISTING_DIR:
1196 /* Apply mode mask */
1197 ret &= lp_dir_security_mask(SNUM(conn));
1198 /* Add in force bits */
1199 ret |= lp_force_dir_security_mode(SNUM(conn));
1204 return NT_STATUS_OK;
1207 /****************************************************************************
1208 Needed to show the msdfs symlinks as directories. Modifies psbuf
1209 to be a directory if it's a msdfs link.
1210 ****************************************************************************/
1212 static bool check_msdfs_link(connection_struct *conn,
1213 const char *pathname,
1214 SMB_STRUCT_STAT *psbuf)
1216 int saved_errno = errno;
1217 if(lp_host_msdfs() &&
1218 lp_msdfs_root(SNUM(conn)) &&
1219 is_msdfs_link(conn, pathname, psbuf)) {
1221 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1224 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1225 errno = saved_errno;
1228 errno = saved_errno;
1233 /****************************************************************************
1234 Get a level dependent lanman2 dir entry.
1235 ****************************************************************************/
1237 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1238 connection_struct *conn,
1240 const char *path_mask,
1243 int requires_resume_key,
1249 int space_remaining,
1251 bool *got_exact_match,
1252 int *last_entry_off,
1253 struct ea_list *name_list)
1257 SMB_STRUCT_STAT sbuf;
1258 const char *mask = NULL;
1259 char *pathreal = NULL;
1261 char *p, *q, *pdata = *ppdata;
1265 SMB_OFF_T file_size = 0;
1266 uint64_t allocation_size = 0;
1268 struct timespec mdate_ts, adate_ts, create_date_ts;
1269 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1271 char *last_entry_ptr;
1273 uint32 nt_extmode; /* Used for NT connections instead of mode */
1274 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1275 bool check_mangled_names = lp_manglednames(conn->params);
1276 char mangled_name[13]; /* mangled 8.3 name. */
1278 *out_of_space = False;
1279 *got_exact_match = False;
1281 ZERO_STRUCT(mdate_ts);
1282 ZERO_STRUCT(adate_ts);
1283 ZERO_STRUCT(create_date_ts);
1285 if (!conn->dirptr) {
1289 p = strrchr_m(path_mask,'/');
1292 mask = talloc_strdup(ctx,"*.*");
1302 bool ms_dfs_link = False;
1304 /* Needed if we run out of space */
1305 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1306 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1309 * Due to bugs in NT client redirectors we are not using
1310 * resume keys any more - set them to zero.
1311 * Check out the related comments in findfirst/findnext.
1317 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1318 (long)conn->dirptr,curr_dirpos));
1325 * fname may get mangled, dname is never mangled.
1326 * Whenever we're accessing the filesystem we use
1327 * pathreal which is composed from dname.
1333 /* Mangle fname if it's an illegal name. */
1334 if (mangle_must_mangle(dname,conn->params)) {
1335 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1337 continue; /* Error - couldn't mangle. */
1339 fname = talloc_strdup(ctx, mangled_name);
1345 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1346 got_match = mask_match(fname, mask, conn->case_sensitive);
1349 if(!got_match && check_mangled_names &&
1350 !mangle_is_8_3(fname, False, conn->params)) {
1352 * It turns out that NT matches wildcards against
1353 * both long *and* short names. This may explain some
1354 * of the wildcard wierdness from old DOS clients
1355 * that some people have been seeing.... JRA.
1357 /* Force the mangling into 8.3. */
1358 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1360 continue; /* Error - couldn't mangle. */
1363 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1364 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1369 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1371 if (dont_descend && !isdots) {
1378 pathreal = talloc_asprintf(ctx,
1383 pathreal = talloc_asprintf(ctx,
1394 if (INFO_LEVEL_IS_UNIX(info_level)) {
1395 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1396 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1397 pathreal,strerror(errno)));
1398 TALLOC_FREE(pathreal);
1402 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1403 /* Needed to show the msdfs symlinks as
1406 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1408 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1409 pathreal,strerror(errno)));
1410 TALLOC_FREE(pathreal);
1417 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1419 mode = dos_mode(conn,pathreal,&sbuf);
1422 if (!dir_check_ftype(conn,mode,dirtype)) {
1423 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1424 TALLOC_FREE(pathreal);
1429 if (!(mode & aDIR)) {
1430 file_size = get_file_size_stat(&sbuf);
1432 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1434 mdate_ts = sbuf.st_ex_mtime;
1435 adate_ts = sbuf.st_ex_atime;
1436 create_date_ts = sbuf.st_ex_btime;
1438 if (ask_sharemode) {
1439 struct timespec write_time_ts;
1440 struct file_id fileid;
1442 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1443 get_file_infos(fileid, NULL, &write_time_ts);
1444 if (!null_timespec(write_time_ts)) {
1445 mdate_ts = write_time_ts;
1449 if (lp_dos_filetime_resolution(SNUM(conn))) {
1450 dos_filetime_timespec(&create_date_ts);
1451 dos_filetime_timespec(&mdate_ts);
1452 dos_filetime_timespec(&adate_ts);
1455 create_date = convert_timespec_to_time_t(create_date_ts);
1456 mdate = convert_timespec_to_time_t(mdate_ts);
1457 adate = convert_timespec_to_time_t(adate_ts);
1459 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1464 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1474 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1476 switch (info_level) {
1477 case SMB_FIND_INFO_STANDARD:
1478 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1479 if(requires_resume_key) {
1483 srv_put_dos_date2(p,0,create_date);
1484 srv_put_dos_date2(p,4,adate);
1485 srv_put_dos_date2(p,8,mdate);
1486 SIVAL(p,12,(uint32)file_size);
1487 SIVAL(p,16,(uint32)allocation_size);
1491 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1492 p += ucs2_align(base_data, p, 0);
1494 len = srvstr_push(base_data, flags2, p,
1495 fname, PTR_DIFF(end_data, p),
1497 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1499 SCVAL(nameptr, -1, len - 2);
1501 SCVAL(nameptr, -1, 0);
1505 SCVAL(nameptr, -1, len - 1);
1507 SCVAL(nameptr, -1, 0);
1513 case SMB_FIND_EA_SIZE:
1514 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1515 if(requires_resume_key) {
1519 srv_put_dos_date2(p,0,create_date);
1520 srv_put_dos_date2(p,4,adate);
1521 srv_put_dos_date2(p,8,mdate);
1522 SIVAL(p,12,(uint32)file_size);
1523 SIVAL(p,16,(uint32)allocation_size);
1526 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1527 SIVAL(p,22,ea_size); /* Extended attributes */
1531 len = srvstr_push(base_data, flags2,
1532 p, fname, PTR_DIFF(end_data, p),
1533 STR_TERMINATE | STR_NOALIGN);
1534 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1547 SCVAL(nameptr,0,len);
1549 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1552 case SMB_FIND_EA_LIST:
1554 struct ea_list *file_list = NULL;
1557 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1561 if(requires_resume_key) {
1565 srv_put_dos_date2(p,0,create_date);
1566 srv_put_dos_date2(p,4,adate);
1567 srv_put_dos_date2(p,8,mdate);
1568 SIVAL(p,12,(uint32)file_size);
1569 SIVAL(p,16,(uint32)allocation_size);
1571 p += 22; /* p now points to the EA area. */
1573 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1574 name_list = ea_list_union(name_list, file_list, &ea_len);
1576 /* We need to determine if this entry will fit in the space available. */
1577 /* Max string size is 255 bytes. */
1578 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1579 /* Move the dirptr back to prev_dirpos */
1580 dptr_SeekDir(conn->dirptr, prev_dirpos);
1581 *out_of_space = True;
1582 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1583 return False; /* Not finished - just out of space */
1586 /* Push the ea_data followed by the name. */
1587 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1589 len = srvstr_push(base_data, flags2,
1590 p + 1, fname, PTR_DIFF(end_data, p+1),
1591 STR_TERMINATE | STR_NOALIGN);
1592 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1605 SCVAL(nameptr,0,len);
1607 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1611 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1612 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1613 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1615 SIVAL(p,0,reskey); p += 4;
1616 put_long_date_timespec(p,create_date_ts); p += 8;
1617 put_long_date_timespec(p,adate_ts); p += 8;
1618 put_long_date_timespec(p,mdate_ts); p += 8;
1619 put_long_date_timespec(p,mdate_ts); p += 8;
1620 SOFF_T(p,0,file_size); p += 8;
1621 SOFF_T(p,0,allocation_size); p += 8;
1622 SIVAL(p,0,nt_extmode); p += 4;
1623 q = p; p += 4; /* q is placeholder for name length. */
1625 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1626 SIVAL(p,0,ea_size); /* Extended attributes */
1629 /* Clear the short name buffer. This is
1630 * IMPORTANT as not doing so will trigger
1631 * a Win2k client bug. JRA.
1633 if (!was_8_3 && check_mangled_names) {
1634 if (!name_to_8_3(fname,mangled_name,True,
1636 /* Error - mangle failed ! */
1637 memset(mangled_name,'\0',12);
1639 mangled_name[12] = 0;
1640 len = srvstr_push(base_data, flags2,
1641 p+2, mangled_name, 24,
1642 STR_UPPER|STR_UNICODE);
1644 memset(p + 2 + len,'\0',24 - len);
1651 len = srvstr_push(base_data, flags2, p,
1652 fname, PTR_DIFF(end_data, p),
1653 STR_TERMINATE_ASCII);
1656 SIVAL(p,0,0); /* Ensure any padding is null. */
1657 len = PTR_DIFF(p, pdata);
1658 len = (len + 3) & ~3;
1663 case SMB_FIND_FILE_DIRECTORY_INFO:
1664 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1666 SIVAL(p,0,reskey); p += 4;
1667 put_long_date_timespec(p,create_date_ts); p += 8;
1668 put_long_date_timespec(p,adate_ts); p += 8;
1669 put_long_date_timespec(p,mdate_ts); p += 8;
1670 put_long_date_timespec(p,mdate_ts); p += 8;
1671 SOFF_T(p,0,file_size); p += 8;
1672 SOFF_T(p,0,allocation_size); p += 8;
1673 SIVAL(p,0,nt_extmode); p += 4;
1674 len = srvstr_push(base_data, flags2,
1675 p + 4, fname, PTR_DIFF(end_data, p+4),
1676 STR_TERMINATE_ASCII);
1679 SIVAL(p,0,0); /* Ensure any padding is null. */
1680 len = PTR_DIFF(p, pdata);
1681 len = (len + 3) & ~3;
1686 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1687 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1689 SIVAL(p,0,reskey); p += 4;
1690 put_long_date_timespec(p,create_date_ts); p += 8;
1691 put_long_date_timespec(p,adate_ts); p += 8;
1692 put_long_date_timespec(p,mdate_ts); p += 8;
1693 put_long_date_timespec(p,mdate_ts); p += 8;
1694 SOFF_T(p,0,file_size); p += 8;
1695 SOFF_T(p,0,allocation_size); p += 8;
1696 SIVAL(p,0,nt_extmode); p += 4;
1697 q = p; p += 4; /* q is placeholder for name length. */
1699 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1700 SIVAL(p,0,ea_size); /* Extended attributes */
1703 len = srvstr_push(base_data, flags2, p,
1704 fname, PTR_DIFF(end_data, p),
1705 STR_TERMINATE_ASCII);
1709 SIVAL(p,0,0); /* Ensure any padding is null. */
1710 len = PTR_DIFF(p, pdata);
1711 len = (len + 3) & ~3;
1716 case SMB_FIND_FILE_NAMES_INFO:
1717 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1719 SIVAL(p,0,reskey); p += 4;
1721 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1722 acl on a dir (tridge) */
1723 len = srvstr_push(base_data, flags2, p,
1724 fname, PTR_DIFF(end_data, p),
1725 STR_TERMINATE_ASCII);
1728 SIVAL(p,0,0); /* Ensure any padding is null. */
1729 len = PTR_DIFF(p, pdata);
1730 len = (len + 3) & ~3;
1735 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1736 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1738 SIVAL(p,0,reskey); p += 4;
1739 put_long_date_timespec(p,create_date_ts); p += 8;
1740 put_long_date_timespec(p,adate_ts); p += 8;
1741 put_long_date_timespec(p,mdate_ts); p += 8;
1742 put_long_date_timespec(p,mdate_ts); p += 8;
1743 SOFF_T(p,0,file_size); p += 8;
1744 SOFF_T(p,0,allocation_size); p += 8;
1745 SIVAL(p,0,nt_extmode); p += 4;
1746 q = p; p += 4; /* q is placeholder for name length. */
1748 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1749 SIVAL(p,0,ea_size); /* Extended attributes */
1752 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1753 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1754 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1755 len = srvstr_push(base_data, flags2, p,
1756 fname, PTR_DIFF(end_data, p),
1757 STR_TERMINATE_ASCII);
1760 SIVAL(p,0,0); /* Ensure any padding is null. */
1761 len = PTR_DIFF(p, pdata);
1762 len = (len + 3) & ~3;
1767 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1768 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1769 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1771 SIVAL(p,0,reskey); p += 4;
1772 put_long_date_timespec(p,create_date_ts); p += 8;
1773 put_long_date_timespec(p,adate_ts); p += 8;
1774 put_long_date_timespec(p,mdate_ts); p += 8;
1775 put_long_date_timespec(p,mdate_ts); p += 8;
1776 SOFF_T(p,0,file_size); p += 8;
1777 SOFF_T(p,0,allocation_size); p += 8;
1778 SIVAL(p,0,nt_extmode); p += 4;
1779 q = p; p += 4; /* q is placeholder for name length */
1781 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1782 SIVAL(p,0,ea_size); /* Extended attributes */
1785 /* Clear the short name buffer. This is
1786 * IMPORTANT as not doing so will trigger
1787 * a Win2k client bug. JRA.
1789 if (!was_8_3 && check_mangled_names) {
1790 if (!name_to_8_3(fname,mangled_name,True,
1792 /* Error - mangle failed ! */
1793 memset(mangled_name,'\0',12);
1795 mangled_name[12] = 0;
1796 len = srvstr_push(base_data, flags2,
1797 p+2, mangled_name, 24,
1798 STR_UPPER|STR_UNICODE);
1801 memset(p + 2 + len,'\0',24 - len);
1808 SSVAL(p,0,0); p += 2; /* Reserved ? */
1809 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1810 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1811 len = srvstr_push(base_data, flags2, p,
1812 fname, PTR_DIFF(end_data, p),
1813 STR_TERMINATE_ASCII);
1816 SIVAL(p,0,0); /* Ensure any padding is null. */
1817 len = PTR_DIFF(p, pdata);
1818 len = (len + 3) & ~3;
1823 /* CIFS UNIX Extension. */
1825 case SMB_FIND_FILE_UNIX:
1826 case SMB_FIND_FILE_UNIX_INFO2:
1828 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1830 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1832 if (info_level == SMB_FIND_FILE_UNIX) {
1833 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1834 p = store_file_unix_basic(conn, p,
1836 len = srvstr_push(base_data, flags2, p,
1837 fname, PTR_DIFF(end_data, p),
1840 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1841 p = store_file_unix_basic_info2(conn, p,
1845 len = srvstr_push(base_data, flags2, p, fname,
1846 PTR_DIFF(end_data, p), 0);
1847 SIVAL(nameptr, 0, len);
1851 SIVAL(p,0,0); /* Ensure any padding is null. */
1853 len = PTR_DIFF(p, pdata);
1854 len = (len + 3) & ~3;
1855 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1857 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1867 if (PTR_DIFF(p,pdata) > space_remaining) {
1868 /* Move the dirptr back to prev_dirpos */
1869 dptr_SeekDir(conn->dirptr, prev_dirpos);
1870 *out_of_space = True;
1871 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1872 return False; /* Not finished - just out of space */
1875 /* Setup the last entry pointer, as an offset from base_data */
1876 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1877 /* Advance the data pointer to the next slot */
1883 /****************************************************************************
1884 Reply to a TRANS2_FINDFIRST.
1885 ****************************************************************************/
1887 static void call_trans2findfirst(connection_struct *conn,
1888 struct smb_request *req,
1889 char **pparams, int total_params,
1890 char **ppdata, int total_data,
1891 unsigned int max_data_bytes)
1893 /* We must be careful here that we don't return more than the
1894 allowed number of data bytes. If this means returning fewer than
1895 maxentries then so be it. We assume that the redirector has
1896 enough room for the fixed number of parameter bytes it has
1898 struct smb_filename *smb_dname = NULL;
1899 char *params = *pparams;
1900 char *pdata = *ppdata;
1904 uint16 findfirst_flags;
1905 bool close_after_first;
1907 bool requires_resume_key;
1909 char *directory = NULL;
1912 int last_entry_off=0;
1916 bool finished = False;
1917 bool dont_descend = False;
1918 bool out_of_space = False;
1919 int space_remaining;
1920 bool mask_contains_wcard = False;
1921 struct ea_list *ea_list = NULL;
1922 NTSTATUS ntstatus = NT_STATUS_OK;
1923 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1924 TALLOC_CTX *ctx = talloc_tos();
1926 if (total_params < 13) {
1927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1931 dirtype = SVAL(params,0);
1932 maxentries = SVAL(params,2);
1933 findfirst_flags = SVAL(params,4);
1934 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1935 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1936 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1937 info_level = SVAL(params,6);
1939 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1940 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1941 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1942 info_level, max_data_bytes));
1945 /* W2K3 seems to treat zero as 1. */
1949 switch (info_level) {
1950 case SMB_FIND_INFO_STANDARD:
1951 case SMB_FIND_EA_SIZE:
1952 case SMB_FIND_EA_LIST:
1953 case SMB_FIND_FILE_DIRECTORY_INFO:
1954 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1955 case SMB_FIND_FILE_NAMES_INFO:
1956 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1957 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1958 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1960 case SMB_FIND_FILE_UNIX:
1961 case SMB_FIND_FILE_UNIX_INFO2:
1962 /* Always use filesystem for UNIX mtime query. */
1963 ask_sharemode = false;
1964 if (!lp_unix_extensions()) {
1965 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1970 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1974 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1975 params+12, total_params - 12,
1976 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1977 if (!NT_STATUS_IS_OK(ntstatus)) {
1978 reply_nterror(req, ntstatus);
1982 ntstatus = resolve_dfspath_wcard(ctx, conn,
1983 req->flags2 & FLAGS2_DFS_PATHNAMES,
1986 &mask_contains_wcard);
1987 if (!NT_STATUS_IS_OK(ntstatus)) {
1988 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1989 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1990 ERRSRV, ERRbadpath);
1993 reply_nterror(req, ntstatus);
1997 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
1998 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
1999 if (!NT_STATUS_IS_OK(ntstatus)) {
2000 reply_nterror(req, ntstatus);
2004 mask = smb_dname->original_lcomp;
2006 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2007 TALLOC_FREE(smb_dname);
2008 if (!NT_STATUS_IS_OK(ntstatus)) {
2009 reply_nterror(req, ntstatus);
2013 ntstatus = check_name(conn, directory);
2014 if (!NT_STATUS_IS_OK(ntstatus)) {
2015 reply_nterror(req, ntstatus);
2019 p = strrchr_m(directory,'/');
2021 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2022 if((directory[0] == '.') && (directory[1] == '\0')) {
2023 mask = talloc_strdup(ctx,"*");
2025 reply_nterror(req, NT_STATUS_NO_MEMORY);
2028 mask_contains_wcard = True;
2030 directory = talloc_strdup(talloc_tos(), "./");
2032 reply_nterror(req, NT_STATUS_NO_MEMORY);
2039 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2041 if (info_level == SMB_FIND_EA_LIST) {
2044 if (total_data < 4) {
2045 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2049 ea_size = IVAL(pdata,0);
2050 if (ea_size != total_data) {
2051 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2052 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2057 if (!lp_ea_support(SNUM(conn))) {
2058 reply_doserror(req, ERRDOS, ERReasnotsupported);
2062 /* Pull out the list of names. */
2063 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2065 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2070 *ppdata = (char *)SMB_REALLOC(
2071 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2072 if(*ppdata == NULL ) {
2073 reply_nterror(req, NT_STATUS_NO_MEMORY);
2077 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2079 /* Realloc the params space */
2080 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2081 if (*pparams == NULL) {
2082 reply_nterror(req, NT_STATUS_NO_MEMORY);
2087 /* Save the wildcard match and attribs we are using on this directory -
2088 needed as lanman2 assumes these are being saved between calls */
2090 ntstatus = dptr_create(conn,
2096 mask_contains_wcard,
2100 if (!NT_STATUS_IS_OK(ntstatus)) {
2101 reply_nterror(req, ntstatus);
2105 dptr_num = dptr_dnum(conn->dirptr);
2106 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2108 /* Initialize per TRANS2_FIND_FIRST operation data */
2109 dptr_init_search_op(conn->dirptr);
2111 /* We don't need to check for VOL here as this is returned by
2112 a different TRANS2 call. */
2114 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2115 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2116 dont_descend = True;
2119 space_remaining = max_data_bytes;
2120 out_of_space = False;
2122 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2123 bool got_exact_match = False;
2125 /* this is a heuristic to avoid seeking the dirptr except when
2126 absolutely necessary. It allows for a filename of about 40 chars */
2127 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2128 out_of_space = True;
2131 finished = !get_lanman2_dir_entry(ctx,
2134 mask,dirtype,info_level,
2135 requires_resume_key,dont_descend,
2138 space_remaining, &out_of_space,
2140 &last_entry_off, ea_list);
2143 if (finished && out_of_space)
2146 if (!finished && !out_of_space)
2150 * As an optimisation if we know we aren't looking
2151 * for a wildcard name (ie. the name matches the wildcard exactly)
2152 * then we can finish on any (first) match.
2153 * This speeds up large directory searches. JRA.
2159 /* Ensure space_remaining never goes -ve. */
2160 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2161 space_remaining = 0;
2162 out_of_space = true;
2164 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2168 /* Check if we can close the dirptr */
2169 if(close_after_first || (finished && close_if_end)) {
2170 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2171 dptr_close(&dptr_num);
2175 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2176 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2177 * the protocol level is less than NT1. Tested with smbclient. JRA.
2178 * This should fix the OS/2 client bug #2335.
2181 if(numentries == 0) {
2182 dptr_close(&dptr_num);
2183 if (Protocol < PROTOCOL_NT1) {
2184 reply_doserror(req, ERRDOS, ERRnofiles);
2187 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2188 ERRDOS, ERRbadfile);
2193 /* At this point pdata points to numentries directory entries. */
2195 /* Set up the return parameter block */
2196 SSVAL(params,0,dptr_num);
2197 SSVAL(params,2,numentries);
2198 SSVAL(params,4,finished);
2199 SSVAL(params,6,0); /* Never an EA error */
2200 SSVAL(params,8,last_entry_off);
2202 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2205 if ((! *directory) && dptr_path(dptr_num)) {
2206 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2208 reply_nterror(req, NT_STATUS_NO_MEMORY);
2212 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2213 smb_fn_name(req->cmd),
2214 mask, directory, dirtype, numentries ) );
2217 * Force a name mangle here to ensure that the
2218 * mask as an 8.3 name is top of the mangled cache.
2219 * The reasons for this are subtle. Don't remove
2220 * this code unless you know what you are doing
2221 * (see PR#13758). JRA.
2224 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2225 char mangled_name[13];
2226 name_to_8_3(mask, mangled_name, True, conn->params);
2232 /****************************************************************************
2233 Reply to a TRANS2_FINDNEXT.
2234 ****************************************************************************/
2236 static void call_trans2findnext(connection_struct *conn,
2237 struct smb_request *req,
2238 char **pparams, int total_params,
2239 char **ppdata, int total_data,
2240 unsigned int max_data_bytes)
2242 /* We must be careful here that we don't return more than the
2243 allowed number of data bytes. If this means returning fewer than
2244 maxentries then so be it. We assume that the redirector has
2245 enough room for the fixed number of parameter bytes it has
2247 char *params = *pparams;
2248 char *pdata = *ppdata;
2254 uint16 findnext_flags;
2255 bool close_after_request;
2257 bool requires_resume_key;
2259 bool mask_contains_wcard = False;
2260 char *resume_name = NULL;
2261 const char *mask = NULL;
2262 const char *directory = NULL;
2266 int i, last_entry_off=0;
2267 bool finished = False;
2268 bool dont_descend = False;
2269 bool out_of_space = False;
2270 int space_remaining;
2271 struct ea_list *ea_list = NULL;
2272 NTSTATUS ntstatus = NT_STATUS_OK;
2273 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2274 TALLOC_CTX *ctx = talloc_tos();
2276 if (total_params < 13) {
2277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2281 dptr_num = SVAL(params,0);
2282 maxentries = SVAL(params,2);
2283 info_level = SVAL(params,4);
2284 resume_key = IVAL(params,6);
2285 findnext_flags = SVAL(params,10);
2286 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2287 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2288 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2289 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2291 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2293 total_params - 12, STR_TERMINATE, &ntstatus,
2294 &mask_contains_wcard);
2295 if (!NT_STATUS_IS_OK(ntstatus)) {
2296 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2297 complain (it thinks we're asking for the directory above the shared
2298 path or an invalid name). Catch this as the resume name is only compared, never used in
2299 a file access. JRA. */
2300 srvstr_pull_talloc(ctx, params, req->flags2,
2301 &resume_name, params+12,
2305 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2306 reply_nterror(req, ntstatus);
2311 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2312 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2313 resume_key = %d resume name = %s continue=%d level = %d\n",
2314 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2315 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2318 /* W2K3 seems to treat zero as 1. */
2322 switch (info_level) {
2323 case SMB_FIND_INFO_STANDARD:
2324 case SMB_FIND_EA_SIZE:
2325 case SMB_FIND_EA_LIST:
2326 case SMB_FIND_FILE_DIRECTORY_INFO:
2327 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2328 case SMB_FIND_FILE_NAMES_INFO:
2329 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2330 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2331 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2333 case SMB_FIND_FILE_UNIX:
2334 case SMB_FIND_FILE_UNIX_INFO2:
2335 /* Always use filesystem for UNIX mtime query. */
2336 ask_sharemode = false;
2337 if (!lp_unix_extensions()) {
2338 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2343 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2347 if (info_level == SMB_FIND_EA_LIST) {
2350 if (total_data < 4) {
2351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2355 ea_size = IVAL(pdata,0);
2356 if (ea_size != total_data) {
2357 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2358 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2359 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2363 if (!lp_ea_support(SNUM(conn))) {
2364 reply_doserror(req, ERRDOS, ERReasnotsupported);
2368 /* Pull out the list of names. */
2369 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2371 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2376 *ppdata = (char *)SMB_REALLOC(
2377 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2378 if(*ppdata == NULL) {
2379 reply_nterror(req, NT_STATUS_NO_MEMORY);
2384 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2386 /* Realloc the params space */
2387 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2388 if(*pparams == NULL ) {
2389 reply_nterror(req, NT_STATUS_NO_MEMORY);
2395 /* Check that the dptr is valid */
2396 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2397 reply_doserror(req, ERRDOS, ERRnofiles);
2401 string_set(&conn->dirpath,dptr_path(dptr_num));
2403 /* Get the wildcard mask from the dptr */
2404 if((p = dptr_wcard(dptr_num))== NULL) {
2405 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2406 reply_doserror(req, ERRDOS, ERRnofiles);
2411 directory = conn->dirpath;
2413 /* Get the attr mask from the dptr */
2414 dirtype = dptr_attr(dptr_num);
2416 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2417 dptr_num, mask, dirtype,
2419 dptr_TellDir(conn->dirptr)));
2421 /* Initialize per TRANS2_FIND_NEXT operation data */
2422 dptr_init_search_op(conn->dirptr);
2424 /* We don't need to check for VOL here as this is returned by
2425 a different TRANS2 call. */
2427 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2428 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2429 dont_descend = True;
2432 space_remaining = max_data_bytes;
2433 out_of_space = False;
2436 * Seek to the correct position. We no longer use the resume key but
2437 * depend on the last file name instead.
2440 if(*resume_name && !continue_bit) {
2443 long current_pos = 0;
2445 * Remember, name_to_8_3 is called by
2446 * get_lanman2_dir_entry(), so the resume name
2447 * could be mangled. Ensure we check the unmangled name.
2450 if (mangle_is_mangled(resume_name, conn->params)) {
2451 char *new_resume_name = NULL;
2452 mangle_lookup_name_from_8_3(ctx,
2456 if (new_resume_name) {
2457 resume_name = new_resume_name;
2462 * Fix for NT redirector problem triggered by resume key indexes
2463 * changing between directory scans. We now return a resume key of 0
2464 * and instead look for the filename to continue from (also given
2465 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2466 * findfirst/findnext (as is usual) then the directory pointer
2467 * should already be at the correct place.
2470 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2471 } /* end if resume_name && !continue_bit */
2473 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2474 bool got_exact_match = False;
2476 /* this is a heuristic to avoid seeking the dirptr except when
2477 absolutely necessary. It allows for a filename of about 40 chars */
2478 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2479 out_of_space = True;
2482 finished = !get_lanman2_dir_entry(ctx,
2485 mask,dirtype,info_level,
2486 requires_resume_key,dont_descend,
2489 space_remaining, &out_of_space,
2491 &last_entry_off, ea_list);
2494 if (finished && out_of_space)
2497 if (!finished && !out_of_space)
2501 * As an optimisation if we know we aren't looking
2502 * for a wildcard name (ie. the name matches the wildcard exactly)
2503 * then we can finish on any (first) match.
2504 * This speeds up large directory searches. JRA.
2510 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2513 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2514 smb_fn_name(req->cmd),
2515 mask, directory, dirtype, numentries ) );
2517 /* Check if we can close the dirptr */
2518 if(close_after_request || (finished && close_if_end)) {
2519 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2520 dptr_close(&dptr_num); /* This frees up the saved mask */
2523 /* Set up the return parameter block */
2524 SSVAL(params,0,numentries);
2525 SSVAL(params,2,finished);
2526 SSVAL(params,4,0); /* Never an EA error */
2527 SSVAL(params,6,last_entry_off);
2529 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2535 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2537 E_md4hash(lp_servicename(SNUM(conn)),objid);
2541 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2543 SMB_ASSERT(extended_info != NULL);
2545 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2546 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2547 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2548 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2549 #ifdef SAMBA_VERSION_REVISION
2550 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2552 extended_info->samba_subversion = 0;
2553 #ifdef SAMBA_VERSION_RC_RELEASE
2554 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2556 #ifdef SAMBA_VERSION_PRE_RELEASE
2557 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2560 #ifdef SAMBA_VERSION_VENDOR_PATCH
2561 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2563 extended_info->samba_gitcommitdate = 0;
2564 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2565 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2568 memset(extended_info->samba_version_string, 0,
2569 sizeof(extended_info->samba_version_string));
2571 snprintf (extended_info->samba_version_string,
2572 sizeof(extended_info->samba_version_string),
2573 "%s", samba_version_string());
2576 /****************************************************************************
2577 Reply to a TRANS2_QFSINFO (query filesystem info).
2578 ****************************************************************************/
2580 static void call_trans2qfsinfo(connection_struct *conn,
2581 struct smb_request *req,
2582 char **pparams, int total_params,
2583 char **ppdata, int total_data,
2584 unsigned int max_data_bytes)
2586 char *pdata, *end_data;
2587 char *params = *pparams;
2591 const char *vname = volume_label(SNUM(conn));
2592 int snum = SNUM(conn);
2593 char *fstype = lp_fstype(SNUM(conn));
2594 uint32 additional_flags = 0;
2596 if (total_params < 2) {
2597 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2601 info_level = SVAL(params,0);
2604 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2605 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2606 "info level (0x%x) on IPC$.\n",
2607 (unsigned int)info_level));
2608 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2613 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2614 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2615 DEBUG(0,("call_trans2qfsinfo: encryption required "
2616 "and info level 0x%x sent.\n",
2617 (unsigned int)info_level));
2618 exit_server_cleanly("encryption required "
2624 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2626 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2627 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2628 reply_doserror(req, ERRSRV, ERRinvdevice);
2632 *ppdata = (char *)SMB_REALLOC(
2633 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2634 if (*ppdata == NULL ) {
2635 reply_nterror(req, NT_STATUS_NO_MEMORY);
2640 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2641 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2643 switch (info_level) {
2644 case SMB_INFO_ALLOCATION:
2646 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2648 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2649 reply_unixerror(req, ERRHRD, ERRgeneral);
2653 block_size = lp_block_size(snum);
2654 if (bsize < block_size) {
2655 uint64_t factor = block_size/bsize;
2660 if (bsize > block_size) {
2661 uint64_t factor = bsize/block_size;
2666 bytes_per_sector = 512;
2667 sectors_per_unit = bsize/bytes_per_sector;
2669 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2670 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2671 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2673 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2674 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2675 SIVAL(pdata,l1_cUnit,dsize);
2676 SIVAL(pdata,l1_cUnitAvail,dfree);
2677 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2681 case SMB_INFO_VOLUME:
2682 /* Return volume name */
2684 * Add volume serial number - hash of a combination of
2685 * the called hostname and the service name.
2687 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2689 * Win2k3 and previous mess this up by sending a name length
2690 * one byte short. I believe only older clients (OS/2 Win9x) use
2691 * this call so try fixing this by adding a terminating null to
2692 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2696 pdata+l2_vol_szVolLabel, vname,
2697 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2698 STR_NOALIGN|STR_TERMINATE);
2699 SCVAL(pdata,l2_vol_cch,len);
2700 data_len = l2_vol_szVolLabel + len;
2701 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2702 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2706 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2707 case SMB_FS_ATTRIBUTE_INFORMATION:
2709 additional_flags = 0;
2710 #if defined(HAVE_SYS_QUOTAS)
2711 additional_flags |= FILE_VOLUME_QUOTAS;
2714 if(lp_nt_acl_support(SNUM(conn))) {
2715 additional_flags |= FILE_PERSISTENT_ACLS;
2718 /* Capabilities are filled in at connection time through STATVFS call */
2719 additional_flags |= conn->fs_capabilities;
2721 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2722 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2723 additional_flags); /* FS ATTRIBUTES */
2725 SIVAL(pdata,4,255); /* Max filename component length */
2726 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2727 and will think we can't do long filenames */
2728 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2729 PTR_DIFF(end_data, pdata+12),
2732 data_len = 12 + len;
2735 case SMB_QUERY_FS_LABEL_INFO:
2736 case SMB_FS_LABEL_INFORMATION:
2737 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2738 PTR_DIFF(end_data, pdata+4), 0);
2743 case SMB_QUERY_FS_VOLUME_INFO:
2744 case SMB_FS_VOLUME_INFORMATION:
2747 * Add volume serial number - hash of a combination of
2748 * the called hostname and the service name.
2750 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2751 (str_checksum(get_local_machine_name())<<16));
2753 /* Max label len is 32 characters. */
2754 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2755 PTR_DIFF(end_data, pdata+18),
2757 SIVAL(pdata,12,len);
2760 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2761 (int)strlen(vname),vname, lp_servicename(snum)));
2764 case SMB_QUERY_FS_SIZE_INFO:
2765 case SMB_FS_SIZE_INFORMATION:
2767 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2769 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2770 reply_unixerror(req, ERRHRD, ERRgeneral);
2773 block_size = lp_block_size(snum);
2774 if (bsize < block_size) {
2775 uint64_t factor = block_size/bsize;
2780 if (bsize > block_size) {
2781 uint64_t factor = bsize/block_size;
2786 bytes_per_sector = 512;
2787 sectors_per_unit = bsize/bytes_per_sector;
2788 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2789 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2790 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2791 SBIG_UINT(pdata,0,dsize);
2792 SBIG_UINT(pdata,8,dfree);
2793 SIVAL(pdata,16,sectors_per_unit);
2794 SIVAL(pdata,20,bytes_per_sector);
2798 case SMB_FS_FULL_SIZE_INFORMATION:
2800 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2802 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2803 reply_unixerror(req, ERRHRD, ERRgeneral);
2806 block_size = lp_block_size(snum);
2807 if (bsize < block_size) {
2808 uint64_t factor = block_size/bsize;
2813 if (bsize > block_size) {
2814 uint64_t factor = bsize/block_size;
2819 bytes_per_sector = 512;
2820 sectors_per_unit = bsize/bytes_per_sector;
2821 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2822 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2823 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2824 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2825 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2826 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2827 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2828 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2832 case SMB_QUERY_FS_DEVICE_INFO:
2833 case SMB_FS_DEVICE_INFORMATION:
2835 SIVAL(pdata,0,0); /* dev type */
2836 SIVAL(pdata,4,0); /* characteristics */
2839 #ifdef HAVE_SYS_QUOTAS
2840 case SMB_FS_QUOTA_INFORMATION:
2842 * what we have to send --metze:
2844 * Unknown1: 24 NULL bytes
2845 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2846 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2847 * Quota Flags: 2 byte :
2848 * Unknown3: 6 NULL bytes
2852 * details for Quota Flags:
2854 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2855 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2856 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2857 * 0x0001 Enable Quotas: enable quota for this fs
2861 /* we need to fake up a fsp here,
2862 * because its not send in this call
2865 SMB_NTQUOTA_STRUCT quotas;
2868 ZERO_STRUCT(quotas);
2874 if (conn->server_info->utok.uid != 0) {
2875 DEBUG(0,("set_user_quota: access_denied "
2876 "service [%s] user [%s]\n",
2877 lp_servicename(SNUM(conn)),
2878 conn->server_info->unix_name));
2879 reply_doserror(req, ERRDOS, ERRnoaccess);
2883 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2884 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2885 reply_doserror(req, ERRSRV, ERRerror);
2891 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2893 /* Unknown1 24 NULL bytes*/
2894 SBIG_UINT(pdata,0,(uint64_t)0);
2895 SBIG_UINT(pdata,8,(uint64_t)0);
2896 SBIG_UINT(pdata,16,(uint64_t)0);
2898 /* Default Soft Quota 8 bytes */
2899 SBIG_UINT(pdata,24,quotas.softlim);
2901 /* Default Hard Quota 8 bytes */
2902 SBIG_UINT(pdata,32,quotas.hardlim);
2904 /* Quota flag 2 bytes */
2905 SSVAL(pdata,40,quotas.qflags);
2907 /* Unknown3 6 NULL bytes */
2913 #endif /* HAVE_SYS_QUOTAS */
2914 case SMB_FS_OBJECTID_INFORMATION:
2916 unsigned char objid[16];
2917 struct smb_extended_info extended_info;
2918 memcpy(pdata,create_volume_objectid(conn, objid),16);
2919 samba_extended_info_version (&extended_info);
2920 SIVAL(pdata,16,extended_info.samba_magic);
2921 SIVAL(pdata,20,extended_info.samba_version);
2922 SIVAL(pdata,24,extended_info.samba_subversion);
2923 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2924 memcpy(pdata+36,extended_info.samba_version_string,28);
2930 * Query the version and capabilities of the CIFS UNIX extensions
2934 case SMB_QUERY_CIFS_UNIX_INFO:
2936 bool large_write = lp_min_receive_file_size() &&
2937 !srv_is_signing_active(smbd_server_conn);
2938 bool large_read = !srv_is_signing_active(smbd_server_conn);
2939 int encrypt_caps = 0;
2941 if (!lp_unix_extensions()) {
2942 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2946 switch (conn->encrypt_level) {
2952 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2955 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2956 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2957 large_write = false;
2963 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2964 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2966 /* We have POSIX ACLs, pathname, encryption,
2967 * large read/write, and locking capability. */
2969 SBIG_UINT(pdata,4,((uint64_t)(
2970 CIFS_UNIX_POSIX_ACLS_CAP|
2971 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2972 CIFS_UNIX_FCNTL_LOCKS_CAP|
2973 CIFS_UNIX_EXTATTR_CAP|
2974 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2976 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2978 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2982 case SMB_QUERY_POSIX_FS_INFO:
2985 vfs_statvfs_struct svfs;
2987 if (!lp_unix_extensions()) {
2988 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2992 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2996 SIVAL(pdata,0,svfs.OptimalTransferSize);
2997 SIVAL(pdata,4,svfs.BlockSize);
2998 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2999 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3000 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3001 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3002 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3003 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3004 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3006 } else if (rc == EOPNOTSUPP) {
3007 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3009 #endif /* EOPNOTSUPP */
3011 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3012 reply_doserror(req, ERRSRV, ERRerror);
3018 case SMB_QUERY_POSIX_WHOAMI:
3024 if (!lp_unix_extensions()) {
3025 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3029 if (max_data_bytes < 40) {
3030 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3034 /* We ARE guest if global_sid_Builtin_Guests is
3035 * in our list of SIDs.
3037 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3038 conn->server_info->ptok)) {
3039 flags |= SMB_WHOAMI_GUEST;
3042 /* We are NOT guest if global_sid_Authenticated_Users
3043 * is in our list of SIDs.
3045 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3046 conn->server_info->ptok)) {
3047 flags &= ~SMB_WHOAMI_GUEST;
3050 /* NOTE: 8 bytes for UID/GID, irrespective of native
3051 * platform size. This matches
3052 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3054 data_len = 4 /* flags */
3061 + 4 /* pad/reserved */
3062 + (conn->server_info->utok.ngroups * 8)
3064 + (conn->server_info->ptok->num_sids *
3068 SIVAL(pdata, 0, flags);
3069 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3071 (uint64_t)conn->server_info->utok.uid);
3072 SBIG_UINT(pdata, 16,
3073 (uint64_t)conn->server_info->utok.gid);
3076 if (data_len >= max_data_bytes) {
3077 /* Potential overflow, skip the GIDs and SIDs. */
3079 SIVAL(pdata, 24, 0); /* num_groups */
3080 SIVAL(pdata, 28, 0); /* num_sids */
3081 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3082 SIVAL(pdata, 36, 0); /* reserved */
3088 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3089 SIVAL(pdata, 28, conn->server_info->num_sids);
3091 /* We walk the SID list twice, but this call is fairly
3092 * infrequent, and I don't expect that it's performance
3093 * sensitive -- jpeach
3095 for (i = 0, sid_bytes = 0;
3096 i < conn->server_info->ptok->num_sids; ++i) {
3097 sid_bytes += ndr_size_dom_sid(
3098 &conn->server_info->ptok->user_sids[i],
3103 /* SID list byte count */
3104 SIVAL(pdata, 32, sid_bytes);
3106 /* 4 bytes pad/reserved - must be zero */
3107 SIVAL(pdata, 36, 0);
3111 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3112 SBIG_UINT(pdata, data_len,
3113 (uint64_t)conn->server_info->utok.groups[i]);
3119 i < conn->server_info->ptok->num_sids; ++i) {
3120 int sid_len = ndr_size_dom_sid(
3121 &conn->server_info->ptok->user_sids[i],
3125 sid_linearize(pdata + data_len, sid_len,
3126 &conn->server_info->ptok->user_sids[i]);
3127 data_len += sid_len;
3133 case SMB_MAC_QUERY_FS_INFO:
3135 * Thursby MAC extension... ONLY on NTFS filesystems
3136 * once we do streams then we don't need this
3138 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3140 SIVAL(pdata,84,0x100); /* Don't support mac... */
3145 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3150 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3153 DEBUG( 4, ( "%s info_level = %d\n",
3154 smb_fn_name(req->cmd), info_level) );
3159 /****************************************************************************
3160 Reply to a TRANS2_SETFSINFO (set filesystem info).
3161 ****************************************************************************/
3163 static void call_trans2setfsinfo(connection_struct *conn,
3164 struct smb_request *req,
3165 char **pparams, int total_params,
3166 char **ppdata, int total_data,
3167 unsigned int max_data_bytes)
3169 char *pdata = *ppdata;
3170 char *params = *pparams;
3173 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3176 if (total_params < 4) {
3177 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3183 info_level = SVAL(params,2);
3186 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3187 info_level != SMB_SET_CIFS_UNIX_INFO) {
3188 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3189 "info level (0x%x) on IPC$.\n",
3190 (unsigned int)info_level));
3191 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3196 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3197 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3198 DEBUG(0,("call_trans2setfsinfo: encryption required "
3199 "and info level 0x%x sent.\n",
3200 (unsigned int)info_level));
3201 exit_server_cleanly("encryption required "
3207 switch(info_level) {
3208 case SMB_SET_CIFS_UNIX_INFO:
3210 uint16 client_unix_major;
3211 uint16 client_unix_minor;
3212 uint32 client_unix_cap_low;
3213 uint32 client_unix_cap_high;
3215 if (!lp_unix_extensions()) {
3217 NT_STATUS_INVALID_LEVEL);
3221 /* There should be 12 bytes of capabilities set. */
3222 if (total_data < 8) {
3225 NT_STATUS_INVALID_PARAMETER);
3228 client_unix_major = SVAL(pdata,0);
3229 client_unix_minor = SVAL(pdata,2);
3230 client_unix_cap_low = IVAL(pdata,4);
3231 client_unix_cap_high = IVAL(pdata,8);
3232 /* Just print these values for now. */
3233 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3234 cap_low = 0x%x, cap_high = 0x%x\n",
3235 (unsigned int)client_unix_major,
3236 (unsigned int)client_unix_minor,
3237 (unsigned int)client_unix_cap_low,
3238 (unsigned int)client_unix_cap_high ));
3240 /* Here is where we must switch to posix pathname processing... */
3241 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3242 lp_set_posix_pathnames();
3243 mangle_change_to_posix();
3246 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3247 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3248 /* Client that knows how to do posix locks,
3249 * but not posix open/mkdir operations. Set a
3250 * default type for read/write checks. */
3252 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3258 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3261 size_t param_len = 0;
3262 size_t data_len = total_data;
3264 if (!lp_unix_extensions()) {
3267 NT_STATUS_INVALID_LEVEL);
3271 if (lp_smb_encrypt(SNUM(conn)) == false) {
3274 NT_STATUS_NOT_SUPPORTED);
3278 DEBUG( 4,("call_trans2setfsinfo: "
3279 "request transport encryption.\n"));
3281 status = srv_request_encryption_setup(conn,
3282 (unsigned char **)ppdata,
3284 (unsigned char **)pparams,
3287 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3288 !NT_STATUS_IS_OK(status)) {
3289 reply_nterror(req, status);
3293 send_trans2_replies(conn, req,
3300 if (NT_STATUS_IS_OK(status)) {
3301 /* Server-side transport
3302 * encryption is now *on*. */
3303 status = srv_encryption_start(conn);
3304 if (!NT_STATUS_IS_OK(status)) {
3305 exit_server_cleanly(
3306 "Failure in setting "
3307 "up encrypted transport");
3313 case SMB_FS_QUOTA_INFORMATION:
3315 files_struct *fsp = NULL;
3316 SMB_NTQUOTA_STRUCT quotas;
3318 ZERO_STRUCT(quotas);
3321 if ((conn->server_info->utok.uid != 0)
3322 ||!CAN_WRITE(conn)) {
3323 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3324 lp_servicename(SNUM(conn)),
3325 conn->server_info->unix_name));
3326 reply_doserror(req, ERRSRV, ERRaccess);
3330 /* note: normaly there're 48 bytes,
3331 * but we didn't use the last 6 bytes for now
3334 fsp = file_fsp(req, SVAL(params,0));
3336 if (!check_fsp_ntquota_handle(conn, req,
3338 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3340 req, NT_STATUS_INVALID_HANDLE);
3344 if (total_data < 42) {
3345 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3349 NT_STATUS_INVALID_PARAMETER);
3353 /* unknown_1 24 NULL bytes in pdata*/
3355 /* the soft quotas 8 bytes (uint64_t)*/
3356 quotas.softlim = (uint64_t)IVAL(pdata,24);
3357 #ifdef LARGE_SMB_OFF_T
3358 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3359 #else /* LARGE_SMB_OFF_T */
3360 if ((IVAL(pdata,28) != 0)&&
3361 ((quotas.softlim != 0xFFFFFFFF)||
3362 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3363 /* more than 32 bits? */
3366 NT_STATUS_INVALID_PARAMETER);
3369 #endif /* LARGE_SMB_OFF_T */
3371 /* the hard quotas 8 bytes (uint64_t)*/
3372 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3373 #ifdef LARGE_SMB_OFF_T
3374 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3375 #else /* LARGE_SMB_OFF_T */
3376 if ((IVAL(pdata,36) != 0)&&
3377 ((quotas.hardlim != 0xFFFFFFFF)||
3378 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3379 /* more than 32 bits? */
3382 NT_STATUS_INVALID_PARAMETER);
3385 #endif /* LARGE_SMB_OFF_T */
3387 /* quota_flags 2 bytes **/
3388 quotas.qflags = SVAL(pdata,40);
3390 /* unknown_2 6 NULL bytes follow*/
3392 /* now set the quotas */
3393 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3394 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3395 reply_doserror(req, ERRSRV, ERRerror);
3402 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3404 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3410 * sending this reply works fine,
3411 * but I'm not sure it's the same
3412 * like windows do...
3415 reply_outbuf(req, 10, 0);
3418 #if defined(HAVE_POSIX_ACLS)
3419 /****************************************************************************
3420 Utility function to count the number of entries in a POSIX acl.
3421 ****************************************************************************/
3423 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3425 unsigned int ace_count = 0;
3426 int entry_id = SMB_ACL_FIRST_ENTRY;
3427 SMB_ACL_ENTRY_T entry;
3429 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3431 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3432 entry_id = SMB_ACL_NEXT_ENTRY;
3439 /****************************************************************************
3440 Utility function to marshall a POSIX acl into wire format.
3441 ****************************************************************************/
3443 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3445 int entry_id = SMB_ACL_FIRST_ENTRY;
3446 SMB_ACL_ENTRY_T entry;
3448 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3449 SMB_ACL_TAG_T tagtype;
3450 SMB_ACL_PERMSET_T permset;
3451 unsigned char perms = 0;
3452 unsigned int own_grp;
3455 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3456 entry_id = SMB_ACL_NEXT_ENTRY;
3459 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3460 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3464 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3465 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3469 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3470 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3471 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3473 SCVAL(pdata,1,perms);
3476 case SMB_ACL_USER_OBJ:
3477 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3478 own_grp = (unsigned int)pst->st_ex_uid;
3479 SIVAL(pdata,2,own_grp);
3484 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3486 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3489 own_grp = (unsigned int)*puid;
3490 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3491 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3492 SIVAL(pdata,2,own_grp);
3496 case SMB_ACL_GROUP_OBJ:
3497 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3498 own_grp = (unsigned int)pst->st_ex_gid;
3499 SIVAL(pdata,2,own_grp);
3504 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3506 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3509 own_grp = (unsigned int)*pgid;
3510 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3511 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3512 SIVAL(pdata,2,own_grp);
3517 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3518 SIVAL(pdata,2,0xFFFFFFFF);
3519 SIVAL(pdata,6,0xFFFFFFFF);
3522 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3523 SIVAL(pdata,2,0xFFFFFFFF);
3524 SIVAL(pdata,6,0xFFFFFFFF);
3527 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3530 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3537 /****************************************************************************
3538 Store the FILE_UNIX_BASIC info.
3539 ****************************************************************************/
3541 static char *store_file_unix_basic(connection_struct *conn,
3544 const SMB_STRUCT_STAT *psbuf)
3546 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3547 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3549 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3552 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3555 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3556 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3557 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3560 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3564 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3568 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3571 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3575 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3579 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3582 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3586 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3593 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3594 * the chflags(2) (or equivalent) flags.
3596 * XXX: this really should be behind the VFS interface. To do this, we would
3597 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3598 * Each VFS module could then implement its own mapping as appropriate for the
3599 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3601 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3605 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3609 { UF_IMMUTABLE, EXT_IMMUTABLE },
3613 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3617 { UF_HIDDEN, EXT_HIDDEN },
3620 /* Do not remove. We need to guarantee that this array has at least one
3621 * entry to build on HP-UX.
3627 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3628 uint32 *smb_fflags, uint32 *smb_fmask)
3632 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3633 *smb_fmask |= info2_flags_map[i].smb_fflag;
3634 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3635 *smb_fflags |= info2_flags_map[i].smb_fflag;
3640 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3641 const uint32 smb_fflags,
3642 const uint32 smb_fmask,
3645 uint32 max_fmask = 0;
3648 *stat_fflags = psbuf->st_ex_flags;
3650 /* For each flags requested in smb_fmask, check the state of the
3651 * corresponding flag in smb_fflags and set or clear the matching
3655 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3656 max_fmask |= info2_flags_map[i].smb_fflag;
3657 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3658 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3659 *stat_fflags |= info2_flags_map[i].stat_fflag;
3661 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3666 /* If smb_fmask is asking to set any bits that are not supported by
3667 * our flag mappings, we should fail.
3669 if ((smb_fmask & max_fmask) != smb_fmask) {
3677 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3678 * of file flags and birth (create) time.
3680 static char *store_file_unix_basic_info2(connection_struct *conn,
3683 const SMB_STRUCT_STAT *psbuf)
3685 uint32 file_flags = 0;
3686 uint32 flags_mask = 0;
3688 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3690 /* Create (birth) time 64 bit */
3691 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3694 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3695 SIVAL(pdata, 0, file_flags); /* flags */
3696 SIVAL(pdata, 4, flags_mask); /* mask */
3702 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3703 const struct stream_struct *streams,
3705 unsigned int max_data_bytes,
3706 unsigned int *data_size)
3709 unsigned int ofs = 0;
3711 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3712 unsigned int next_offset;
3714 smb_ucs2_t *namebuf;
3716 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3717 streams[i].name, &namelen) ||
3720 return NT_STATUS_INVALID_PARAMETER;
3724 * name_buf is now null-terminated, we need to marshall as not
3730 SIVAL(data, ofs+4, namelen);
3731 SOFF_T(data, ofs+8, streams[i].size);
3732 SOFF_T(data, ofs+16, streams[i].alloc_size);
3733 memcpy(data+ofs+24, namebuf, namelen);
3734 TALLOC_FREE(namebuf);
3736 next_offset = ofs + 24 + namelen;
3738 if (i == num_streams-1) {
3739 SIVAL(data, ofs, 0);
3742 unsigned int align = ndr_align_size(next_offset, 8);
3744 memset(data+next_offset, 0, align);
3745 next_offset += align;
3747 SIVAL(data, ofs, next_offset - ofs);
3756 return NT_STATUS_OK;
3759 /****************************************************************************
3760 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3761 ****************************************************************************/
3763 static void call_trans2qpipeinfo(connection_struct *conn,
3764 struct smb_request *req,
3765 unsigned int tran_call,
3766 char **pparams, int total_params,
3767 char **ppdata, int total_data,
3768 unsigned int max_data_bytes)
3770 char *params = *pparams;
3771 char *pdata = *ppdata;
3772 unsigned int data_size = 0;
3773 unsigned int param_size = 2;
3778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3782 if (total_params < 4) {
3783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3787 fsp = file_fsp(req, SVAL(params,0));
3788 if (!fsp_is_np(fsp)) {
3789 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3793 info_level = SVAL(params,2);
3795 *pparams = (char *)SMB_REALLOC(*pparams,2);
3796 if (*pparams == NULL) {
3797 reply_nterror(req, NT_STATUS_NO_MEMORY);
3802 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3803 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3804 if (*ppdata == NULL ) {
3805 reply_nterror(req, NT_STATUS_NO_MEMORY);
3810 switch (info_level) {
3811 case SMB_FILE_STANDARD_INFORMATION:
3813 SOFF_T(pdata,0,4096LL);
3820 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3824 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3830 /****************************************************************************
3831 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3832 file name or file id).
3833 ****************************************************************************/
3835 static void call_trans2qfilepathinfo(connection_struct *conn,
3836 struct smb_request *req,
3837 unsigned int tran_call,
3838 char **pparams, int total_params,
3839 char **ppdata, int total_data,
3840 unsigned int max_data_bytes)
3842 char *params = *pparams;
3843 char *pdata = *ppdata;
3844 char *dstart, *dend;
3848 SMB_OFF_T file_size=0;
3849 uint64_t allocation_size=0;
3850 unsigned int data_size = 0;
3851 unsigned int param_size = 2;
3852 SMB_STRUCT_STAT sbuf;
3853 char *dos_fname = NULL;
3855 struct smb_filename *smb_fname = NULL;
3860 bool delete_pending = False;
3862 time_t create_time, mtime, atime;
3863 struct timespec create_time_ts, mtime_ts, atime_ts;
3864 struct timespec write_time_ts;
3865 files_struct *fsp = NULL;
3866 struct file_id fileid;
3867 struct ea_list *ea_list = NULL;
3868 char *lock_data = NULL;
3869 bool ms_dfs_link = false;
3870 TALLOC_CTX *ctx = talloc_tos();
3873 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3878 ZERO_STRUCT(write_time_ts);
3880 if (tran_call == TRANSACT2_QFILEINFO) {
3881 if (total_params < 4) {
3882 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3887 call_trans2qpipeinfo(conn, req, tran_call,
3888 pparams, total_params,
3894 fsp = file_fsp(req, SVAL(params,0));
3895 info_level = SVAL(params,2);
3897 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3899 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3900 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3904 /* Initial check for valid fsp ptr. */
3905 if (!check_fsp_open(conn, req, fsp)) {
3909 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3911 reply_nterror(req, NT_STATUS_NO_MEMORY);
3915 if(fsp->fake_file_handle) {
3917 * This is actually for the QUOTA_FAKE_FILE --metze
3920 /* We know this name is ok, it's already passed the checks. */
3922 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3924 * This is actually a QFILEINFO on a directory
3925 * handle (returned from an NT SMB). NT5.0 seems
3926 * to do this call. JRA.
3929 if (INFO_LEVEL_IS_UNIX(info_level)) {
3930 /* Always do lstat for UNIX calls. */
3931 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3932 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3933 reply_unixerror(req,ERRDOS,ERRbadpath);
3936 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3937 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3938 reply_unixerror(req, ERRDOS, ERRbadpath);
3942 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3943 get_file_infos(fileid, &delete_pending, &write_time_ts);
3946 * Original code - this is an open file.
3948 if (!check_fsp(conn, req, fsp)) {
3952 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3953 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3954 reply_unixerror(req, ERRDOS, ERRbadfid);
3957 pos = fsp->fh->position_information;
3958 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3959 get_file_infos(fileid, &delete_pending, &write_time_ts);
3963 NTSTATUS status = NT_STATUS_OK;
3966 if (total_params < 7) {
3967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3971 info_level = SVAL(params,0);
3973 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3975 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3976 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3980 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3982 STR_TERMINATE, &status);
3983 if (!NT_STATUS_IS_OK(status)) {
3984 reply_nterror(req, status);
3988 status = resolve_dfspath(ctx,
3990 req->flags2 & FLAGS2_DFS_PATHNAMES,
3993 if (!NT_STATUS_IS_OK(status)) {
3994 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3995 reply_botherror(req,
3996 NT_STATUS_PATH_NOT_COVERED,
3997 ERRSRV, ERRbadpath);
3999 reply_nterror(req, status);
4003 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
4004 if (!NT_STATUS_IS_OK(status)) {
4005 reply_nterror(req, status);
4008 sbuf = smb_fname->st;
4010 status = get_full_smb_filename(ctx, smb_fname, &fname);
4011 TALLOC_FREE(smb_fname);
4012 if (!NT_STATUS_IS_OK(status)) {
4013 reply_nterror(req, status);
4017 status = check_name(conn, fname);
4018 if (!NT_STATUS_IS_OK(status)) {
4019 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
4020 reply_nterror(req, status);
4024 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4025 && is_ntfs_stream_name(fname)) {
4027 SMB_STRUCT_STAT bsbuf;
4029 status = split_ntfs_stream_name(talloc_tos(), fname,
4031 if (!NT_STATUS_IS_OK(status)) {
4032 DEBUG(10, ("create_file_unixpath: "
4033 "split_ntfs_stream_name failed: %s\n",
4034 nt_errstr(status)));
4035 reply_nterror(req, status);
4039 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4041 if (INFO_LEVEL_IS_UNIX(info_level)) {
4042 /* Always do lstat for UNIX calls. */
4043 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4044 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4045 reply_unixerror(req,ERRDOS,ERRbadpath);
4049 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4050 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4051 reply_unixerror(req,ERRDOS,ERRbadpath);
4056 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4057 get_file_infos(fileid, &delete_pending, NULL);
4058 if (delete_pending) {
4059 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4064 if (INFO_LEVEL_IS_UNIX(info_level)) {
4065 /* Always do lstat for UNIX calls. */
4066 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4067 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4068 reply_unixerror(req, ERRDOS, ERRbadpath);
4072 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4073 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4076 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4077 reply_unixerror(req, ERRDOS, ERRbadpath);
4082 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4083 get_file_infos(fileid, &delete_pending, &write_time_ts);
4084 if (delete_pending) {
4085 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4090 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4091 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4095 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4096 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4098 p = strrchr_m(fname,'/');
4105 mode = dos_mode_msdfs(conn,fname,&sbuf);
4107 mode = dos_mode(conn,fname,&sbuf);
4110 mode = FILE_ATTRIBUTE_NORMAL;
4112 nlink = sbuf.st_ex_nlink;
4114 if (nlink && (mode&aDIR)) {
4118 if ((nlink > 0) && delete_pending) {
4122 fullpathname = fname;
4124 file_size = get_file_size_stat(&sbuf);
4126 /* Pull out any data sent here before we realloc. */
4127 switch (info_level) {
4128 case SMB_INFO_QUERY_EAS_FROM_LIST:
4130 /* Pull any EA list from the data portion. */
4133 if (total_data < 4) {
4135 req, NT_STATUS_INVALID_PARAMETER);
4138 ea_size = IVAL(pdata,0);
4140 if (total_data > 0 && ea_size != total_data) {
4141 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4142 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4144 req, NT_STATUS_INVALID_PARAMETER);
4148 if (!lp_ea_support(SNUM(conn))) {
4149 reply_doserror(req, ERRDOS,
4150 ERReasnotsupported);
4154 /* Pull out the list of names. */
4155 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4158 req, NT_STATUS_INVALID_PARAMETER);
4164 case SMB_QUERY_POSIX_LOCK:
4166 if (fsp == NULL || fsp->fh->fd == -1) {
4167 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4171 if (total_data != POSIX_LOCK_DATA_SIZE) {
4173 req, NT_STATUS_INVALID_PARAMETER);
4177 /* Copy the lock range data. */
4178 lock_data = (char *)TALLOC_MEMDUP(
4179 ctx, pdata, total_data);
4181 reply_nterror(req, NT_STATUS_NO_MEMORY);
4189 *pparams = (char *)SMB_REALLOC(*pparams,2);
4190 if (*pparams == NULL) {
4191 reply_nterror(req, NT_STATUS_NO_MEMORY);
4196 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4197 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4198 if (*ppdata == NULL ) {
4199 reply_nterror(req, NT_STATUS_NO_MEMORY);
4204 dend = dstart + data_size - 1;
4206 create_time_ts = sbuf.st_ex_btime;
4207 mtime_ts = sbuf.st_ex_mtime;
4208 atime_ts = sbuf.st_ex_atime;
4210 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4213 /* Do we have this path open ? */
4215 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4216 fsp1 = file_find_di_first(fileid);
4217 if (fsp1 && fsp1->initial_allocation_size) {
4218 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4222 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4223 mtime_ts = write_time_ts;
4226 if (lp_dos_filetime_resolution(SNUM(conn))) {
4227 dos_filetime_timespec(&create_time_ts);
4228 dos_filetime_timespec(&mtime_ts);
4229 dos_filetime_timespec(&atime_ts);
4232 create_time = convert_timespec_to_time_t(create_time_ts);
4233 mtime = convert_timespec_to_time_t(mtime_ts);
4234 atime = convert_timespec_to_time_t(atime_ts);
4236 /* NT expects the name to be in an exact form of the *full*
4237 filename. See the trans2 torture test */
4238 if (ISDOT(base_name)) {
4239 dos_fname = talloc_strdup(ctx, "\\");
4241 reply_nterror(req, NT_STATUS_NO_MEMORY);
4245 dos_fname = talloc_asprintf(ctx,
4249 reply_nterror(req, NT_STATUS_NO_MEMORY);
4252 string_replace(dos_fname, '/', '\\');
4255 switch (info_level) {
4256 case SMB_INFO_STANDARD:
4257 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4259 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4260 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4261 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4262 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4263 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4264 SSVAL(pdata,l1_attrFile,mode);
4267 case SMB_INFO_QUERY_EA_SIZE:
4269 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4270 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4272 srv_put_dos_date2(pdata,0,create_time);
4273 srv_put_dos_date2(pdata,4,atime);
4274 srv_put_dos_date2(pdata,8,mtime); /* write time */
4275 SIVAL(pdata,12,(uint32)file_size);
4276 SIVAL(pdata,16,(uint32)allocation_size);
4277 SSVAL(pdata,20,mode);
4278 SIVAL(pdata,22,ea_size);
4282 case SMB_INFO_IS_NAME_VALID:
4283 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4284 if (tran_call == TRANSACT2_QFILEINFO) {
4285 /* os/2 needs this ? really ?*/
4286 reply_doserror(req, ERRDOS, ERRbadfunc);
4293 case SMB_INFO_QUERY_EAS_FROM_LIST:
4295 size_t total_ea_len = 0;
4296 struct ea_list *ea_file_list = NULL;
4298 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4300 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4301 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4303 if (!ea_list || (total_ea_len > data_size)) {
4305 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4309 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4313 case SMB_INFO_QUERY_ALL_EAS:
4315 /* We have data_size bytes to put EA's into. */
4316 size_t total_ea_len = 0;
4318 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4320 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4321 if (!ea_list || (total_ea_len > data_size)) {
4323 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4327 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4331 case SMB_FILE_BASIC_INFORMATION:
4332 case SMB_QUERY_FILE_BASIC_INFO:
4334 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4335 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4336 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4338 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4342 put_long_date_timespec(pdata,create_time_ts);
4343 put_long_date_timespec(pdata+8,atime_ts);
4344 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4345 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4346 SIVAL(pdata,32,mode);
4348 DEBUG(5,("SMB_QFBI - "));
4349 DEBUG(5,("create: %s ", ctime(&create_time)));
4350 DEBUG(5,("access: %s ", ctime(&atime)));
4351 DEBUG(5,("write: %s ", ctime(&mtime)));
4352 DEBUG(5,("change: %s ", ctime(&mtime)));
4353 DEBUG(5,("mode: %x\n", mode));
4356 case SMB_FILE_STANDARD_INFORMATION:
4357 case SMB_QUERY_FILE_STANDARD_INFO:
4359 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4361 SOFF_T(pdata,0,allocation_size);
4362 SOFF_T(pdata,8,file_size);
4363 SIVAL(pdata,16,nlink);
4364 SCVAL(pdata,20,delete_pending?1:0);
4365 SCVAL(pdata,21,(mode&aDIR)?1:0);
4366 SSVAL(pdata,22,0); /* Padding. */
4369 case SMB_FILE_EA_INFORMATION:
4370 case SMB_QUERY_FILE_EA_INFO:
4372 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4373 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4375 SIVAL(pdata,0,ea_size);
4379 /* Get the 8.3 name - used if NT SMB was negotiated. */
4380 case SMB_QUERY_FILE_ALT_NAME_INFO:
4381 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4383 char mangled_name[13];
4384 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4385 if (!name_to_8_3(base_name,mangled_name,
4386 True,conn->params)) {
4389 NT_STATUS_NO_MEMORY);
4391 len = srvstr_push(dstart, req->flags2,
4392 pdata+4, mangled_name,
4393 PTR_DIFF(dend, pdata+4),
4395 data_size = 4 + len;
4400 case SMB_QUERY_FILE_NAME_INFO:
4402 this must be *exactly* right for ACLs on mapped drives to work
4404 len = srvstr_push(dstart, req->flags2,
4406 PTR_DIFF(dend, pdata+4),
4408 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4409 data_size = 4 + len;
4413 case SMB_FILE_ALLOCATION_INFORMATION:
4414 case SMB_QUERY_FILE_ALLOCATION_INFO:
4415 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4417 SOFF_T(pdata,0,allocation_size);
4420 case SMB_FILE_END_OF_FILE_INFORMATION:
4421 case SMB_QUERY_FILE_END_OF_FILEINFO:
4422 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4424 SOFF_T(pdata,0,file_size);
4427 case SMB_QUERY_FILE_ALL_INFO:
4428 case SMB_FILE_ALL_INFORMATION:
4430 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4431 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4432 put_long_date_timespec(pdata,create_time_ts);
4433 put_long_date_timespec(pdata+8,atime_ts);
4434 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4435 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4436 SIVAL(pdata,32,mode);
4437 SIVAL(pdata,36,0); /* padding. */
4439 SOFF_T(pdata,0,allocation_size);
4440 SOFF_T(pdata,8,file_size);
4441 SIVAL(pdata,16,nlink);
4442 SCVAL(pdata,20,delete_pending);
4443 SCVAL(pdata,21,(mode&aDIR)?1:0);
4446 SIVAL(pdata,0,ea_size);
4447 pdata += 4; /* EA info */
4448 len = srvstr_push(dstart, req->flags2,
4450 PTR_DIFF(dend, pdata+4),
4454 data_size = PTR_DIFF(pdata,(*ppdata));
4457 case SMB_FILE_INTERNAL_INFORMATION:
4458 /* This should be an index number - looks like
4461 I think this causes us to fail the IFSKIT
4462 BasicFileInformationTest. -tpot */
4464 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4465 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4466 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4470 case SMB_FILE_ACCESS_INFORMATION:
4471 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4473 SIVAL(pdata,0,fsp->access_mask);
4475 /* GENERIC_EXECUTE mapping from Windows */
4476 SIVAL(pdata,0,0x12019F);
4481 case SMB_FILE_NAME_INFORMATION:
4482 /* Pathname with leading '\'. */
4485 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4486 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4487 SIVAL(pdata,0,byte_len);
4488 data_size = 4 + byte_len;
4492 case SMB_FILE_DISPOSITION_INFORMATION:
4493 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4495 SCVAL(pdata,0,delete_pending);
4498 case SMB_FILE_POSITION_INFORMATION:
4499 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4501 SOFF_T(pdata,0,pos);
4504 case SMB_FILE_MODE_INFORMATION:
4505 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4506 SIVAL(pdata,0,mode);
4510 case SMB_FILE_ALIGNMENT_INFORMATION:
4511 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4512 SIVAL(pdata,0,0); /* No alignment needed. */
4517 * NT4 server just returns "invalid query" to this - if we try
4518 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4521 /* The first statement above is false - verified using Thursby
4522 * client against NT4 -- gcolley.
4524 case SMB_QUERY_FILE_STREAM_INFO:
4525 case SMB_FILE_STREAM_INFORMATION: {
4526 unsigned int num_streams;
4527 struct stream_struct *streams;
4530 DEBUG(10,("call_trans2qfilepathinfo: "
4531 "SMB_FILE_STREAM_INFORMATION\n"));
4533 status = SMB_VFS_STREAMINFO(
4534 conn, fsp, fname, talloc_tos(),
4535 &num_streams, &streams);
4537 if (!NT_STATUS_IS_OK(status)) {
4538 DEBUG(10, ("could not get stream info: %s\n",
4539 nt_errstr(status)));
4540 reply_nterror(req, status);
4544 status = marshall_stream_info(num_streams, streams,
4545 pdata, max_data_bytes,
4548 if (!NT_STATUS_IS_OK(status)) {
4549 DEBUG(10, ("marshall_stream_info failed: %s\n",
4550 nt_errstr(status)));
4551 reply_nterror(req, status);
4555 TALLOC_FREE(streams);
4559 case SMB_QUERY_COMPRESSION_INFO:
4560 case SMB_FILE_COMPRESSION_INFORMATION:
4561 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4562 SOFF_T(pdata,0,file_size);
4563 SIVAL(pdata,8,0); /* ??? */
4564 SIVAL(pdata,12,0); /* ??? */
4568 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4569 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4570 put_long_date_timespec(pdata,create_time_ts);
4571 put_long_date_timespec(pdata+8,atime_ts);
4572 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4573 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4574 SOFF_T(pdata,32,allocation_size);
4575 SOFF_T(pdata,40,file_size);
4576 SIVAL(pdata,48,mode);
4577 SIVAL(pdata,52,0); /* ??? */
4581 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4582 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4583 SIVAL(pdata,0,mode);
4589 * CIFS UNIX Extensions.
4592 case SMB_QUERY_FILE_UNIX_BASIC:
4594 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4595 data_size = PTR_DIFF(pdata,(*ppdata));
4599 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4601 for (i=0; i<100; i++)
4602 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4608 case SMB_QUERY_FILE_UNIX_INFO2:
4610 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4611 data_size = PTR_DIFF(pdata,(*ppdata));
4615 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4617 for (i=0; i<100; i++)
4618 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4624 case SMB_QUERY_FILE_UNIX_LINK:
4626 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4629 reply_nterror(req, NT_STATUS_NO_MEMORY);
4633 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4635 if(!S_ISLNK(sbuf.st_ex_mode)) {
4636 reply_unixerror(req, ERRSRV,
4641 reply_unixerror(req, ERRDOS, ERRbadlink);
4644 len = SMB_VFS_READLINK(conn,fullpathname,
4647 reply_unixerror(req, ERRDOS,
4652 len = srvstr_push(dstart, req->flags2,
4654 PTR_DIFF(dend, pdata),
4657 data_size = PTR_DIFF(pdata,(*ppdata));
4662 #if defined(HAVE_POSIX_ACLS)
4663 case SMB_QUERY_POSIX_ACL:
4665 SMB_ACL_T file_acl = NULL;
4666 SMB_ACL_T def_acl = NULL;
4667 uint16 num_file_acls = 0;
4668 uint16 num_def_acls = 0;
4670 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4671 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4673 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4676 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4677 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4681 NT_STATUS_NOT_IMPLEMENTED);
4685 if (S_ISDIR(sbuf.st_ex_mode)) {
4686 if (fsp && fsp->is_directory) {
4687 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4689 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4691 def_acl = free_empty_sys_acl(conn, def_acl);
4694 num_file_acls = count_acl_entries(conn, file_acl);
4695 num_def_acls = count_acl_entries(conn, def_acl);
4697 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4698 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4700 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4701 SMB_POSIX_ACL_HEADER_SIZE) ));
4703 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4706 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4710 NT_STATUS_BUFFER_TOO_SMALL);
4714 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4715 SSVAL(pdata,2,num_file_acls);
4716 SSVAL(pdata,4,num_def_acls);
4717 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4719 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4722 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4725 req, NT_STATUS_INTERNAL_ERROR);
4728 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4730 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4733 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4737 NT_STATUS_INTERNAL_ERROR);
4742 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4745 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4747 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4753 case SMB_QUERY_POSIX_LOCK:
4755 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4759 enum brl_type lock_type;
4761 if (total_data != POSIX_LOCK_DATA_SIZE) {
4763 req, NT_STATUS_INVALID_PARAMETER);
4767 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4768 case POSIX_LOCK_TYPE_READ:
4769 lock_type = READ_LOCK;
4771 case POSIX_LOCK_TYPE_WRITE:
4772 lock_type = WRITE_LOCK;
4774 case POSIX_LOCK_TYPE_UNLOCK:
4776 /* There's no point in asking for an unlock... */
4779 NT_STATUS_INVALID_PARAMETER);
4783 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4784 #if defined(HAVE_LONGLONG)
4785 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4786 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4787 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4788 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4789 #else /* HAVE_LONGLONG */
4790 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4791 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4792 #endif /* HAVE_LONGLONG */
4794 status = query_lock(fsp,
4801 if (ERROR_WAS_LOCK_DENIED(status)) {
4802 /* Here we need to report who has it locked... */
4803 data_size = POSIX_LOCK_DATA_SIZE;
4805 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4806 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4807 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4808 #if defined(HAVE_LONGLONG)
4809 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4810 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4811 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4812 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4813 #else /* HAVE_LONGLONG */
4814 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4815 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4816 #endif /* HAVE_LONGLONG */
4818 } else if (NT_STATUS_IS_OK(status)) {
4819 /* For success we just return a copy of what we sent
4820 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4821 data_size = POSIX_LOCK_DATA_SIZE;
4822 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4823 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4825 reply_nterror(req, status);
4832 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4836 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4842 /****************************************************************************
4843 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4845 ****************************************************************************/
4847 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4848 connection_struct *conn,
4849 const char *oldname_in,
4850 const char *newname_in)
4852 struct smb_filename *smb_fname = NULL;
4853 struct smb_filename *smb_fname_new = NULL;
4854 char *oldname = NULL;
4855 char *newname = NULL;
4856 NTSTATUS status = NT_STATUS_OK;
4858 status = unix_convert(ctx, conn, oldname_in, &smb_fname, 0);
4859 if (!NT_STATUS_IS_OK(status)) {
4863 status = get_full_smb_filename(ctx, smb_fname, &oldname);
4864 if (!NT_STATUS_IS_OK(status)) {
4868 status = check_name(conn, oldname);
4869 if (!NT_STATUS_IS_OK(status)) {
4873 /* source must already exist. */
4874 if (!VALID_STAT(smb_fname->st)) {
4875 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4879 status = unix_convert(ctx, conn, newname_in, &smb_fname_new, 0);
4880 if (!NT_STATUS_IS_OK(status)) {
4884 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
4885 if (!NT_STATUS_IS_OK(status)) {
4889 status = check_name(conn, newname);
4890 if (!NT_STATUS_IS_OK(status)) {
4894 /* Disallow if newname already exists. */
4895 if (VALID_STAT(smb_fname_new->st)) {
4896 status = NT_STATUS_OBJECT_NAME_COLLISION;
4900 /* No links from a directory. */
4901 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
4902 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4906 /* Ensure this is within the share. */
4907 status = check_reduced_name(conn, oldname);
4908 if (!NT_STATUS_IS_OK(status)) {
4912 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4914 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4915 status = map_nt_error_from_unix(errno);
4916 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4917 nt_errstr(status), newname, oldname));
4920 TALLOC_FREE(smb_fname);
4921 TALLOC_FREE(smb_fname_new);
4925 /****************************************************************************
4926 Deal with setting the time from any of the setfilepathinfo functions.
4927 ****************************************************************************/
4929 NTSTATUS smb_set_file_time(connection_struct *conn,
4932 const SMB_STRUCT_STAT *psbuf,
4933 struct smb_file_time *ft,
4934 bool setting_write_time)
4937 FILE_NOTIFY_CHANGE_LAST_ACCESS
4938 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4940 if (!VALID_STAT(*psbuf)) {
4941 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4944 /* get some defaults (no modifications) if any info is zero or -1. */
4945 if (null_timespec(ft->atime)) {
4946 ft->atime= psbuf->st_ex_atime;
4947 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4950 if (null_timespec(ft->mtime)) {
4951 ft->mtime = psbuf->st_ex_mtime;
4952 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4955 if (!setting_write_time) {
4956 /* ft->mtime comes from change time, not write time. */
4957 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4960 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4961 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4962 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4963 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4964 if (!null_timespec(ft->create_time)) {
4965 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4966 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4970 * Try and set the times of this file if
4971 * they are different from the current values.
4975 struct timespec mts = psbuf->st_ex_mtime;
4976 struct timespec ats = psbuf->st_ex_atime;
4977 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4978 (timespec_compare(&ft->mtime, &mts) == 0)) {
4979 return NT_STATUS_OK;
4983 if (setting_write_time) {
4985 * This was a setfileinfo on an open file.
4986 * NT does this a lot. We also need to
4987 * set the time here, as it can be read by
4988 * FindFirst/FindNext and with the patch for bug #2045
4989 * in smbd/fileio.c it ensures that this timestamp is
4990 * kept sticky even after a write. We save the request
4991 * away and will set it on file close and after a write. JRA.
4994 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4995 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4998 if (fsp->base_fsp) {
4999 set_sticky_write_time_fsp(fsp->base_fsp,
5002 set_sticky_write_time_fsp(fsp, ft->mtime);
5005 set_sticky_write_time_path(conn, fname,
5006 vfs_file_id_from_sbuf(conn, psbuf),
5011 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5013 if (fsp && fsp->base_fsp) {
5014 fname = fsp->base_fsp->fsp_name;
5017 if(file_ntimes(conn, fname, ft)!=0) {
5018 return map_nt_error_from_unix(errno);
5020 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
5022 return NT_STATUS_OK;
5025 /****************************************************************************
5026 Deal with setting the dosmode from any of the setfilepathinfo functions.
5027 ****************************************************************************/
5029 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5032 SMB_STRUCT_STAT *psbuf,
5035 if (!VALID_STAT(*psbuf)) {
5036 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5040 if (fsp->base_fsp) {
5041 fname = fsp->base_fsp->fsp_name;
5043 fname = fsp->fsp_name;
5048 if (S_ISDIR(psbuf->st_ex_mode)) {
5055 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5057 /* check the mode isn't different, before changing it */
5058 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5060 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5061 fname, (unsigned int)dosmode ));
5063 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5064 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5065 fname, strerror(errno)));
5066 return map_nt_error_from_unix(errno);
5069 return NT_STATUS_OK;
5072 /****************************************************************************
5073 Deal with setting the size from any of the setfilepathinfo functions.
5074 ****************************************************************************/
5076 static NTSTATUS smb_set_file_size(connection_struct *conn,
5077 struct smb_request *req,
5080 SMB_STRUCT_STAT *psbuf,
5083 NTSTATUS status = NT_STATUS_OK;
5084 files_struct *new_fsp = NULL;
5086 if (!VALID_STAT(*psbuf)) {
5087 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5090 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5092 if (size == get_file_size_stat(psbuf)) {
5093 return NT_STATUS_OK;
5096 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5097 fname, (double)size ));
5099 if (fsp && fsp->fh->fd != -1) {
5100 /* Handle based call. */
5101 if (vfs_set_filelen(fsp, size) == -1) {
5102 return map_nt_error_from_unix(errno);
5104 trigger_write_time_update_immediate(fsp);
5105 return NT_STATUS_OK;
5108 status = SMB_VFS_CREATE_FILE(
5111 0, /* root_dir_fid */
5113 0, /* create_file_flags */
5114 FILE_WRITE_ATTRIBUTES, /* access_mask */
5115 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5117 FILE_OPEN, /* create_disposition*/
5118 0, /* create_options */
5119 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5120 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5121 0, /* allocation_size */
5124 &new_fsp, /* result */
5128 if (!NT_STATUS_IS_OK(status)) {
5129 /* NB. We check for open_was_deferred in the caller. */
5133 if (vfs_set_filelen(new_fsp, size) == -1) {
5134 status = map_nt_error_from_unix(errno);
5135 close_file(req, new_fsp,NORMAL_CLOSE);
5139 trigger_write_time_update_immediate(new_fsp);
5140 close_file(req, new_fsp,NORMAL_CLOSE);
5141 return NT_STATUS_OK;
5144 /****************************************************************************
5145 Deal with SMB_INFO_SET_EA.
5146 ****************************************************************************/
5148 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5154 struct ea_list *ea_list = NULL;
5155 TALLOC_CTX *ctx = NULL;
5156 NTSTATUS status = NT_STATUS_OK;
5158 if (total_data < 10) {
5160 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5161 length. They seem to have no effect. Bug #3212. JRA */
5163 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5164 /* We're done. We only get EA info in this call. */
5165 return NT_STATUS_OK;
5168 return NT_STATUS_INVALID_PARAMETER;
5171 if (IVAL(pdata,0) > total_data) {
5172 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5173 IVAL(pdata,0), (unsigned int)total_data));
5174 return NT_STATUS_INVALID_PARAMETER;
5178 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5180 return NT_STATUS_INVALID_PARAMETER;
5182 status = set_ea(conn, fsp, fname, ea_list);
5187 /****************************************************************************
5188 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5189 ****************************************************************************/
5191 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5196 SMB_STRUCT_STAT *psbuf)
5198 NTSTATUS status = NT_STATUS_OK;
5199 bool delete_on_close;
5202 if (total_data < 1) {
5203 return NT_STATUS_INVALID_PARAMETER;
5207 return NT_STATUS_INVALID_HANDLE;
5210 delete_on_close = (CVAL(pdata,0) ? True : False);
5211 dosmode = dos_mode(conn, fname, psbuf);
5213 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5214 "delete_on_close = %u\n",
5216 (unsigned int)dosmode,
5217 (unsigned int)delete_on_close ));
5219 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5221 if (!NT_STATUS_IS_OK(status)) {
5225 /* The set is across all open files on this dev/inode pair. */
5226 if (!set_delete_on_close(fsp, delete_on_close,
5227 &conn->server_info->utok)) {
5228 return NT_STATUS_ACCESS_DENIED;
5230 return NT_STATUS_OK;
5233 /****************************************************************************
5234 Deal with SMB_FILE_POSITION_INFORMATION.
5235 ****************************************************************************/
5237 static NTSTATUS smb_file_position_information(connection_struct *conn,
5242 uint64_t position_information;
5244 if (total_data < 8) {
5245 return NT_STATUS_INVALID_PARAMETER;
5249 /* Ignore on pathname based set. */
5250 return NT_STATUS_OK;
5253 position_information = (uint64_t)IVAL(pdata,0);
5254 #ifdef LARGE_SMB_OFF_T
5255 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5256 #else /* LARGE_SMB_OFF_T */
5257 if (IVAL(pdata,4) != 0) {
5258 /* more than 32 bits? */
5259 return NT_STATUS_INVALID_PARAMETER;
5261 #endif /* LARGE_SMB_OFF_T */
5263 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5264 fsp->fsp_name, (double)position_information ));
5265 fsp->fh->position_information = position_information;
5266 return NT_STATUS_OK;
5269 /****************************************************************************
5270 Deal with SMB_FILE_MODE_INFORMATION.
5271 ****************************************************************************/
5273 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5279 if (total_data < 4) {
5280 return NT_STATUS_INVALID_PARAMETER;
5282 mode = IVAL(pdata,0);
5283 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5284 return NT_STATUS_INVALID_PARAMETER;
5286 return NT_STATUS_OK;
5289 /****************************************************************************
5290 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5291 ****************************************************************************/
5293 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5294 struct smb_request *req,
5299 char *link_target = NULL;
5300 const char *newname = fname;
5301 NTSTATUS status = NT_STATUS_OK;
5302 TALLOC_CTX *ctx = talloc_tos();
5304 /* Set a symbolic link. */
5305 /* Don't allow this if follow links is false. */
5307 if (total_data == 0) {
5308 return NT_STATUS_INVALID_PARAMETER;
5311 if (!lp_symlinks(SNUM(conn))) {
5312 return NT_STATUS_ACCESS_DENIED;
5315 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5316 total_data, STR_TERMINATE);
5319 return NT_STATUS_INVALID_PARAMETER;
5322 /* !widelinks forces the target path to be within the share. */
5323 /* This means we can interpret the target as a pathname. */
5324 if (!lp_widelinks(SNUM(conn))) {
5325 char *rel_name = NULL;
5326 char *last_dirp = NULL;
5328 if (*link_target == '/') {
5329 /* No absolute paths allowed. */
5330 return NT_STATUS_ACCESS_DENIED;
5332 rel_name = talloc_strdup(ctx,newname);
5334 return NT_STATUS_NO_MEMORY;
5336 last_dirp = strrchr_m(rel_name, '/');
5338 last_dirp[1] = '\0';
5340 rel_name = talloc_strdup(ctx,"./");
5342 return NT_STATUS_NO_MEMORY;
5345 rel_name = talloc_asprintf_append(rel_name,
5349 return NT_STATUS_NO_MEMORY;
5352 status = check_name(conn, rel_name);
5353 if (!NT_STATUS_IS_OK(status)) {
5358 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5359 newname, link_target ));
5361 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5362 return map_nt_error_from_unix(errno);
5365 return NT_STATUS_OK;
5368 /****************************************************************************
5369 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5370 ****************************************************************************/
5372 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5373 struct smb_request *req,
5374 const char *pdata, int total_data,
5377 char *oldname = NULL;
5378 TALLOC_CTX *ctx = talloc_tos();
5379 NTSTATUS status = NT_STATUS_OK;
5381 /* Set a hard link. */
5382 if (total_data == 0) {
5383 return NT_STATUS_INVALID_PARAMETER;
5386 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5387 total_data, STR_TERMINATE, &status);
5388 if (!NT_STATUS_IS_OK(status)) {
5392 status = resolve_dfspath(ctx, conn,
5393 req->flags2 & FLAGS2_DFS_PATHNAMES,
5396 if (!NT_STATUS_IS_OK(status)) {
5400 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5403 return hardlink_internals(ctx, conn, oldname, fname);
5406 /****************************************************************************
5407 Deal with SMB_FILE_RENAME_INFORMATION.
5408 ****************************************************************************/
5410 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5411 struct smb_request *req,
5420 char *newname = NULL;
5421 char *base_name = NULL;
5422 struct smb_filename *smb_fname = NULL;
5423 bool dest_has_wcard = False;
5424 NTSTATUS status = NT_STATUS_OK;
5426 TALLOC_CTX *ctx = talloc_tos();
5428 if (total_data < 13) {
5429 return NT_STATUS_INVALID_PARAMETER;
5432 overwrite = (CVAL(pdata,0) ? True : False);
5433 root_fid = IVAL(pdata,4);
5434 len = IVAL(pdata,8);
5436 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5437 return NT_STATUS_INVALID_PARAMETER;
5440 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5443 if (!NT_STATUS_IS_OK(status)) {
5447 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5450 status = resolve_dfspath_wcard(ctx, conn,
5451 req->flags2 & FLAGS2_DFS_PATHNAMES,
5455 if (!NT_STATUS_IS_OK(status)) {
5459 /* Check the new name has no '/' characters. */
5460 if (strchr_m(newname, '/')) {
5461 return NT_STATUS_NOT_SUPPORTED;
5464 if (fsp && fsp->base_fsp) {
5465 /* newname must be a stream name. */
5466 if (newname[0] != ':') {
5467 return NT_STATUS_NOT_SUPPORTED;
5469 base_name = talloc_asprintf(ctx, "%s%s",
5470 fsp->base_fsp->fsp_name,
5473 return NT_STATUS_NO_MEMORY;
5476 /* newname must *not* be a stream name. */
5477 if (is_ntfs_stream_name(newname)) {
5478 return NT_STATUS_NOT_SUPPORTED;
5481 /* Create the base directory. */
5482 base_name = talloc_strdup(ctx, fname);
5484 return NT_STATUS_NO_MEMORY;
5486 p = strrchr_m(base_name, '/');
5490 base_name = talloc_strdup(ctx, "./");
5492 return NT_STATUS_NO_MEMORY;
5495 /* Append the new name. */
5496 base_name = talloc_asprintf_append(base_name,
5500 return NT_STATUS_NO_MEMORY;
5503 status = unix_convert(ctx, conn, newname, &smb_fname,
5506 /* If an error we expect this to be
5507 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5509 if (!NT_STATUS_IS_OK(status)
5510 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5517 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5518 fsp->fnum, fsp->fsp_name, base_name ));
5519 status = rename_internals_fsp(conn, fsp, base_name,
5521 smb_fname->original_lcomp : NULL,
5524 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5525 fname, base_name ));
5526 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5527 overwrite, False, dest_has_wcard,
5528 FILE_WRITE_ATTRIBUTES);
5531 TALLOC_FREE(smb_fname);
5535 /****************************************************************************
5536 Deal with SMB_SET_POSIX_ACL.
5537 ****************************************************************************/
5539 #if defined(HAVE_POSIX_ACLS)
5540 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5545 SMB_STRUCT_STAT *psbuf)
5547 uint16 posix_acl_version;
5548 uint16 num_file_acls;
5549 uint16 num_def_acls;
5550 bool valid_file_acls = True;
5551 bool valid_def_acls = True;
5553 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5554 return NT_STATUS_INVALID_PARAMETER;
5556 posix_acl_version = SVAL(pdata,0);
5557 num_file_acls = SVAL(pdata,2);
5558 num_def_acls = SVAL(pdata,4);
5560 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5561 valid_file_acls = False;
5565 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5566 valid_def_acls = False;
5570 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5571 return NT_STATUS_INVALID_PARAMETER;
5574 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5575 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5576 return NT_STATUS_INVALID_PARAMETER;
5579 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5580 fname ? fname : fsp->fsp_name,
5581 (unsigned int)num_file_acls,
5582 (unsigned int)num_def_acls));
5584 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5585 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5586 return map_nt_error_from_unix(errno);
5589 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5590 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5591 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5592 return map_nt_error_from_unix(errno);
5594 return NT_STATUS_OK;
5598 /****************************************************************************
5599 Deal with SMB_SET_POSIX_LOCK.
5600 ****************************************************************************/
5602 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5603 struct smb_request *req,
5611 bool blocking_lock = False;
5612 enum brl_type lock_type;
5614 NTSTATUS status = NT_STATUS_OK;
5616 if (fsp == NULL || fsp->fh->fd == -1) {
5617 return NT_STATUS_INVALID_HANDLE;
5620 if (total_data != POSIX_LOCK_DATA_SIZE) {
5621 return NT_STATUS_INVALID_PARAMETER;
5624 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5625 case POSIX_LOCK_TYPE_READ:
5626 lock_type = READ_LOCK;
5628 case POSIX_LOCK_TYPE_WRITE:
5629 /* Return the right POSIX-mappable error code for files opened read-only. */
5630 if (!fsp->can_write) {
5631 return NT_STATUS_INVALID_HANDLE;
5633 lock_type = WRITE_LOCK;
5635 case POSIX_LOCK_TYPE_UNLOCK:
5636 lock_type = UNLOCK_LOCK;
5639 return NT_STATUS_INVALID_PARAMETER;
5642 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5643 blocking_lock = False;
5644 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5645 blocking_lock = True;
5647 return NT_STATUS_INVALID_PARAMETER;
5650 if (!lp_blocking_locks(SNUM(conn))) {
5651 blocking_lock = False;
5654 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5655 #if defined(HAVE_LONGLONG)
5656 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5657 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5658 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5659 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5660 #else /* HAVE_LONGLONG */
5661 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5662 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5663 #endif /* HAVE_LONGLONG */
5665 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5666 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5668 (unsigned int)lock_type,
5669 (unsigned int)lock_pid,
5673 if (lock_type == UNLOCK_LOCK) {
5674 status = do_unlock(smbd_messaging_context(),
5681 uint32 block_smbpid;
5683 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5695 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5697 * A blocking lock was requested. Package up
5698 * this smb into a queued request and push it
5699 * onto the blocking lock queue.
5701 if(push_blocking_lock_request(br_lck,
5704 -1, /* infinite timeout. */
5712 TALLOC_FREE(br_lck);
5716 TALLOC_FREE(br_lck);
5722 /****************************************************************************
5723 Deal with SMB_INFO_STANDARD.
5724 ****************************************************************************/
5726 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5731 const SMB_STRUCT_STAT *psbuf)
5733 struct smb_file_time ft;
5736 if (total_data < 12) {
5737 return NT_STATUS_INVALID_PARAMETER;
5741 ft.create_time = interpret_long_date(pdata);
5744 ft.atime = interpret_long_date(pdata + 8);
5747 ft.mtime = interpret_long_date(pdata + 16);
5749 DEBUG(10,("smb_set_info_standard: file %s\n",
5750 fname ? fname : fsp->fsp_name ));
5752 return smb_set_file_time(conn,
5760 /****************************************************************************
5761 Deal with SMB_SET_FILE_BASIC_INFO.
5762 ****************************************************************************/
5764 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5769 SMB_STRUCT_STAT *psbuf)
5771 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5772 struct timespec write_time;
5773 struct timespec changed_time;
5774 struct smb_file_time ft;
5776 NTSTATUS status = NT_STATUS_OK;
5777 bool setting_write_time = true;
5781 if (total_data < 36) {
5782 return NT_STATUS_INVALID_PARAMETER;
5785 /* Set the attributes */
5786 dosmode = IVAL(pdata,32);
5787 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5788 if (!NT_STATUS_IS_OK(status)) {
5793 ft.atime = interpret_long_date(pdata+8);
5795 write_time = interpret_long_date(pdata+16);
5796 changed_time = interpret_long_date(pdata+24);
5799 ft.mtime = timespec_min(&write_time, &changed_time);
5802 ft.create_time = interpret_long_date(pdata);
5804 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5805 !null_timespec(write_time)) {
5806 ft.mtime = write_time;
5809 /* Prefer a defined time to an undefined one. */
5810 if (null_timespec(ft.mtime)) {
5811 if (null_timespec(write_time)) {
5812 ft.mtime = changed_time;
5813 setting_write_time = false;
5815 ft.mtime = write_time;
5819 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5820 fname ? fname : fsp->fsp_name ));
5822 return smb_set_file_time(conn,
5827 setting_write_time);
5830 /****************************************************************************
5831 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5832 ****************************************************************************/
5834 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5835 struct smb_request *req,
5840 SMB_STRUCT_STAT *psbuf)
5842 uint64_t allocation_size = 0;
5843 NTSTATUS status = NT_STATUS_OK;
5844 files_struct *new_fsp = NULL;
5846 if (!VALID_STAT(*psbuf)) {
5847 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5850 if (total_data < 8) {
5851 return NT_STATUS_INVALID_PARAMETER;
5854 allocation_size = (uint64_t)IVAL(pdata,0);
5855 #ifdef LARGE_SMB_OFF_T
5856 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5857 #else /* LARGE_SMB_OFF_T */
5858 if (IVAL(pdata,4) != 0) {
5859 /* more than 32 bits? */
5860 return NT_STATUS_INVALID_PARAMETER;
5862 #endif /* LARGE_SMB_OFF_T */
5864 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5865 fname, (double)allocation_size ));
5867 if (allocation_size) {
5868 allocation_size = smb_roundup(conn, allocation_size);
5871 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5872 fname, (double)allocation_size ));
5874 if (fsp && fsp->fh->fd != -1) {
5875 /* Open file handle. */
5876 /* Only change if needed. */
5877 if (allocation_size != get_file_size_stat(psbuf)) {
5878 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5879 return map_nt_error_from_unix(errno);
5882 /* But always update the time. */
5884 * This is equivalent to a write. Ensure it's seen immediately
5885 * if there are no pending writes.
5887 trigger_write_time_update_immediate(fsp);
5888 return NT_STATUS_OK;
5891 /* Pathname or stat or directory file. */
5893 status = SMB_VFS_CREATE_FILE(
5896 0, /* root_dir_fid */
5898 0, /* create_file_flags */
5899 FILE_WRITE_DATA, /* access_mask */
5900 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5902 FILE_OPEN, /* create_disposition*/
5903 0, /* create_options */
5904 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5905 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5906 0, /* allocation_size */
5909 &new_fsp, /* result */
5913 if (!NT_STATUS_IS_OK(status)) {
5914 /* NB. We check for open_was_deferred in the caller. */
5918 /* Only change if needed. */
5919 if (allocation_size != get_file_size_stat(psbuf)) {
5920 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5921 status = map_nt_error_from_unix(errno);
5922 close_file(req, new_fsp, NORMAL_CLOSE);
5927 /* Changing the allocation size should set the last mod time. */
5929 * This is equivalent to a write. Ensure it's seen immediately
5930 * if there are no pending writes.
5932 trigger_write_time_update_immediate(new_fsp);
5934 close_file(req, new_fsp, NORMAL_CLOSE);
5935 return NT_STATUS_OK;
5938 /****************************************************************************
5939 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5940 ****************************************************************************/
5942 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5943 struct smb_request *req,
5948 SMB_STRUCT_STAT *psbuf)
5952 if (total_data < 8) {
5953 return NT_STATUS_INVALID_PARAMETER;
5956 size = IVAL(pdata,0);
5957 #ifdef LARGE_SMB_OFF_T
5958 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5959 #else /* LARGE_SMB_OFF_T */
5960 if (IVAL(pdata,4) != 0) {
5961 /* more than 32 bits? */
5962 return NT_STATUS_INVALID_PARAMETER;
5964 #endif /* LARGE_SMB_OFF_T */
5965 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5966 "file %s to %.0f\n", fname, (double)size ));
5968 return smb_set_file_size(conn, req,
5975 /****************************************************************************
5976 Allow a UNIX info mknod.
5977 ****************************************************************************/
5979 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5983 SMB_STRUCT_STAT *psbuf)
5985 uint32 file_type = IVAL(pdata,56);
5986 #if defined(HAVE_MAKEDEV)
5987 uint32 dev_major = IVAL(pdata,60);
5988 uint32 dev_minor = IVAL(pdata,68);
5990 SMB_DEV_T dev = (SMB_DEV_T)0;
5991 uint32 raw_unixmode = IVAL(pdata,84);
5995 if (total_data < 100) {
5996 return NT_STATUS_INVALID_PARAMETER;
5999 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
6000 if (!NT_STATUS_IS_OK(status)) {
6004 #if defined(HAVE_MAKEDEV)
6005 dev = makedev(dev_major, dev_minor);
6008 switch (file_type) {
6009 #if defined(S_IFIFO)
6010 case UNIX_TYPE_FIFO:
6011 unixmode |= S_IFIFO;
6014 #if defined(S_IFSOCK)
6015 case UNIX_TYPE_SOCKET:
6016 unixmode |= S_IFSOCK;
6019 #if defined(S_IFCHR)
6020 case UNIX_TYPE_CHARDEV:
6021 unixmode |= S_IFCHR;
6024 #if defined(S_IFBLK)
6025 case UNIX_TYPE_BLKDEV:
6026 unixmode |= S_IFBLK;
6030 return NT_STATUS_INVALID_PARAMETER;
6033 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6034 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6036 /* Ok - do the mknod. */
6037 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6038 return map_nt_error_from_unix(errno);
6041 /* If any of the other "set" calls fail we
6042 * don't want to end up with a half-constructed mknod.
6045 if (lp_inherit_perms(SNUM(conn))) {
6047 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6048 return NT_STATUS_NO_MEMORY;
6050 inherit_access_posix_acl(conn, parent, fname, unixmode);
6051 TALLOC_FREE(parent);
6054 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6055 status = map_nt_error_from_unix(errno);
6056 SMB_VFS_UNLINK(conn,fname);
6059 return NT_STATUS_OK;
6062 /****************************************************************************
6063 Deal with SMB_SET_FILE_UNIX_BASIC.
6064 ****************************************************************************/
6066 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6067 struct smb_request *req,
6072 SMB_STRUCT_STAT *psbuf)
6074 struct smb_file_time ft;
6075 uint32 raw_unixmode;
6078 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6079 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6080 NTSTATUS status = NT_STATUS_OK;
6081 bool delete_on_fail = False;
6082 enum perm_type ptype;
6086 if (total_data < 100) {
6087 return NT_STATUS_INVALID_PARAMETER;
6090 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6091 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6092 size=IVAL(pdata,0); /* first 8 Bytes are size */
6093 #ifdef LARGE_SMB_OFF_T
6094 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6095 #else /* LARGE_SMB_OFF_T */
6096 if (IVAL(pdata,4) != 0) {
6097 /* more than 32 bits? */
6098 return NT_STATUS_INVALID_PARAMETER;
6100 #endif /* LARGE_SMB_OFF_T */
6103 ft.atime = interpret_long_date(pdata+24); /* access_time */
6104 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6105 set_owner = (uid_t)IVAL(pdata,40);
6106 set_grp = (gid_t)IVAL(pdata,48);
6107 raw_unixmode = IVAL(pdata,84);
6109 if (VALID_STAT(*psbuf)) {
6110 if (S_ISDIR(psbuf->st_ex_mode)) {
6111 ptype = PERM_EXISTING_DIR;
6113 ptype = PERM_EXISTING_FILE;
6116 ptype = PERM_NEW_FILE;
6119 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6120 if (!NT_STATUS_IS_OK(status)) {
6124 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6125 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6126 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6128 if (!VALID_STAT(*psbuf)) {
6130 * The only valid use of this is to create character and block
6131 * devices, and named pipes. This is deprecated (IMHO) and
6132 * a new info level should be used for mknod. JRA.
6135 status = smb_unix_mknod(conn,
6140 if (!NT_STATUS_IS_OK(status)) {
6144 /* Ensure we don't try and change anything else. */
6145 raw_unixmode = SMB_MODE_NO_CHANGE;
6146 size = get_file_size_stat(psbuf);
6147 ft.atime = psbuf->st_ex_atime;
6148 ft.mtime = psbuf->st_ex_mtime;
6150 * We continue here as we might want to change the
6153 delete_on_fail = True;
6157 /* Horrible backwards compatibility hack as an old server bug
6158 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6162 size = get_file_size_stat(psbuf);
6167 * Deal with the UNIX specific mode set.
6170 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6171 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6172 (unsigned int)unixmode, fname ));
6173 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6174 return map_nt_error_from_unix(errno);
6179 * Deal with the UNIX specific uid set.
6182 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_ex_uid != set_owner)) {
6185 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6186 (unsigned int)set_owner, fname ));
6188 if (S_ISLNK(psbuf->st_ex_mode)) {
6189 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6191 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6195 status = map_nt_error_from_unix(errno);
6196 if (delete_on_fail) {
6197 SMB_VFS_UNLINK(conn,fname);
6204 * Deal with the UNIX specific gid set.
6207 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_ex_gid != set_grp)) {
6208 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6209 (unsigned int)set_owner, fname ));
6210 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6211 status = map_nt_error_from_unix(errno);
6212 if (delete_on_fail) {
6213 SMB_VFS_UNLINK(conn,fname);
6219 /* Deal with any size changes. */
6221 status = smb_set_file_size(conn, req,
6226 if (!NT_STATUS_IS_OK(status)) {
6230 /* Deal with any time changes. */
6232 return smb_set_file_time(conn,
6240 /****************************************************************************
6241 Deal with SMB_SET_FILE_UNIX_INFO2.
6242 ****************************************************************************/
6244 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6245 struct smb_request *req,
6250 SMB_STRUCT_STAT *psbuf)
6256 if (total_data < 116) {
6257 return NT_STATUS_INVALID_PARAMETER;
6260 /* Start by setting all the fields that are common between UNIX_BASIC
6263 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6265 if (!NT_STATUS_IS_OK(status)) {
6269 smb_fflags = IVAL(pdata, 108);
6270 smb_fmask = IVAL(pdata, 112);
6272 /* NB: We should only attempt to alter the file flags if the client
6273 * sends a non-zero mask.
6275 if (smb_fmask != 0) {
6276 int stat_fflags = 0;
6278 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6280 /* Client asked to alter a flag we don't understand. */
6281 return NT_STATUS_INVALID_PARAMETER;
6284 if (fsp && fsp->fh->fd != -1) {
6285 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6286 return NT_STATUS_NOT_SUPPORTED;
6288 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6289 return map_nt_error_from_unix(errno);
6294 /* XXX: need to add support for changing the create_time here. You
6295 * can do this for paths on Darwin with setattrlist(2). The right way
6296 * to hook this up is probably by extending the VFS utimes interface.
6299 return NT_STATUS_OK;
6302 /****************************************************************************
6303 Create a directory with POSIX semantics.
6304 ****************************************************************************/
6306 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6307 struct smb_request *req,
6311 SMB_STRUCT_STAT *psbuf,
6312 int *pdata_return_size)
6314 NTSTATUS status = NT_STATUS_OK;
6315 uint32 raw_unixmode = 0;
6316 uint32 mod_unixmode = 0;
6317 mode_t unixmode = (mode_t)0;
6318 files_struct *fsp = NULL;
6319 uint16 info_level_return = 0;
6321 char *pdata = *ppdata;
6323 if (total_data < 18) {
6324 return NT_STATUS_INVALID_PARAMETER;
6327 raw_unixmode = IVAL(pdata,8);
6328 /* Next 4 bytes are not yet defined. */
6330 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6331 if (!NT_STATUS_IS_OK(status)) {
6335 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6337 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6338 fname, (unsigned int)unixmode ));
6340 status = SMB_VFS_CREATE_FILE(
6343 0, /* root_dir_fid */
6345 0, /* create_file_flags */
6346 FILE_READ_ATTRIBUTES, /* access_mask */
6347 FILE_SHARE_NONE, /* share_access */
6348 FILE_CREATE, /* create_disposition*/
6349 FILE_DIRECTORY_FILE, /* create_options */
6350 mod_unixmode, /* file_attributes */
6351 0, /* oplock_request */
6352 0, /* allocation_size */
6359 if (NT_STATUS_IS_OK(status)) {
6360 close_file(req, fsp, NORMAL_CLOSE);
6363 info_level_return = SVAL(pdata,16);
6365 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6366 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6367 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6368 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6370 *pdata_return_size = 12;
6373 /* Realloc the data size */
6374 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6375 if (*ppdata == NULL) {
6376 *pdata_return_size = 0;
6377 return NT_STATUS_NO_MEMORY;
6381 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6382 SSVAL(pdata,2,0); /* No fnum. */
6383 SIVAL(pdata,4,info); /* Was directory created. */
6385 switch (info_level_return) {
6386 case SMB_QUERY_FILE_UNIX_BASIC:
6387 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6388 SSVAL(pdata,10,0); /* Padding. */
6389 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6391 case SMB_QUERY_FILE_UNIX_INFO2:
6392 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6393 SSVAL(pdata,10,0); /* Padding. */
6394 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6397 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6398 SSVAL(pdata,10,0); /* Padding. */
6405 /****************************************************************************
6406 Open/Create a file with POSIX semantics.
6407 ****************************************************************************/
6409 static NTSTATUS smb_posix_open(connection_struct *conn,
6410 struct smb_request *req,
6414 SMB_STRUCT_STAT *psbuf,
6415 int *pdata_return_size)
6417 bool extended_oplock_granted = False;
6418 char *pdata = *ppdata;
6420 uint32 wire_open_mode = 0;
6421 uint32 raw_unixmode = 0;
6422 uint32 mod_unixmode = 0;
6423 uint32 create_disp = 0;
6424 uint32 access_mask = 0;
6425 uint32 create_options = 0;
6426 NTSTATUS status = NT_STATUS_OK;
6427 mode_t unixmode = (mode_t)0;
6428 files_struct *fsp = NULL;
6429 int oplock_request = 0;
6431 uint16 info_level_return = 0;
6433 if (total_data < 18) {
6434 return NT_STATUS_INVALID_PARAMETER;
6437 flags = IVAL(pdata,0);
6438 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6439 if (oplock_request) {
6440 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6443 wire_open_mode = IVAL(pdata,4);
6445 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6446 return smb_posix_mkdir(conn, req,
6454 switch (wire_open_mode & SMB_ACCMODE) {
6456 access_mask = FILE_READ_DATA;
6459 access_mask = FILE_WRITE_DATA;
6462 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6465 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6466 (unsigned int)wire_open_mode ));
6467 return NT_STATUS_INVALID_PARAMETER;
6470 wire_open_mode &= ~SMB_ACCMODE;
6472 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6473 create_disp = FILE_CREATE;
6474 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6475 create_disp = FILE_OVERWRITE_IF;
6476 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6477 create_disp = FILE_OPEN_IF;
6478 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6479 create_disp = FILE_OPEN;
6481 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6482 (unsigned int)wire_open_mode ));
6483 return NT_STATUS_INVALID_PARAMETER;
6486 raw_unixmode = IVAL(pdata,8);
6487 /* Next 4 bytes are not yet defined. */
6489 status = unix_perms_from_wire(conn,
6492 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6495 if (!NT_STATUS_IS_OK(status)) {
6499 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6501 if (wire_open_mode & SMB_O_SYNC) {
6502 create_options |= FILE_WRITE_THROUGH;
6504 if (wire_open_mode & SMB_O_APPEND) {
6505 access_mask |= FILE_APPEND_DATA;
6507 if (wire_open_mode & SMB_O_DIRECT) {
6508 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6511 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6513 (unsigned int)wire_open_mode,
6514 (unsigned int)unixmode ));
6516 status = SMB_VFS_CREATE_FILE(
6519 0, /* root_dir_fid */
6521 0, /* create_file_flags */
6522 access_mask, /* access_mask */
6523 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6525 create_disp, /* create_disposition*/
6526 FILE_NON_DIRECTORY_FILE, /* create_options */
6527 mod_unixmode, /* file_attributes */
6528 oplock_request, /* oplock_request */
6529 0, /* allocation_size */
6536 if (!NT_STATUS_IS_OK(status)) {
6540 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6541 extended_oplock_granted = True;
6544 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6545 extended_oplock_granted = True;
6548 info_level_return = SVAL(pdata,16);
6550 /* Allocate the correct return size. */
6552 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6553 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6554 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6555 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6557 *pdata_return_size = 12;
6560 /* Realloc the data size */
6561 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6562 if (*ppdata == NULL) {
6563 close_file(req, fsp, ERROR_CLOSE);
6564 *pdata_return_size = 0;
6565 return NT_STATUS_NO_MEMORY;
6569 if (extended_oplock_granted) {
6570 if (flags & REQUEST_BATCH_OPLOCK) {
6571 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6573 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6575 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6576 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6578 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6581 SSVAL(pdata,2,fsp->fnum);
6582 SIVAL(pdata,4,info); /* Was file created etc. */
6584 switch (info_level_return) {
6585 case SMB_QUERY_FILE_UNIX_BASIC:
6586 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6587 SSVAL(pdata,10,0); /* padding. */
6588 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6590 case SMB_QUERY_FILE_UNIX_INFO2:
6591 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6592 SSVAL(pdata,10,0); /* padding. */
6593 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6596 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6597 SSVAL(pdata,10,0); /* padding. */
6600 return NT_STATUS_OK;
6603 /****************************************************************************
6604 Delete a file with POSIX semantics.
6605 ****************************************************************************/
6607 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6608 struct smb_request *req,
6612 SMB_STRUCT_STAT *psbuf)
6614 NTSTATUS status = NT_STATUS_OK;
6615 files_struct *fsp = NULL;
6619 int create_options = 0;
6621 struct share_mode_lock *lck = NULL;
6623 if (total_data < 2) {
6624 return NT_STATUS_INVALID_PARAMETER;
6627 flags = SVAL(pdata,0);
6629 if (!VALID_STAT(*psbuf)) {
6630 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6633 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6634 !VALID_STAT_OF_DIR(*psbuf)) {
6635 return NT_STATUS_NOT_A_DIRECTORY;
6638 DEBUG(10,("smb_posix_unlink: %s %s\n",
6639 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6642 if (VALID_STAT_OF_DIR(*psbuf)) {
6643 create_options |= FILE_DIRECTORY_FILE;
6646 status = SMB_VFS_CREATE_FILE(
6649 0, /* root_dir_fid */
6651 0, /* create_file_flags */
6652 DELETE_ACCESS, /* access_mask */
6653 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6655 FILE_OPEN, /* create_disposition*/
6656 create_options, /* create_options */
6657 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6658 0, /* oplock_request */
6659 0, /* allocation_size */
6666 if (!NT_STATUS_IS_OK(status)) {
6671 * Don't lie to client. If we can't really delete due to
6672 * non-POSIX opens return SHARING_VIOLATION.
6675 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6678 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6679 "lock for file %s\n", fsp->fsp_name));
6680 close_file(req, fsp, NORMAL_CLOSE);
6681 return NT_STATUS_INVALID_PARAMETER;
6685 * See if others still have the file open. If this is the case, then
6686 * don't delete. If all opens are POSIX delete we can set the delete
6687 * on close disposition.
6689 for (i=0; i<lck->num_share_modes; i++) {
6690 struct share_mode_entry *e = &lck->share_modes[i];
6691 if (is_valid_share_mode_entry(e)) {
6692 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6695 /* Fail with sharing violation. */
6696 close_file(req, fsp, NORMAL_CLOSE);
6698 return NT_STATUS_SHARING_VIOLATION;
6703 * Set the delete on close.
6705 status = smb_set_file_disposition_info(conn,
6712 if (!NT_STATUS_IS_OK(status)) {
6713 close_file(req, fsp, NORMAL_CLOSE);
6718 return close_file(req, fsp, NORMAL_CLOSE);
6721 /****************************************************************************
6722 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6723 ****************************************************************************/
6725 static void call_trans2setfilepathinfo(connection_struct *conn,
6726 struct smb_request *req,
6727 unsigned int tran_call,
6728 char **pparams, int total_params,
6729 char **ppdata, int total_data,
6730 unsigned int max_data_bytes)
6732 char *params = *pparams;
6733 char *pdata = *ppdata;
6735 SMB_STRUCT_STAT sbuf;
6737 struct smb_filename *smb_fname = NULL;
6738 files_struct *fsp = NULL;
6739 NTSTATUS status = NT_STATUS_OK;
6740 int data_return_size = 0;
6741 TALLOC_CTX *ctx = talloc_tos();
6744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6750 if (tran_call == TRANSACT2_SETFILEINFO) {
6751 if (total_params < 4) {
6752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6756 fsp = file_fsp(req, SVAL(params,0));
6757 /* Basic check for non-null fsp. */
6758 if (!check_fsp_open(conn, req, fsp)) {
6761 info_level = SVAL(params,2);
6763 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6765 reply_nterror(req, NT_STATUS_NO_MEMORY);
6769 if(fsp->is_directory || fsp->fh->fd == -1) {
6771 * This is actually a SETFILEINFO on a directory
6772 * handle (returned from an NT SMB). NT5.0 seems
6773 * to do this call. JRA.
6775 if (INFO_LEVEL_IS_UNIX(info_level)) {
6776 /* Always do lstat for UNIX calls. */
6777 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6778 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6779 reply_unixerror(req,ERRDOS,ERRbadpath);
6783 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6784 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6785 reply_unixerror(req,ERRDOS,ERRbadpath);
6789 } else if (fsp->print_file) {
6791 * Doing a DELETE_ON_CLOSE should cancel a print job.
6793 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6794 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6796 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6799 send_trans2_replies(conn, req, params, 2,
6804 reply_unixerror(req, ERRDOS, ERRbadpath);
6809 * Original code - this is an open file.
6811 if (!check_fsp(conn, req, fsp)) {
6815 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6816 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6817 reply_unixerror(req, ERRDOS, ERRbadfid);
6823 if (total_params < 7) {
6824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6828 info_level = SVAL(params,0);
6829 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6830 total_params - 6, STR_TERMINATE,
6832 if (!NT_STATUS_IS_OK(status)) {
6833 reply_nterror(req, status);
6837 status = resolve_dfspath(ctx, conn,
6838 req->flags2 & FLAGS2_DFS_PATHNAMES,
6841 if (!NT_STATUS_IS_OK(status)) {
6842 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6843 reply_botherror(req,
6844 NT_STATUS_PATH_NOT_COVERED,
6845 ERRSRV, ERRbadpath);
6848 reply_nterror(req, status);
6852 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
6853 if (!NT_STATUS_IS_OK(status)) {
6854 reply_nterror(req, status);
6857 sbuf = smb_fname->st;
6859 status = get_full_smb_filename(ctx, smb_fname, &fname);
6860 TALLOC_FREE(smb_fname);
6861 if (!NT_STATUS_IS_OK(status)) {
6862 reply_nterror(req, status);
6866 status = check_name(conn, fname);
6867 if (!NT_STATUS_IS_OK(status)) {
6868 reply_nterror(req, status);
6872 if (INFO_LEVEL_IS_UNIX(info_level)) {
6874 * For CIFS UNIX extensions the target name may not exist.
6877 /* Always do lstat for UNIX calls. */
6878 SMB_VFS_LSTAT(conn,fname,&sbuf);
6880 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6881 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6882 reply_unixerror(req, ERRDOS, ERRbadpath);
6887 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6888 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6892 if (!CAN_WRITE(conn)) {
6893 /* Allow POSIX opens. The open path will deny
6894 * any non-readonly opens. */
6895 if (info_level != SMB_POSIX_PATH_OPEN) {
6896 reply_doserror(req, ERRSRV, ERRaccess);
6901 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6902 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6904 /* Realloc the parameter size */
6905 *pparams = (char *)SMB_REALLOC(*pparams,2);
6906 if (*pparams == NULL) {
6907 reply_nterror(req, NT_STATUS_NO_MEMORY);
6914 switch (info_level) {
6916 case SMB_INFO_STANDARD:
6918 status = smb_set_info_standard(conn,
6927 case SMB_INFO_SET_EA:
6929 status = smb_info_set_ea(conn,
6937 case SMB_SET_FILE_BASIC_INFO:
6938 case SMB_FILE_BASIC_INFORMATION:
6940 status = smb_set_file_basic_info(conn,
6949 case SMB_FILE_ALLOCATION_INFORMATION:
6950 case SMB_SET_FILE_ALLOCATION_INFO:
6952 status = smb_set_file_allocation_info(conn, req,
6961 case SMB_FILE_END_OF_FILE_INFORMATION:
6962 case SMB_SET_FILE_END_OF_FILE_INFO:
6964 status = smb_set_file_end_of_file_info(conn, req,
6973 case SMB_FILE_DISPOSITION_INFORMATION:
6974 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6977 /* JRA - We used to just ignore this on a path ?
6978 * Shouldn't this be invalid level on a pathname
6981 if (tran_call != TRANSACT2_SETFILEINFO) {
6982 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6985 status = smb_set_file_disposition_info(conn,
6994 case SMB_FILE_POSITION_INFORMATION:
6996 status = smb_file_position_information(conn,
7003 /* From tridge Samba4 :
7004 * MODE_INFORMATION in setfileinfo (I have no
7005 * idea what "mode information" on a file is - it takes a value of 0,
7006 * 2, 4 or 6. What could it be?).
7009 case SMB_FILE_MODE_INFORMATION:
7011 status = smb_file_mode_information(conn,
7018 * CIFS UNIX extensions.
7021 case SMB_SET_FILE_UNIX_BASIC:
7023 status = smb_set_file_unix_basic(conn, req,
7032 case SMB_SET_FILE_UNIX_INFO2:
7034 status = smb_set_file_unix_info2(conn, req,
7043 case SMB_SET_FILE_UNIX_LINK:
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_link(conn, req, pdata,
7055 case SMB_SET_FILE_UNIX_HLINK:
7057 if (tran_call != TRANSACT2_SETPATHINFO) {
7058 /* We must have a pathname for this. */
7059 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7062 status = smb_set_file_unix_hlink(conn, req,
7068 case SMB_FILE_RENAME_INFORMATION:
7070 status = smb_file_rename_information(conn, req,
7076 #if defined(HAVE_POSIX_ACLS)
7077 case SMB_SET_POSIX_ACL:
7079 status = smb_set_posix_acl(conn,
7089 case SMB_SET_POSIX_LOCK:
7091 if (tran_call != TRANSACT2_SETFILEINFO) {
7092 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7095 status = smb_set_posix_lock(conn, req,
7096 pdata, total_data, fsp);
7100 case SMB_POSIX_PATH_OPEN:
7102 if (tran_call != TRANSACT2_SETPATHINFO) {
7103 /* We must have a pathname for this. */
7104 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7108 status = smb_posix_open(conn, req,
7117 case SMB_POSIX_PATH_UNLINK:
7119 if (tran_call != TRANSACT2_SETPATHINFO) {
7120 /* We must have a pathname for this. */
7121 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7125 status = smb_posix_unlink(conn, req,
7134 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7138 if (!NT_STATUS_IS_OK(status)) {
7139 if (open_was_deferred(req->mid)) {
7140 /* We have re-scheduled this call. */
7143 if (blocking_lock_was_deferred(req->mid)) {
7144 /* We have re-scheduled this call. */
7147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7148 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7149 ERRSRV, ERRbadpath);
7152 if (info_level == SMB_POSIX_PATH_OPEN) {
7153 reply_openerror(req, status);
7157 reply_nterror(req, status);
7162 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7168 /****************************************************************************
7169 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7170 ****************************************************************************/
7172 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7173 char **pparams, int total_params,
7174 char **ppdata, int total_data,
7175 unsigned int max_data_bytes)
7177 struct smb_filename *smb_dname = NULL;
7178 char *params = *pparams;
7179 char *pdata = *ppdata;
7180 char *directory = NULL;
7181 NTSTATUS status = NT_STATUS_OK;
7182 struct ea_list *ea_list = NULL;
7183 TALLOC_CTX *ctx = talloc_tos();
7185 if (!CAN_WRITE(conn)) {
7186 reply_doserror(req, ERRSRV, ERRaccess);
7190 if (total_params < 5) {
7191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7195 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7196 total_params - 4, STR_TERMINATE,
7198 if (!NT_STATUS_IS_OK(status)) {
7199 reply_nterror(req, status);
7203 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7205 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
7206 if (!NT_STATUS_IS_OK(status)) {
7207 reply_nterror(req, status);
7211 status = get_full_smb_filename(ctx, smb_dname, &directory);
7212 if (!NT_STATUS_IS_OK(status)) {
7213 reply_nterror(req, status);
7217 status = check_name(conn, directory);
7218 if (!NT_STATUS_IS_OK(status)) {
7219 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7220 reply_nterror(req, status);
7224 /* Any data in this call is an EA list. */
7225 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7226 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7231 * OS/2 workplace shell seems to send SET_EA requests of "null"
7232 * length (4 bytes containing IVAL 4).
7233 * They seem to have no effect. Bug #3212. JRA.
7236 if (total_data != 4) {
7237 if (total_data < 10) {
7238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7242 if (IVAL(pdata,0) > total_data) {
7243 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7244 IVAL(pdata,0), (unsigned int)total_data));
7245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7249 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7256 /* If total_data == 4 Windows doesn't care what values
7257 * are placed in that field, it just ignores them.
7258 * The System i QNTC IBM SMB client puts bad values here,
7259 * so ignore them. */
7261 status = create_directory(conn, req, directory);
7263 if (!NT_STATUS_IS_OK(status)) {
7264 reply_nterror(req, status);
7268 /* Try and set any given EA. */
7270 status = set_ea(conn, NULL, directory, ea_list);
7271 if (!NT_STATUS_IS_OK(status)) {
7272 reply_nterror(req, status);
7277 /* Realloc the parameter and data sizes */
7278 *pparams = (char *)SMB_REALLOC(*pparams,2);
7279 if(*pparams == NULL) {
7280 reply_nterror(req, NT_STATUS_NO_MEMORY);
7287 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7292 /****************************************************************************
7293 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7294 We don't actually do this - we just send a null response.
7295 ****************************************************************************/
7297 static void call_trans2findnotifyfirst(connection_struct *conn,
7298 struct smb_request *req,
7299 char **pparams, int total_params,
7300 char **ppdata, int total_data,
7301 unsigned int max_data_bytes)
7303 char *params = *pparams;
7306 if (total_params < 6) {
7307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7311 info_level = SVAL(params,4);
7312 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7314 switch (info_level) {
7319 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7323 /* Realloc the parameter and data sizes */
7324 *pparams = (char *)SMB_REALLOC(*pparams,6);
7325 if (*pparams == NULL) {
7326 reply_nterror(req, NT_STATUS_NO_MEMORY);
7331 SSVAL(params,0,fnf_handle);
7332 SSVAL(params,2,0); /* No changes */
7333 SSVAL(params,4,0); /* No EA errors */
7340 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7345 /****************************************************************************
7346 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7347 changes). Currently this does nothing.
7348 ****************************************************************************/
7350 static void call_trans2findnotifynext(connection_struct *conn,
7351 struct smb_request *req,
7352 char **pparams, int total_params,
7353 char **ppdata, int total_data,
7354 unsigned int max_data_bytes)
7356 char *params = *pparams;
7358 DEBUG(3,("call_trans2findnotifynext\n"));
7360 /* Realloc the parameter and data sizes */
7361 *pparams = (char *)SMB_REALLOC(*pparams,4);
7362 if (*pparams == NULL) {
7363 reply_nterror(req, NT_STATUS_NO_MEMORY);
7368 SSVAL(params,0,0); /* No changes */
7369 SSVAL(params,2,0); /* No EA errors */
7371 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7376 /****************************************************************************
7377 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7378 ****************************************************************************/
7380 static void call_trans2getdfsreferral(connection_struct *conn,
7381 struct smb_request *req,
7382 char **pparams, int total_params,
7383 char **ppdata, int total_data,
7384 unsigned int max_data_bytes)
7386 char *params = *pparams;
7387 char *pathname = NULL;
7389 int max_referral_level;
7390 NTSTATUS status = NT_STATUS_OK;
7391 TALLOC_CTX *ctx = talloc_tos();
7393 DEBUG(10,("call_trans2getdfsreferral\n"));
7395 if (total_params < 3) {
7396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7400 max_referral_level = SVAL(params,0);
7402 if(!lp_host_msdfs()) {
7403 reply_doserror(req, ERRDOS, ERRbadfunc);
7407 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7408 total_params - 2, STR_TERMINATE);
7410 reply_nterror(req, NT_STATUS_NOT_FOUND);
7413 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7414 ppdata,&status)) < 0) {
7415 reply_nterror(req, status);
7419 SSVAL(req->inbuf, smb_flg2,
7420 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7421 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7426 #define LMCAT_SPL 0x53
7427 #define LMFUNC_GETJOBID 0x60
7429 /****************************************************************************
7430 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7431 ****************************************************************************/
7433 static void call_trans2ioctl(connection_struct *conn,
7434 struct smb_request *req,
7435 char **pparams, int total_params,
7436 char **ppdata, int total_data,
7437 unsigned int max_data_bytes)
7439 char *pdata = *ppdata;
7440 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7442 /* check for an invalid fid before proceeding */
7445 reply_doserror(req, ERRDOS, ERRbadfid);
7449 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7450 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7451 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7452 if (*ppdata == NULL) {
7453 reply_nterror(req, NT_STATUS_NO_MEMORY);
7458 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7459 CAN ACCEPT THIS IN UNICODE. JRA. */
7461 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7462 srvstr_push(pdata, req->flags2, pdata + 2,
7463 global_myname(), 15,
7464 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7465 srvstr_push(pdata, req->flags2, pdata+18,
7466 lp_servicename(SNUM(conn)), 13,
7467 STR_ASCII|STR_TERMINATE); /* Service name */
7468 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7473 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7474 reply_doserror(req, ERRSRV, ERRerror);
7477 /****************************************************************************
7478 Reply to a SMBfindclose (stop trans2 directory search).
7479 ****************************************************************************/
7481 void reply_findclose(struct smb_request *req)
7485 START_PROFILE(SMBfindclose);
7488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7489 END_PROFILE(SMBfindclose);
7493 dptr_num = SVALS(req->vwv+0, 0);
7495 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7497 dptr_close(&dptr_num);
7499 reply_outbuf(req, 0, 0);
7501 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7503 END_PROFILE(SMBfindclose);
7507 /****************************************************************************
7508 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7509 ****************************************************************************/
7511 void reply_findnclose(struct smb_request *req)
7515 START_PROFILE(SMBfindnclose);
7518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7519 END_PROFILE(SMBfindnclose);
7523 dptr_num = SVAL(req->vwv+0, 0);
7525 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7527 /* We never give out valid handles for a
7528 findnotifyfirst - so any dptr_num is ok here.
7531 reply_outbuf(req, 0, 0);
7533 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7535 END_PROFILE(SMBfindnclose);
7539 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7540 struct trans_state *state)
7542 if (Protocol >= PROTOCOL_NT1) {
7543 req->flags2 |= 0x40; /* IS_LONG_NAME */
7544 SSVAL(req->inbuf,smb_flg2,req->flags2);
7547 if (conn->encrypt_level == Required && !req->encrypted) {
7548 if (state->call != TRANSACT2_QFSINFO &&
7549 state->call != TRANSACT2_SETFSINFO) {
7550 DEBUG(0,("handle_trans2: encryption required "
7552 (unsigned int)state->call));
7553 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7558 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7560 /* Now we must call the relevant TRANS2 function */
7561 switch(state->call) {
7562 case TRANSACT2_OPEN:
7564 START_PROFILE(Trans2_open);
7565 call_trans2open(conn, req,
7566 &state->param, state->total_param,
7567 &state->data, state->total_data,
7568 state->max_data_return);
7569 END_PROFILE(Trans2_open);
7573 case TRANSACT2_FINDFIRST:
7575 START_PROFILE(Trans2_findfirst);
7576 call_trans2findfirst(conn, req,
7577 &state->param, state->total_param,
7578 &state->data, state->total_data,
7579 state->max_data_return);
7580 END_PROFILE(Trans2_findfirst);
7584 case TRANSACT2_FINDNEXT:
7586 START_PROFILE(Trans2_findnext);
7587 call_trans2findnext(conn, req,
7588 &state->param, state->total_param,
7589 &state->data, state->total_data,
7590 state->max_data_return);
7591 END_PROFILE(Trans2_findnext);
7595 case TRANSACT2_QFSINFO:
7597 START_PROFILE(Trans2_qfsinfo);
7598 call_trans2qfsinfo(conn, req,
7599 &state->param, state->total_param,
7600 &state->data, state->total_data,
7601 state->max_data_return);
7602 END_PROFILE(Trans2_qfsinfo);
7606 case TRANSACT2_SETFSINFO:
7608 START_PROFILE(Trans2_setfsinfo);
7609 call_trans2setfsinfo(conn, req,
7610 &state->param, state->total_param,
7611 &state->data, state->total_data,
7612 state->max_data_return);
7613 END_PROFILE(Trans2_setfsinfo);
7617 case TRANSACT2_QPATHINFO:
7618 case TRANSACT2_QFILEINFO:
7620 START_PROFILE(Trans2_qpathinfo);
7621 call_trans2qfilepathinfo(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_qpathinfo);
7629 case TRANSACT2_SETPATHINFO:
7630 case TRANSACT2_SETFILEINFO:
7632 START_PROFILE(Trans2_setpathinfo);
7633 call_trans2setfilepathinfo(conn, req, state->call,
7634 &state->param, state->total_param,
7635 &state->data, state->total_data,
7636 state->max_data_return);
7637 END_PROFILE(Trans2_setpathinfo);
7641 case TRANSACT2_FINDNOTIFYFIRST:
7643 START_PROFILE(Trans2_findnotifyfirst);
7644 call_trans2findnotifyfirst(conn, req,
7645 &state->param, state->total_param,
7646 &state->data, state->total_data,
7647 state->max_data_return);
7648 END_PROFILE(Trans2_findnotifyfirst);
7652 case TRANSACT2_FINDNOTIFYNEXT:
7654 START_PROFILE(Trans2_findnotifynext);
7655 call_trans2findnotifynext(conn, req,
7656 &state->param, state->total_param,
7657 &state->data, state->total_data,
7658 state->max_data_return);
7659 END_PROFILE(Trans2_findnotifynext);
7663 case TRANSACT2_MKDIR:
7665 START_PROFILE(Trans2_mkdir);
7666 call_trans2mkdir(conn, req,
7667 &state->param, state->total_param,
7668 &state->data, state->total_data,
7669 state->max_data_return);
7670 END_PROFILE(Trans2_mkdir);
7674 case TRANSACT2_GET_DFS_REFERRAL:
7676 START_PROFILE(Trans2_get_dfs_referral);
7677 call_trans2getdfsreferral(conn, req,
7678 &state->param, state->total_param,
7679 &state->data, state->total_data,
7680 state->max_data_return);
7681 END_PROFILE(Trans2_get_dfs_referral);
7685 case TRANSACT2_IOCTL:
7687 START_PROFILE(Trans2_ioctl);
7688 call_trans2ioctl(conn, req,
7689 &state->param, state->total_param,
7690 &state->data, state->total_data,
7691 state->max_data_return);
7692 END_PROFILE(Trans2_ioctl);
7697 /* Error in request */
7698 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7699 reply_doserror(req, ERRSRV,ERRerror);
7703 /****************************************************************************
7704 Reply to a SMBtrans2.
7705 ****************************************************************************/
7707 void reply_trans2(struct smb_request *req)
7709 connection_struct *conn = req->conn;
7714 unsigned int tran_call;
7715 struct trans_state *state;
7718 START_PROFILE(SMBtrans2);
7720 if (req->wct < 14) {
7721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7722 END_PROFILE(SMBtrans2);
7726 dsoff = SVAL(req->vwv+12, 0);
7727 dscnt = SVAL(req->vwv+11, 0);
7728 psoff = SVAL(req->vwv+10, 0);
7729 pscnt = SVAL(req->vwv+9, 0);
7730 tran_call = SVAL(req->vwv+14, 0);
7732 result = allow_new_trans(conn->pending_trans, req->mid);
7733 if (!NT_STATUS_IS_OK(result)) {
7734 DEBUG(2, ("Got invalid trans2 request: %s\n",
7735 nt_errstr(result)));
7736 reply_nterror(req, result);
7737 END_PROFILE(SMBtrans2);
7742 switch (tran_call) {
7743 /* List the allowed trans2 calls on IPC$ */
7744 case TRANSACT2_OPEN:
7745 case TRANSACT2_GET_DFS_REFERRAL:
7746 case TRANSACT2_QFILEINFO:
7747 case TRANSACT2_QFSINFO:
7748 case TRANSACT2_SETFSINFO:
7751 reply_doserror(req, ERRSRV, ERRaccess);
7752 END_PROFILE(SMBtrans2);
7757 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7758 DEBUG(0, ("talloc failed\n"));
7759 reply_nterror(req, NT_STATUS_NO_MEMORY);
7760 END_PROFILE(SMBtrans2);
7764 state->cmd = SMBtrans2;
7766 state->mid = req->mid;
7767 state->vuid = req->vuid;
7768 state->setup_count = SVAL(req->vwv+13, 0);
7769 state->setup = NULL;
7770 state->total_param = SVAL(req->vwv+0, 0);
7771 state->param = NULL;
7772 state->total_data = SVAL(req->vwv+1, 0);
7774 state->max_param_return = SVAL(req->vwv+2, 0);
7775 state->max_data_return = SVAL(req->vwv+3, 0);
7776 state->max_setup_return = SVAL(req->vwv+4, 0);
7777 state->close_on_completion = BITSETW(req->vwv+5, 0);
7778 state->one_way = BITSETW(req->vwv+5, 1);
7780 state->call = tran_call;
7782 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7783 is so as a sanity check */
7784 if (state->setup_count != 1) {
7786 * Need to have rc=0 for ioctl to get job id for OS/2.
7787 * Network printing will fail if function is not successful.
7788 * Similar function in reply.c will be used if protocol
7789 * is LANMAN1.0 instead of LM1.2X002.
7790 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7791 * outbuf doesn't have to be set(only job id is used).
7793 if ( (state->setup_count == 4)
7794 && (tran_call == TRANSACT2_IOCTL)
7795 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7796 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7797 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7799 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7800 DEBUG(2,("Transaction is %d\n",tran_call));
7802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7803 END_PROFILE(SMBtrans2);
7808 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7811 if (state->total_data) {
7813 if (trans_oob(state->total_data, 0, dscnt)
7814 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7818 /* Can't use talloc here, the core routines do realloc on the
7819 * params and data. */
7820 state->data = (char *)SMB_MALLOC(state->total_data);
7821 if (state->data == NULL) {
7822 DEBUG(0,("reply_trans2: data malloc fail for %u "
7823 "bytes !\n", (unsigned int)state->total_data));
7825 reply_nterror(req, NT_STATUS_NO_MEMORY);
7826 END_PROFILE(SMBtrans2);
7830 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7833 if (state->total_param) {
7835 if (trans_oob(state->total_param, 0, pscnt)
7836 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7840 /* Can't use talloc here, the core routines do realloc on the
7841 * params and data. */
7842 state->param = (char *)SMB_MALLOC(state->total_param);
7843 if (state->param == NULL) {
7844 DEBUG(0,("reply_trans: param malloc fail for %u "
7845 "bytes !\n", (unsigned int)state->total_param));
7846 SAFE_FREE(state->data);
7848 reply_nterror(req, NT_STATUS_NO_MEMORY);
7849 END_PROFILE(SMBtrans2);
7853 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7856 state->received_data = dscnt;
7857 state->received_param = pscnt;
7859 if ((state->received_param == state->total_param) &&
7860 (state->received_data == state->total_data)) {
7862 handle_trans2(conn, req, state);
7864 SAFE_FREE(state->data);
7865 SAFE_FREE(state->param);
7867 END_PROFILE(SMBtrans2);
7871 DLIST_ADD(conn->pending_trans, state);
7873 /* We need to send an interim response then receive the rest
7874 of the parameter/data bytes */
7875 reply_outbuf(req, 0, 0);
7876 show_msg((char *)req->outbuf);
7877 END_PROFILE(SMBtrans2);
7882 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7883 SAFE_FREE(state->data);
7884 SAFE_FREE(state->param);
7886 END_PROFILE(SMBtrans2);
7887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7891 /****************************************************************************
7892 Reply to a SMBtranss2
7893 ****************************************************************************/
7895 void reply_transs2(struct smb_request *req)
7897 connection_struct *conn = req->conn;
7898 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7899 struct trans_state *state;
7901 START_PROFILE(SMBtranss2);
7903 show_msg((char *)req->inbuf);
7906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7907 END_PROFILE(SMBtranss2);
7911 for (state = conn->pending_trans; state != NULL;
7912 state = state->next) {
7913 if (state->mid == req->mid) {
7918 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7920 END_PROFILE(SMBtranss2);
7924 /* Revise state->total_param and state->total_data in case they have
7925 changed downwards */
7927 if (SVAL(req->vwv+0, 0) < state->total_param)
7928 state->total_param = SVAL(req->vwv+0, 0);
7929 if (SVAL(req->vwv+1, 0) < state->total_data)
7930 state->total_data = SVAL(req->vwv+1, 0);
7932 pcnt = SVAL(req->vwv+2, 0);
7933 poff = SVAL(req->vwv+3, 0);
7934 pdisp = SVAL(req->vwv+4, 0);
7936 dcnt = SVAL(req->vwv+5, 0);
7937 doff = SVAL(req->vwv+6, 0);
7938 ddisp = SVAL(req->vwv+7, 0);
7940 state->received_param += pcnt;
7941 state->received_data += dcnt;
7943 if ((state->received_data > state->total_data) ||
7944 (state->received_param > state->total_param))
7948 if (trans_oob(state->total_param, pdisp, pcnt)
7949 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7952 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7956 if (trans_oob(state->total_data, ddisp, dcnt)
7957 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7960 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7963 if ((state->received_param < state->total_param) ||
7964 (state->received_data < state->total_data)) {
7965 END_PROFILE(SMBtranss2);
7969 handle_trans2(conn, req, state);
7971 DLIST_REMOVE(conn->pending_trans, state);
7972 SAFE_FREE(state->data);
7973 SAFE_FREE(state->param);
7976 END_PROFILE(SMBtranss2);
7981 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7982 DLIST_REMOVE(conn->pending_trans, state);
7983 SAFE_FREE(state->data);
7984 SAFE_FREE(state->param);
7986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7987 END_PROFILE(SMBtranss2);