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 = SMB_VFS_CREATE_FILE(
997 0, /* root_dir_fid */
998 smb_fname, /* fname */
999 access_mask, /* access_mask */
1000 share_mode, /* share_access */
1001 create_disposition, /* create_disposition*/
1002 create_options, /* create_options */
1003 open_attr, /* file_attributes */
1004 oplock_request, /* oplock_request */
1005 open_size, /* allocation_size */
1007 ea_list, /* ea_list */
1009 &smb_action); /* psbuf */
1011 if (!NT_STATUS_IS_OK(status)) {
1012 if (open_was_deferred(req->mid)) {
1013 /* We have re-scheduled this call. */
1016 reply_openerror(req, status);
1020 size = get_file_size_stat(&smb_fname->st);
1021 fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st);
1022 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1023 inode = smb_fname->st.st_ex_ino;
1025 close_file(req, fsp, ERROR_CLOSE);
1026 reply_doserror(req, ERRDOS,ERRnoaccess);
1030 /* Realloc the size of parameters and data we will return */
1031 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1032 if(*pparams == NULL ) {
1033 reply_nterror(req, NT_STATUS_NO_MEMORY);
1038 SSVAL(params,0,fsp->fnum);
1039 SSVAL(params,2,fattr);
1040 srv_put_dos_date2(params,4, mtime);
1041 SIVAL(params,8, (uint32)size);
1042 SSVAL(params,12,deny_mode);
1043 SSVAL(params,14,0); /* open_type - file or directory. */
1044 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1046 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1047 smb_action |= EXTENDED_OPLOCK_GRANTED;
1050 SSVAL(params,18,smb_action);
1053 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1055 SIVAL(params,20,inode);
1056 SSVAL(params,24,0); /* Padding. */
1058 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1059 SIVAL(params, 26, ea_size);
1061 SIVAL(params, 26, 0);
1064 /* Send the required number of replies */
1065 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1067 TALLOC_FREE(smb_fname);
1070 /*********************************************************
1071 Routine to check if a given string matches exactly.
1072 as a special case a mask of "." does NOT match. That
1073 is required for correct wildcard semantics
1074 Case can be significant or not.
1075 **********************************************************/
1077 static bool exact_match(connection_struct *conn,
1081 if (mask[0] == '.' && mask[1] == 0)
1083 if (dptr_has_wild(conn->dirptr)) {
1086 if (conn->case_sensitive)
1087 return strcmp(str,mask)==0;
1089 return StrCaseCmp(str,mask) == 0;
1092 /****************************************************************************
1093 Return the filetype for UNIX extensions.
1094 ****************************************************************************/
1096 static uint32 unix_filetype(mode_t mode)
1099 return UNIX_TYPE_FILE;
1100 else if(S_ISDIR(mode))
1101 return UNIX_TYPE_DIR;
1103 else if(S_ISLNK(mode))
1104 return UNIX_TYPE_SYMLINK;
1107 else if(S_ISCHR(mode))
1108 return UNIX_TYPE_CHARDEV;
1111 else if(S_ISBLK(mode))
1112 return UNIX_TYPE_BLKDEV;
1115 else if(S_ISFIFO(mode))
1116 return UNIX_TYPE_FIFO;
1119 else if(S_ISSOCK(mode))
1120 return UNIX_TYPE_SOCKET;
1123 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1124 return UNIX_TYPE_UNKNOWN;
1127 /****************************************************************************
1128 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1129 ****************************************************************************/
1131 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1133 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1134 SMB_STRUCT_STAT *psbuf,
1136 enum perm_type ptype,
1141 if (perms == SMB_MODE_NO_CHANGE) {
1142 if (!VALID_STAT(*psbuf)) {
1143 return NT_STATUS_INVALID_PARAMETER;
1145 *ret_perms = psbuf->st_ex_mode;
1146 return NT_STATUS_OK;
1150 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1151 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1152 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1153 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1154 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1155 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1156 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1157 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1158 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1160 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1163 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1166 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1171 /* Apply mode mask */
1172 ret &= lp_create_mask(SNUM(conn));
1173 /* Add in force bits */
1174 ret |= lp_force_create_mode(SNUM(conn));
1177 ret &= lp_dir_mask(SNUM(conn));
1178 /* Add in force bits */
1179 ret |= lp_force_dir_mode(SNUM(conn));
1181 case PERM_EXISTING_FILE:
1182 /* Apply mode mask */
1183 ret &= lp_security_mask(SNUM(conn));
1184 /* Add in force bits */
1185 ret |= lp_force_security_mode(SNUM(conn));
1187 case PERM_EXISTING_DIR:
1188 /* Apply mode mask */
1189 ret &= lp_dir_security_mask(SNUM(conn));
1190 /* Add in force bits */
1191 ret |= lp_force_dir_security_mode(SNUM(conn));
1196 return NT_STATUS_OK;
1199 /****************************************************************************
1200 Needed to show the msdfs symlinks as directories. Modifies psbuf
1201 to be a directory if it's a msdfs link.
1202 ****************************************************************************/
1204 static bool check_msdfs_link(connection_struct *conn,
1205 const char *pathname,
1206 SMB_STRUCT_STAT *psbuf)
1208 int saved_errno = errno;
1209 if(lp_host_msdfs() &&
1210 lp_msdfs_root(SNUM(conn)) &&
1211 is_msdfs_link(conn, pathname, psbuf)) {
1213 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1216 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1217 errno = saved_errno;
1220 errno = saved_errno;
1225 /****************************************************************************
1226 Get a level dependent lanman2 dir entry.
1227 ****************************************************************************/
1229 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1230 connection_struct *conn,
1232 const char *path_mask,
1235 int requires_resume_key,
1241 int space_remaining,
1243 bool *got_exact_match,
1244 int *last_entry_off,
1245 struct ea_list *name_list)
1249 SMB_STRUCT_STAT sbuf;
1250 const char *mask = NULL;
1251 char *pathreal = NULL;
1253 char *p, *q, *pdata = *ppdata;
1257 SMB_OFF_T file_size = 0;
1258 uint64_t allocation_size = 0;
1260 struct timespec mdate_ts, adate_ts, create_date_ts;
1261 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1263 char *last_entry_ptr;
1265 uint32 nt_extmode; /* Used for NT connections instead of mode */
1266 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1267 bool check_mangled_names = lp_manglednames(conn->params);
1268 char mangled_name[13]; /* mangled 8.3 name. */
1270 *out_of_space = False;
1271 *got_exact_match = False;
1273 ZERO_STRUCT(mdate_ts);
1274 ZERO_STRUCT(adate_ts);
1275 ZERO_STRUCT(create_date_ts);
1277 if (!conn->dirptr) {
1281 p = strrchr_m(path_mask,'/');
1284 mask = talloc_strdup(ctx,"*.*");
1294 bool ms_dfs_link = False;
1296 /* Needed if we run out of space */
1297 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1298 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1301 * Due to bugs in NT client redirectors we are not using
1302 * resume keys any more - set them to zero.
1303 * Check out the related comments in findfirst/findnext.
1309 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1310 (long)conn->dirptr,curr_dirpos));
1317 * fname may get mangled, dname is never mangled.
1318 * Whenever we're accessing the filesystem we use
1319 * pathreal which is composed from dname.
1325 /* Mangle fname if it's an illegal name. */
1326 if (mangle_must_mangle(dname,conn->params)) {
1327 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1329 continue; /* Error - couldn't mangle. */
1331 fname = talloc_strdup(ctx, mangled_name);
1337 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1338 got_match = mask_match(fname, mask, conn->case_sensitive);
1341 if(!got_match && check_mangled_names &&
1342 !mangle_is_8_3(fname, False, conn->params)) {
1344 * It turns out that NT matches wildcards against
1345 * both long *and* short names. This may explain some
1346 * of the wildcard wierdness from old DOS clients
1347 * that some people have been seeing.... JRA.
1349 /* Force the mangling into 8.3. */
1350 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1352 continue; /* Error - couldn't mangle. */
1355 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1356 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1361 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1363 if (dont_descend && !isdots) {
1370 pathreal = talloc_asprintf(ctx,
1375 pathreal = talloc_asprintf(ctx,
1386 if (INFO_LEVEL_IS_UNIX(info_level)) {
1387 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1388 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1389 pathreal,strerror(errno)));
1390 TALLOC_FREE(pathreal);
1394 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1395 /* Needed to show the msdfs symlinks as
1398 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1400 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1401 pathreal,strerror(errno)));
1402 TALLOC_FREE(pathreal);
1409 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1411 mode = dos_mode(conn,pathreal,&sbuf);
1414 if (!dir_check_ftype(conn,mode,dirtype)) {
1415 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1416 TALLOC_FREE(pathreal);
1421 if (!(mode & aDIR)) {
1422 file_size = get_file_size_stat(&sbuf);
1424 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1426 mdate_ts = sbuf.st_ex_mtime;
1427 adate_ts = sbuf.st_ex_atime;
1428 create_date_ts = sbuf.st_ex_btime;
1430 if (ask_sharemode) {
1431 struct timespec write_time_ts;
1432 struct file_id fileid;
1434 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1435 get_file_infos(fileid, NULL, &write_time_ts);
1436 if (!null_timespec(write_time_ts)) {
1437 mdate_ts = write_time_ts;
1441 if (lp_dos_filetime_resolution(SNUM(conn))) {
1442 dos_filetime_timespec(&create_date_ts);
1443 dos_filetime_timespec(&mdate_ts);
1444 dos_filetime_timespec(&adate_ts);
1447 create_date = convert_timespec_to_time_t(create_date_ts);
1448 mdate = convert_timespec_to_time_t(mdate_ts);
1449 adate = convert_timespec_to_time_t(adate_ts);
1451 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1456 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1466 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1468 switch (info_level) {
1469 case SMB_FIND_INFO_STANDARD:
1470 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1471 if(requires_resume_key) {
1475 srv_put_dos_date2(p,0,create_date);
1476 srv_put_dos_date2(p,4,adate);
1477 srv_put_dos_date2(p,8,mdate);
1478 SIVAL(p,12,(uint32)file_size);
1479 SIVAL(p,16,(uint32)allocation_size);
1483 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1484 p += ucs2_align(base_data, p, 0);
1486 len = srvstr_push(base_data, flags2, p,
1487 fname, PTR_DIFF(end_data, p),
1489 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1491 SCVAL(nameptr, -1, len - 2);
1493 SCVAL(nameptr, -1, 0);
1497 SCVAL(nameptr, -1, len - 1);
1499 SCVAL(nameptr, -1, 0);
1505 case SMB_FIND_EA_SIZE:
1506 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1507 if(requires_resume_key) {
1511 srv_put_dos_date2(p,0,create_date);
1512 srv_put_dos_date2(p,4,adate);
1513 srv_put_dos_date2(p,8,mdate);
1514 SIVAL(p,12,(uint32)file_size);
1515 SIVAL(p,16,(uint32)allocation_size);
1518 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1519 SIVAL(p,22,ea_size); /* Extended attributes */
1523 len = srvstr_push(base_data, flags2,
1524 p, fname, PTR_DIFF(end_data, p),
1525 STR_TERMINATE | STR_NOALIGN);
1526 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1539 SCVAL(nameptr,0,len);
1541 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1544 case SMB_FIND_EA_LIST:
1546 struct ea_list *file_list = NULL;
1549 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1553 if(requires_resume_key) {
1557 srv_put_dos_date2(p,0,create_date);
1558 srv_put_dos_date2(p,4,adate);
1559 srv_put_dos_date2(p,8,mdate);
1560 SIVAL(p,12,(uint32)file_size);
1561 SIVAL(p,16,(uint32)allocation_size);
1563 p += 22; /* p now points to the EA area. */
1565 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1566 name_list = ea_list_union(name_list, file_list, &ea_len);
1568 /* We need to determine if this entry will fit in the space available. */
1569 /* Max string size is 255 bytes. */
1570 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1571 /* Move the dirptr back to prev_dirpos */
1572 dptr_SeekDir(conn->dirptr, prev_dirpos);
1573 *out_of_space = True;
1574 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1575 return False; /* Not finished - just out of space */
1578 /* Push the ea_data followed by the name. */
1579 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1581 len = srvstr_push(base_data, flags2,
1582 p + 1, fname, PTR_DIFF(end_data, p+1),
1583 STR_TERMINATE | STR_NOALIGN);
1584 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1597 SCVAL(nameptr,0,len);
1599 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1603 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1604 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1605 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1607 SIVAL(p,0,reskey); p += 4;
1608 put_long_date_timespec(p,create_date_ts); p += 8;
1609 put_long_date_timespec(p,adate_ts); p += 8;
1610 put_long_date_timespec(p,mdate_ts); p += 8;
1611 put_long_date_timespec(p,mdate_ts); p += 8;
1612 SOFF_T(p,0,file_size); p += 8;
1613 SOFF_T(p,0,allocation_size); p += 8;
1614 SIVAL(p,0,nt_extmode); p += 4;
1615 q = p; p += 4; /* q is placeholder for name length. */
1617 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1618 SIVAL(p,0,ea_size); /* Extended attributes */
1621 /* Clear the short name buffer. This is
1622 * IMPORTANT as not doing so will trigger
1623 * a Win2k client bug. JRA.
1625 if (!was_8_3 && check_mangled_names) {
1626 if (!name_to_8_3(fname,mangled_name,True,
1628 /* Error - mangle failed ! */
1629 memset(mangled_name,'\0',12);
1631 mangled_name[12] = 0;
1632 len = srvstr_push(base_data, flags2,
1633 p+2, mangled_name, 24,
1634 STR_UPPER|STR_UNICODE);
1636 memset(p + 2 + len,'\0',24 - len);
1643 len = srvstr_push(base_data, flags2, p,
1644 fname, PTR_DIFF(end_data, p),
1645 STR_TERMINATE_ASCII);
1648 SIVAL(p,0,0); /* Ensure any padding is null. */
1649 len = PTR_DIFF(p, pdata);
1650 len = (len + 3) & ~3;
1655 case SMB_FIND_FILE_DIRECTORY_INFO:
1656 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1658 SIVAL(p,0,reskey); p += 4;
1659 put_long_date_timespec(p,create_date_ts); p += 8;
1660 put_long_date_timespec(p,adate_ts); p += 8;
1661 put_long_date_timespec(p,mdate_ts); p += 8;
1662 put_long_date_timespec(p,mdate_ts); p += 8;
1663 SOFF_T(p,0,file_size); p += 8;
1664 SOFF_T(p,0,allocation_size); p += 8;
1665 SIVAL(p,0,nt_extmode); p += 4;
1666 len = srvstr_push(base_data, flags2,
1667 p + 4, fname, PTR_DIFF(end_data, p+4),
1668 STR_TERMINATE_ASCII);
1671 SIVAL(p,0,0); /* Ensure any padding is null. */
1672 len = PTR_DIFF(p, pdata);
1673 len = (len + 3) & ~3;
1678 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1679 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1681 SIVAL(p,0,reskey); p += 4;
1682 put_long_date_timespec(p,create_date_ts); p += 8;
1683 put_long_date_timespec(p,adate_ts); p += 8;
1684 put_long_date_timespec(p,mdate_ts); p += 8;
1685 put_long_date_timespec(p,mdate_ts); p += 8;
1686 SOFF_T(p,0,file_size); p += 8;
1687 SOFF_T(p,0,allocation_size); p += 8;
1688 SIVAL(p,0,nt_extmode); p += 4;
1689 q = p; p += 4; /* q is placeholder for name length. */
1691 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1692 SIVAL(p,0,ea_size); /* Extended attributes */
1695 len = srvstr_push(base_data, flags2, p,
1696 fname, PTR_DIFF(end_data, p),
1697 STR_TERMINATE_ASCII);
1701 SIVAL(p,0,0); /* Ensure any padding is null. */
1702 len = PTR_DIFF(p, pdata);
1703 len = (len + 3) & ~3;
1708 case SMB_FIND_FILE_NAMES_INFO:
1709 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1711 SIVAL(p,0,reskey); p += 4;
1713 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1714 acl on a dir (tridge) */
1715 len = srvstr_push(base_data, flags2, p,
1716 fname, PTR_DIFF(end_data, p),
1717 STR_TERMINATE_ASCII);
1720 SIVAL(p,0,0); /* Ensure any padding is null. */
1721 len = PTR_DIFF(p, pdata);
1722 len = (len + 3) & ~3;
1727 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1728 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1730 SIVAL(p,0,reskey); p += 4;
1731 put_long_date_timespec(p,create_date_ts); p += 8;
1732 put_long_date_timespec(p,adate_ts); p += 8;
1733 put_long_date_timespec(p,mdate_ts); p += 8;
1734 put_long_date_timespec(p,mdate_ts); p += 8;
1735 SOFF_T(p,0,file_size); p += 8;
1736 SOFF_T(p,0,allocation_size); p += 8;
1737 SIVAL(p,0,nt_extmode); p += 4;
1738 q = p; p += 4; /* q is placeholder for name length. */
1740 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1741 SIVAL(p,0,ea_size); /* Extended attributes */
1744 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1745 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1746 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1747 len = srvstr_push(base_data, flags2, p,
1748 fname, PTR_DIFF(end_data, p),
1749 STR_TERMINATE_ASCII);
1752 SIVAL(p,0,0); /* Ensure any padding is null. */
1753 len = PTR_DIFF(p, pdata);
1754 len = (len + 3) & ~3;
1759 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1760 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1761 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1763 SIVAL(p,0,reskey); p += 4;
1764 put_long_date_timespec(p,create_date_ts); p += 8;
1765 put_long_date_timespec(p,adate_ts); p += 8;
1766 put_long_date_timespec(p,mdate_ts); p += 8;
1767 put_long_date_timespec(p,mdate_ts); p += 8;
1768 SOFF_T(p,0,file_size); p += 8;
1769 SOFF_T(p,0,allocation_size); p += 8;
1770 SIVAL(p,0,nt_extmode); p += 4;
1771 q = p; p += 4; /* q is placeholder for name length */
1773 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1774 SIVAL(p,0,ea_size); /* Extended attributes */
1777 /* Clear the short name buffer. This is
1778 * IMPORTANT as not doing so will trigger
1779 * a Win2k client bug. JRA.
1781 if (!was_8_3 && check_mangled_names) {
1782 if (!name_to_8_3(fname,mangled_name,True,
1784 /* Error - mangle failed ! */
1785 memset(mangled_name,'\0',12);
1787 mangled_name[12] = 0;
1788 len = srvstr_push(base_data, flags2,
1789 p+2, mangled_name, 24,
1790 STR_UPPER|STR_UNICODE);
1793 memset(p + 2 + len,'\0',24 - len);
1800 SSVAL(p,0,0); p += 2; /* Reserved ? */
1801 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1802 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1803 len = srvstr_push(base_data, flags2, p,
1804 fname, PTR_DIFF(end_data, p),
1805 STR_TERMINATE_ASCII);
1808 SIVAL(p,0,0); /* Ensure any padding is null. */
1809 len = PTR_DIFF(p, pdata);
1810 len = (len + 3) & ~3;
1815 /* CIFS UNIX Extension. */
1817 case SMB_FIND_FILE_UNIX:
1818 case SMB_FIND_FILE_UNIX_INFO2:
1820 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1822 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1824 if (info_level == SMB_FIND_FILE_UNIX) {
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1826 p = store_file_unix_basic(conn, p,
1828 len = srvstr_push(base_data, flags2, p,
1829 fname, PTR_DIFF(end_data, p),
1832 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1833 p = store_file_unix_basic_info2(conn, p,
1837 len = srvstr_push(base_data, flags2, p, fname,
1838 PTR_DIFF(end_data, p), 0);
1839 SIVAL(nameptr, 0, len);
1843 SIVAL(p,0,0); /* Ensure any padding is null. */
1845 len = PTR_DIFF(p, pdata);
1846 len = (len + 3) & ~3;
1847 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1849 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1859 if (PTR_DIFF(p,pdata) > space_remaining) {
1860 /* Move the dirptr back to prev_dirpos */
1861 dptr_SeekDir(conn->dirptr, prev_dirpos);
1862 *out_of_space = True;
1863 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1864 return False; /* Not finished - just out of space */
1867 /* Setup the last entry pointer, as an offset from base_data */
1868 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1869 /* Advance the data pointer to the next slot */
1875 /****************************************************************************
1876 Reply to a TRANS2_FINDFIRST.
1877 ****************************************************************************/
1879 static void call_trans2findfirst(connection_struct *conn,
1880 struct smb_request *req,
1881 char **pparams, int total_params,
1882 char **ppdata, int total_data,
1883 unsigned int max_data_bytes)
1885 /* We must be careful here that we don't return more than the
1886 allowed number of data bytes. If this means returning fewer than
1887 maxentries then so be it. We assume that the redirector has
1888 enough room for the fixed number of parameter bytes it has
1890 struct smb_filename *smb_dname = NULL;
1891 char *params = *pparams;
1892 char *pdata = *ppdata;
1896 uint16 findfirst_flags;
1897 bool close_after_first;
1899 bool requires_resume_key;
1901 char *directory = NULL;
1904 int last_entry_off=0;
1908 bool finished = False;
1909 bool dont_descend = False;
1910 bool out_of_space = False;
1911 int space_remaining;
1912 bool mask_contains_wcard = False;
1913 struct ea_list *ea_list = NULL;
1914 NTSTATUS ntstatus = NT_STATUS_OK;
1915 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1916 TALLOC_CTX *ctx = talloc_tos();
1918 if (total_params < 13) {
1919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1923 dirtype = SVAL(params,0);
1924 maxentries = SVAL(params,2);
1925 findfirst_flags = SVAL(params,4);
1926 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1927 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1928 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1929 info_level = SVAL(params,6);
1931 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1932 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1933 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1934 info_level, max_data_bytes));
1937 /* W2K3 seems to treat zero as 1. */
1941 switch (info_level) {
1942 case SMB_FIND_INFO_STANDARD:
1943 case SMB_FIND_EA_SIZE:
1944 case SMB_FIND_EA_LIST:
1945 case SMB_FIND_FILE_DIRECTORY_INFO:
1946 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1947 case SMB_FIND_FILE_NAMES_INFO:
1948 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1949 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1950 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1952 case SMB_FIND_FILE_UNIX:
1953 case SMB_FIND_FILE_UNIX_INFO2:
1954 /* Always use filesystem for UNIX mtime query. */
1955 ask_sharemode = false;
1956 if (!lp_unix_extensions()) {
1957 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1962 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1966 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1967 params+12, total_params - 12,
1968 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1969 if (!NT_STATUS_IS_OK(ntstatus)) {
1970 reply_nterror(req, ntstatus);
1974 ntstatus = resolve_dfspath_wcard(ctx, conn,
1975 req->flags2 & FLAGS2_DFS_PATHNAMES,
1978 &mask_contains_wcard);
1979 if (!NT_STATUS_IS_OK(ntstatus)) {
1980 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1981 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1982 ERRSRV, ERRbadpath);
1985 reply_nterror(req, ntstatus);
1989 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
1990 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
1991 if (!NT_STATUS_IS_OK(ntstatus)) {
1992 reply_nterror(req, ntstatus);
1996 mask = smb_dname->original_lcomp;
1998 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
1999 TALLOC_FREE(smb_dname);
2000 if (!NT_STATUS_IS_OK(ntstatus)) {
2001 reply_nterror(req, ntstatus);
2005 ntstatus = check_name(conn, directory);
2006 if (!NT_STATUS_IS_OK(ntstatus)) {
2007 reply_nterror(req, ntstatus);
2011 p = strrchr_m(directory,'/');
2013 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2014 if((directory[0] == '.') && (directory[1] == '\0')) {
2015 mask = talloc_strdup(ctx,"*");
2017 reply_nterror(req, NT_STATUS_NO_MEMORY);
2020 mask_contains_wcard = True;
2022 directory = talloc_strdup(talloc_tos(), "./");
2024 reply_nterror(req, NT_STATUS_NO_MEMORY);
2031 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2033 if (info_level == SMB_FIND_EA_LIST) {
2036 if (total_data < 4) {
2037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2041 ea_size = IVAL(pdata,0);
2042 if (ea_size != total_data) {
2043 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2044 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2045 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2049 if (!lp_ea_support(SNUM(conn))) {
2050 reply_doserror(req, ERRDOS, ERReasnotsupported);
2054 /* Pull out the list of names. */
2055 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2057 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2062 *ppdata = (char *)SMB_REALLOC(
2063 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2064 if(*ppdata == NULL ) {
2065 reply_nterror(req, NT_STATUS_NO_MEMORY);
2069 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2071 /* Realloc the params space */
2072 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2073 if (*pparams == NULL) {
2074 reply_nterror(req, NT_STATUS_NO_MEMORY);
2079 /* Save the wildcard match and attribs we are using on this directory -
2080 needed as lanman2 assumes these are being saved between calls */
2082 ntstatus = dptr_create(conn,
2088 mask_contains_wcard,
2092 if (!NT_STATUS_IS_OK(ntstatus)) {
2093 reply_nterror(req, ntstatus);
2097 dptr_num = dptr_dnum(conn->dirptr);
2098 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2100 /* Initialize per TRANS2_FIND_FIRST operation data */
2101 dptr_init_search_op(conn->dirptr);
2103 /* We don't need to check for VOL here as this is returned by
2104 a different TRANS2 call. */
2106 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2107 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2108 dont_descend = True;
2111 space_remaining = max_data_bytes;
2112 out_of_space = False;
2114 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2115 bool got_exact_match = False;
2117 /* this is a heuristic to avoid seeking the dirptr except when
2118 absolutely necessary. It allows for a filename of about 40 chars */
2119 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2120 out_of_space = True;
2123 finished = !get_lanman2_dir_entry(ctx,
2126 mask,dirtype,info_level,
2127 requires_resume_key,dont_descend,
2130 space_remaining, &out_of_space,
2132 &last_entry_off, ea_list);
2135 if (finished && out_of_space)
2138 if (!finished && !out_of_space)
2142 * As an optimisation if we know we aren't looking
2143 * for a wildcard name (ie. the name matches the wildcard exactly)
2144 * then we can finish on any (first) match.
2145 * This speeds up large directory searches. JRA.
2151 /* Ensure space_remaining never goes -ve. */
2152 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2153 space_remaining = 0;
2154 out_of_space = true;
2156 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2160 /* Check if we can close the dirptr */
2161 if(close_after_first || (finished && close_if_end)) {
2162 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2163 dptr_close(&dptr_num);
2167 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2168 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2169 * the protocol level is less than NT1. Tested with smbclient. JRA.
2170 * This should fix the OS/2 client bug #2335.
2173 if(numentries == 0) {
2174 dptr_close(&dptr_num);
2175 if (Protocol < PROTOCOL_NT1) {
2176 reply_doserror(req, ERRDOS, ERRnofiles);
2179 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2180 ERRDOS, ERRbadfile);
2185 /* At this point pdata points to numentries directory entries. */
2187 /* Set up the return parameter block */
2188 SSVAL(params,0,dptr_num);
2189 SSVAL(params,2,numentries);
2190 SSVAL(params,4,finished);
2191 SSVAL(params,6,0); /* Never an EA error */
2192 SSVAL(params,8,last_entry_off);
2194 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2197 if ((! *directory) && dptr_path(dptr_num)) {
2198 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2200 reply_nterror(req, NT_STATUS_NO_MEMORY);
2204 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2205 smb_fn_name(req->cmd),
2206 mask, directory, dirtype, numentries ) );
2209 * Force a name mangle here to ensure that the
2210 * mask as an 8.3 name is top of the mangled cache.
2211 * The reasons for this are subtle. Don't remove
2212 * this code unless you know what you are doing
2213 * (see PR#13758). JRA.
2216 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2217 char mangled_name[13];
2218 name_to_8_3(mask, mangled_name, True, conn->params);
2224 /****************************************************************************
2225 Reply to a TRANS2_FINDNEXT.
2226 ****************************************************************************/
2228 static void call_trans2findnext(connection_struct *conn,
2229 struct smb_request *req,
2230 char **pparams, int total_params,
2231 char **ppdata, int total_data,
2232 unsigned int max_data_bytes)
2234 /* We must be careful here that we don't return more than the
2235 allowed number of data bytes. If this means returning fewer than
2236 maxentries then so be it. We assume that the redirector has
2237 enough room for the fixed number of parameter bytes it has
2239 char *params = *pparams;
2240 char *pdata = *ppdata;
2246 uint16 findnext_flags;
2247 bool close_after_request;
2249 bool requires_resume_key;
2251 bool mask_contains_wcard = False;
2252 char *resume_name = NULL;
2253 const char *mask = NULL;
2254 const char *directory = NULL;
2258 int i, last_entry_off=0;
2259 bool finished = False;
2260 bool dont_descend = False;
2261 bool out_of_space = False;
2262 int space_remaining;
2263 struct ea_list *ea_list = NULL;
2264 NTSTATUS ntstatus = NT_STATUS_OK;
2265 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2266 TALLOC_CTX *ctx = talloc_tos();
2268 if (total_params < 13) {
2269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2273 dptr_num = SVAL(params,0);
2274 maxentries = SVAL(params,2);
2275 info_level = SVAL(params,4);
2276 resume_key = IVAL(params,6);
2277 findnext_flags = SVAL(params,10);
2278 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2279 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2280 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2281 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2283 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2285 total_params - 12, STR_TERMINATE, &ntstatus,
2286 &mask_contains_wcard);
2287 if (!NT_STATUS_IS_OK(ntstatus)) {
2288 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2289 complain (it thinks we're asking for the directory above the shared
2290 path or an invalid name). Catch this as the resume name is only compared, never used in
2291 a file access. JRA. */
2292 srvstr_pull_talloc(ctx, params, req->flags2,
2293 &resume_name, params+12,
2297 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2298 reply_nterror(req, ntstatus);
2303 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2304 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2305 resume_key = %d resume name = %s continue=%d level = %d\n",
2306 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2307 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2310 /* W2K3 seems to treat zero as 1. */
2314 switch (info_level) {
2315 case SMB_FIND_INFO_STANDARD:
2316 case SMB_FIND_EA_SIZE:
2317 case SMB_FIND_EA_LIST:
2318 case SMB_FIND_FILE_DIRECTORY_INFO:
2319 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2320 case SMB_FIND_FILE_NAMES_INFO:
2321 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2322 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2323 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2325 case SMB_FIND_FILE_UNIX:
2326 case SMB_FIND_FILE_UNIX_INFO2:
2327 /* Always use filesystem for UNIX mtime query. */
2328 ask_sharemode = false;
2329 if (!lp_unix_extensions()) {
2330 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2335 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2339 if (info_level == SMB_FIND_EA_LIST) {
2342 if (total_data < 4) {
2343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2347 ea_size = IVAL(pdata,0);
2348 if (ea_size != total_data) {
2349 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2350 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2355 if (!lp_ea_support(SNUM(conn))) {
2356 reply_doserror(req, ERRDOS, ERReasnotsupported);
2360 /* Pull out the list of names. */
2361 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2368 *ppdata = (char *)SMB_REALLOC(
2369 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2370 if(*ppdata == NULL) {
2371 reply_nterror(req, NT_STATUS_NO_MEMORY);
2376 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2378 /* Realloc the params space */
2379 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2380 if(*pparams == NULL ) {
2381 reply_nterror(req, NT_STATUS_NO_MEMORY);
2387 /* Check that the dptr is valid */
2388 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2389 reply_doserror(req, ERRDOS, ERRnofiles);
2393 string_set(&conn->dirpath,dptr_path(dptr_num));
2395 /* Get the wildcard mask from the dptr */
2396 if((p = dptr_wcard(dptr_num))== NULL) {
2397 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2398 reply_doserror(req, ERRDOS, ERRnofiles);
2403 directory = conn->dirpath;
2405 /* Get the attr mask from the dptr */
2406 dirtype = dptr_attr(dptr_num);
2408 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2409 dptr_num, mask, dirtype,
2411 dptr_TellDir(conn->dirptr)));
2413 /* Initialize per TRANS2_FIND_NEXT operation data */
2414 dptr_init_search_op(conn->dirptr);
2416 /* We don't need to check for VOL here as this is returned by
2417 a different TRANS2 call. */
2419 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2420 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2421 dont_descend = True;
2424 space_remaining = max_data_bytes;
2425 out_of_space = False;
2428 * Seek to the correct position. We no longer use the resume key but
2429 * depend on the last file name instead.
2432 if(*resume_name && !continue_bit) {
2435 long current_pos = 0;
2437 * Remember, name_to_8_3 is called by
2438 * get_lanman2_dir_entry(), so the resume name
2439 * could be mangled. Ensure we check the unmangled name.
2442 if (mangle_is_mangled(resume_name, conn->params)) {
2443 char *new_resume_name = NULL;
2444 mangle_lookup_name_from_8_3(ctx,
2448 if (new_resume_name) {
2449 resume_name = new_resume_name;
2454 * Fix for NT redirector problem triggered by resume key indexes
2455 * changing between directory scans. We now return a resume key of 0
2456 * and instead look for the filename to continue from (also given
2457 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2458 * findfirst/findnext (as is usual) then the directory pointer
2459 * should already be at the correct place.
2462 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2463 } /* end if resume_name && !continue_bit */
2465 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2466 bool got_exact_match = False;
2468 /* this is a heuristic to avoid seeking the dirptr except when
2469 absolutely necessary. It allows for a filename of about 40 chars */
2470 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2471 out_of_space = True;
2474 finished = !get_lanman2_dir_entry(ctx,
2477 mask,dirtype,info_level,
2478 requires_resume_key,dont_descend,
2481 space_remaining, &out_of_space,
2483 &last_entry_off, ea_list);
2486 if (finished && out_of_space)
2489 if (!finished && !out_of_space)
2493 * As an optimisation if we know we aren't looking
2494 * for a wildcard name (ie. the name matches the wildcard exactly)
2495 * then we can finish on any (first) match.
2496 * This speeds up large directory searches. JRA.
2502 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2505 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2506 smb_fn_name(req->cmd),
2507 mask, directory, dirtype, numentries ) );
2509 /* Check if we can close the dirptr */
2510 if(close_after_request || (finished && close_if_end)) {
2511 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2512 dptr_close(&dptr_num); /* This frees up the saved mask */
2515 /* Set up the return parameter block */
2516 SSVAL(params,0,numentries);
2517 SSVAL(params,2,finished);
2518 SSVAL(params,4,0); /* Never an EA error */
2519 SSVAL(params,6,last_entry_off);
2521 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2527 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2529 E_md4hash(lp_servicename(SNUM(conn)),objid);
2533 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2535 SMB_ASSERT(extended_info != NULL);
2537 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2538 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2539 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2540 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2541 #ifdef SAMBA_VERSION_REVISION
2542 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2544 extended_info->samba_subversion = 0;
2545 #ifdef SAMBA_VERSION_RC_RELEASE
2546 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2548 #ifdef SAMBA_VERSION_PRE_RELEASE
2549 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2552 #ifdef SAMBA_VERSION_VENDOR_PATCH
2553 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2555 extended_info->samba_gitcommitdate = 0;
2556 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2557 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2560 memset(extended_info->samba_version_string, 0,
2561 sizeof(extended_info->samba_version_string));
2563 snprintf (extended_info->samba_version_string,
2564 sizeof(extended_info->samba_version_string),
2565 "%s", samba_version_string());
2568 /****************************************************************************
2569 Reply to a TRANS2_QFSINFO (query filesystem info).
2570 ****************************************************************************/
2572 static void call_trans2qfsinfo(connection_struct *conn,
2573 struct smb_request *req,
2574 char **pparams, int total_params,
2575 char **ppdata, int total_data,
2576 unsigned int max_data_bytes)
2578 char *pdata, *end_data;
2579 char *params = *pparams;
2583 const char *vname = volume_label(SNUM(conn));
2584 int snum = SNUM(conn);
2585 char *fstype = lp_fstype(SNUM(conn));
2586 uint32 additional_flags = 0;
2588 if (total_params < 2) {
2589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2593 info_level = SVAL(params,0);
2596 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2597 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2598 "info level (0x%x) on IPC$.\n",
2599 (unsigned int)info_level));
2600 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2605 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2606 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2607 DEBUG(0,("call_trans2qfsinfo: encryption required "
2608 "and info level 0x%x sent.\n",
2609 (unsigned int)info_level));
2610 exit_server_cleanly("encryption required "
2616 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2618 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2619 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2620 reply_doserror(req, ERRSRV, ERRinvdevice);
2624 *ppdata = (char *)SMB_REALLOC(
2625 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2626 if (*ppdata == NULL ) {
2627 reply_nterror(req, NT_STATUS_NO_MEMORY);
2632 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2633 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2635 switch (info_level) {
2636 case SMB_INFO_ALLOCATION:
2638 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2640 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2641 reply_unixerror(req, ERRHRD, ERRgeneral);
2645 block_size = lp_block_size(snum);
2646 if (bsize < block_size) {
2647 uint64_t factor = block_size/bsize;
2652 if (bsize > block_size) {
2653 uint64_t factor = bsize/block_size;
2658 bytes_per_sector = 512;
2659 sectors_per_unit = bsize/bytes_per_sector;
2661 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2662 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2663 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2665 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2666 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2667 SIVAL(pdata,l1_cUnit,dsize);
2668 SIVAL(pdata,l1_cUnitAvail,dfree);
2669 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2673 case SMB_INFO_VOLUME:
2674 /* Return volume name */
2676 * Add volume serial number - hash of a combination of
2677 * the called hostname and the service name.
2679 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2681 * Win2k3 and previous mess this up by sending a name length
2682 * one byte short. I believe only older clients (OS/2 Win9x) use
2683 * this call so try fixing this by adding a terminating null to
2684 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2688 pdata+l2_vol_szVolLabel, vname,
2689 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2690 STR_NOALIGN|STR_TERMINATE);
2691 SCVAL(pdata,l2_vol_cch,len);
2692 data_len = l2_vol_szVolLabel + len;
2693 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2694 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2698 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2699 case SMB_FS_ATTRIBUTE_INFORMATION:
2701 additional_flags = 0;
2702 #if defined(HAVE_SYS_QUOTAS)
2703 additional_flags |= FILE_VOLUME_QUOTAS;
2706 if(lp_nt_acl_support(SNUM(conn))) {
2707 additional_flags |= FILE_PERSISTENT_ACLS;
2710 /* Capabilities are filled in at connection time through STATVFS call */
2711 additional_flags |= conn->fs_capabilities;
2713 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2714 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2715 additional_flags); /* FS ATTRIBUTES */
2717 SIVAL(pdata,4,255); /* Max filename component length */
2718 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2719 and will think we can't do long filenames */
2720 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2721 PTR_DIFF(end_data, pdata+12),
2724 data_len = 12 + len;
2727 case SMB_QUERY_FS_LABEL_INFO:
2728 case SMB_FS_LABEL_INFORMATION:
2729 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2730 PTR_DIFF(end_data, pdata+4), 0);
2735 case SMB_QUERY_FS_VOLUME_INFO:
2736 case SMB_FS_VOLUME_INFORMATION:
2739 * Add volume serial number - hash of a combination of
2740 * the called hostname and the service name.
2742 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2743 (str_checksum(get_local_machine_name())<<16));
2745 /* Max label len is 32 characters. */
2746 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2747 PTR_DIFF(end_data, pdata+18),
2749 SIVAL(pdata,12,len);
2752 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2753 (int)strlen(vname),vname, lp_servicename(snum)));
2756 case SMB_QUERY_FS_SIZE_INFO:
2757 case SMB_FS_SIZE_INFORMATION:
2759 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2761 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2762 reply_unixerror(req, ERRHRD, ERRgeneral);
2765 block_size = lp_block_size(snum);
2766 if (bsize < block_size) {
2767 uint64_t factor = block_size/bsize;
2772 if (bsize > block_size) {
2773 uint64_t factor = bsize/block_size;
2778 bytes_per_sector = 512;
2779 sectors_per_unit = bsize/bytes_per_sector;
2780 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2781 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2782 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2783 SBIG_UINT(pdata,0,dsize);
2784 SBIG_UINT(pdata,8,dfree);
2785 SIVAL(pdata,16,sectors_per_unit);
2786 SIVAL(pdata,20,bytes_per_sector);
2790 case SMB_FS_FULL_SIZE_INFORMATION:
2792 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2794 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2795 reply_unixerror(req, ERRHRD, ERRgeneral);
2798 block_size = lp_block_size(snum);
2799 if (bsize < block_size) {
2800 uint64_t factor = block_size/bsize;
2805 if (bsize > block_size) {
2806 uint64_t factor = bsize/block_size;
2811 bytes_per_sector = 512;
2812 sectors_per_unit = bsize/bytes_per_sector;
2813 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2814 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2815 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2816 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2817 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2818 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2819 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2820 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2824 case SMB_QUERY_FS_DEVICE_INFO:
2825 case SMB_FS_DEVICE_INFORMATION:
2827 SIVAL(pdata,0,0); /* dev type */
2828 SIVAL(pdata,4,0); /* characteristics */
2831 #ifdef HAVE_SYS_QUOTAS
2832 case SMB_FS_QUOTA_INFORMATION:
2834 * what we have to send --metze:
2836 * Unknown1: 24 NULL bytes
2837 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2838 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2839 * Quota Flags: 2 byte :
2840 * Unknown3: 6 NULL bytes
2844 * details for Quota Flags:
2846 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2847 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2848 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2849 * 0x0001 Enable Quotas: enable quota for this fs
2853 /* we need to fake up a fsp here,
2854 * because its not send in this call
2857 SMB_NTQUOTA_STRUCT quotas;
2860 ZERO_STRUCT(quotas);
2866 if (conn->server_info->utok.uid != 0) {
2867 DEBUG(0,("set_user_quota: access_denied "
2868 "service [%s] user [%s]\n",
2869 lp_servicename(SNUM(conn)),
2870 conn->server_info->unix_name));
2871 reply_doserror(req, ERRDOS, ERRnoaccess);
2875 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2876 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2877 reply_doserror(req, ERRSRV, ERRerror);
2883 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2885 /* Unknown1 24 NULL bytes*/
2886 SBIG_UINT(pdata,0,(uint64_t)0);
2887 SBIG_UINT(pdata,8,(uint64_t)0);
2888 SBIG_UINT(pdata,16,(uint64_t)0);
2890 /* Default Soft Quota 8 bytes */
2891 SBIG_UINT(pdata,24,quotas.softlim);
2893 /* Default Hard Quota 8 bytes */
2894 SBIG_UINT(pdata,32,quotas.hardlim);
2896 /* Quota flag 2 bytes */
2897 SSVAL(pdata,40,quotas.qflags);
2899 /* Unknown3 6 NULL bytes */
2905 #endif /* HAVE_SYS_QUOTAS */
2906 case SMB_FS_OBJECTID_INFORMATION:
2908 unsigned char objid[16];
2909 struct smb_extended_info extended_info;
2910 memcpy(pdata,create_volume_objectid(conn, objid),16);
2911 samba_extended_info_version (&extended_info);
2912 SIVAL(pdata,16,extended_info.samba_magic);
2913 SIVAL(pdata,20,extended_info.samba_version);
2914 SIVAL(pdata,24,extended_info.samba_subversion);
2915 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2916 memcpy(pdata+36,extended_info.samba_version_string,28);
2922 * Query the version and capabilities of the CIFS UNIX extensions
2926 case SMB_QUERY_CIFS_UNIX_INFO:
2928 bool large_write = lp_min_receive_file_size() &&
2929 !srv_is_signing_active(smbd_server_conn);
2930 bool large_read = !srv_is_signing_active(smbd_server_conn);
2931 int encrypt_caps = 0;
2933 if (!lp_unix_extensions()) {
2934 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2938 switch (conn->encrypt_level) {
2944 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2947 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2948 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2949 large_write = false;
2955 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2956 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2958 /* We have POSIX ACLs, pathname, encryption,
2959 * large read/write, and locking capability. */
2961 SBIG_UINT(pdata,4,((uint64_t)(
2962 CIFS_UNIX_POSIX_ACLS_CAP|
2963 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2964 CIFS_UNIX_FCNTL_LOCKS_CAP|
2965 CIFS_UNIX_EXTATTR_CAP|
2966 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2968 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2970 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2974 case SMB_QUERY_POSIX_FS_INFO:
2977 vfs_statvfs_struct svfs;
2979 if (!lp_unix_extensions()) {
2980 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2984 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2988 SIVAL(pdata,0,svfs.OptimalTransferSize);
2989 SIVAL(pdata,4,svfs.BlockSize);
2990 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2991 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2992 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2993 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2994 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2995 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2996 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2998 } else if (rc == EOPNOTSUPP) {
2999 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3001 #endif /* EOPNOTSUPP */
3003 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3004 reply_doserror(req, ERRSRV, ERRerror);
3010 case SMB_QUERY_POSIX_WHOAMI:
3016 if (!lp_unix_extensions()) {
3017 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3021 if (max_data_bytes < 40) {
3022 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3026 /* We ARE guest if global_sid_Builtin_Guests is
3027 * in our list of SIDs.
3029 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3030 conn->server_info->ptok)) {
3031 flags |= SMB_WHOAMI_GUEST;
3034 /* We are NOT guest if global_sid_Authenticated_Users
3035 * is in our list of SIDs.
3037 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3038 conn->server_info->ptok)) {
3039 flags &= ~SMB_WHOAMI_GUEST;
3042 /* NOTE: 8 bytes for UID/GID, irrespective of native
3043 * platform size. This matches
3044 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3046 data_len = 4 /* flags */
3053 + 4 /* pad/reserved */
3054 + (conn->server_info->utok.ngroups * 8)
3056 + (conn->server_info->ptok->num_sids *
3060 SIVAL(pdata, 0, flags);
3061 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3063 (uint64_t)conn->server_info->utok.uid);
3064 SBIG_UINT(pdata, 16,
3065 (uint64_t)conn->server_info->utok.gid);
3068 if (data_len >= max_data_bytes) {
3069 /* Potential overflow, skip the GIDs and SIDs. */
3071 SIVAL(pdata, 24, 0); /* num_groups */
3072 SIVAL(pdata, 28, 0); /* num_sids */
3073 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3074 SIVAL(pdata, 36, 0); /* reserved */
3080 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3081 SIVAL(pdata, 28, conn->server_info->num_sids);
3083 /* We walk the SID list twice, but this call is fairly
3084 * infrequent, and I don't expect that it's performance
3085 * sensitive -- jpeach
3087 for (i = 0, sid_bytes = 0;
3088 i < conn->server_info->ptok->num_sids; ++i) {
3089 sid_bytes += ndr_size_dom_sid(
3090 &conn->server_info->ptok->user_sids[i],
3095 /* SID list byte count */
3096 SIVAL(pdata, 32, sid_bytes);
3098 /* 4 bytes pad/reserved - must be zero */
3099 SIVAL(pdata, 36, 0);
3103 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3104 SBIG_UINT(pdata, data_len,
3105 (uint64_t)conn->server_info->utok.groups[i]);
3111 i < conn->server_info->ptok->num_sids; ++i) {
3112 int sid_len = ndr_size_dom_sid(
3113 &conn->server_info->ptok->user_sids[i],
3117 sid_linearize(pdata + data_len, sid_len,
3118 &conn->server_info->ptok->user_sids[i]);
3119 data_len += sid_len;
3125 case SMB_MAC_QUERY_FS_INFO:
3127 * Thursby MAC extension... ONLY on NTFS filesystems
3128 * once we do streams then we don't need this
3130 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3132 SIVAL(pdata,84,0x100); /* Don't support mac... */
3137 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3142 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3145 DEBUG( 4, ( "%s info_level = %d\n",
3146 smb_fn_name(req->cmd), info_level) );
3151 /****************************************************************************
3152 Reply to a TRANS2_SETFSINFO (set filesystem info).
3153 ****************************************************************************/
3155 static void call_trans2setfsinfo(connection_struct *conn,
3156 struct smb_request *req,
3157 char **pparams, int total_params,
3158 char **ppdata, int total_data,
3159 unsigned int max_data_bytes)
3161 char *pdata = *ppdata;
3162 char *params = *pparams;
3165 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3168 if (total_params < 4) {
3169 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3175 info_level = SVAL(params,2);
3178 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3179 info_level != SMB_SET_CIFS_UNIX_INFO) {
3180 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3181 "info level (0x%x) on IPC$.\n",
3182 (unsigned int)info_level));
3183 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3188 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3189 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3190 DEBUG(0,("call_trans2setfsinfo: encryption required "
3191 "and info level 0x%x sent.\n",
3192 (unsigned int)info_level));
3193 exit_server_cleanly("encryption required "
3199 switch(info_level) {
3200 case SMB_SET_CIFS_UNIX_INFO:
3202 uint16 client_unix_major;
3203 uint16 client_unix_minor;
3204 uint32 client_unix_cap_low;
3205 uint32 client_unix_cap_high;
3207 if (!lp_unix_extensions()) {
3209 NT_STATUS_INVALID_LEVEL);
3213 /* There should be 12 bytes of capabilities set. */
3214 if (total_data < 8) {
3217 NT_STATUS_INVALID_PARAMETER);
3220 client_unix_major = SVAL(pdata,0);
3221 client_unix_minor = SVAL(pdata,2);
3222 client_unix_cap_low = IVAL(pdata,4);
3223 client_unix_cap_high = IVAL(pdata,8);
3224 /* Just print these values for now. */
3225 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3226 cap_low = 0x%x, cap_high = 0x%x\n",
3227 (unsigned int)client_unix_major,
3228 (unsigned int)client_unix_minor,
3229 (unsigned int)client_unix_cap_low,
3230 (unsigned int)client_unix_cap_high ));
3232 /* Here is where we must switch to posix pathname processing... */
3233 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3234 lp_set_posix_pathnames();
3235 mangle_change_to_posix();
3238 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3239 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3240 /* Client that knows how to do posix locks,
3241 * but not posix open/mkdir operations. Set a
3242 * default type for read/write checks. */
3244 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3250 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3253 size_t param_len = 0;
3254 size_t data_len = total_data;
3256 if (!lp_unix_extensions()) {
3259 NT_STATUS_INVALID_LEVEL);
3263 if (lp_smb_encrypt(SNUM(conn)) == false) {
3266 NT_STATUS_NOT_SUPPORTED);
3270 DEBUG( 4,("call_trans2setfsinfo: "
3271 "request transport encryption.\n"));
3273 status = srv_request_encryption_setup(conn,
3274 (unsigned char **)ppdata,
3276 (unsigned char **)pparams,
3279 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3280 !NT_STATUS_IS_OK(status)) {
3281 reply_nterror(req, status);
3285 send_trans2_replies(conn, req,
3292 if (NT_STATUS_IS_OK(status)) {
3293 /* Server-side transport
3294 * encryption is now *on*. */
3295 status = srv_encryption_start(conn);
3296 if (!NT_STATUS_IS_OK(status)) {
3297 exit_server_cleanly(
3298 "Failure in setting "
3299 "up encrypted transport");
3305 case SMB_FS_QUOTA_INFORMATION:
3307 files_struct *fsp = NULL;
3308 SMB_NTQUOTA_STRUCT quotas;
3310 ZERO_STRUCT(quotas);
3313 if ((conn->server_info->utok.uid != 0)
3314 ||!CAN_WRITE(conn)) {
3315 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3316 lp_servicename(SNUM(conn)),
3317 conn->server_info->unix_name));
3318 reply_doserror(req, ERRSRV, ERRaccess);
3322 /* note: normaly there're 48 bytes,
3323 * but we didn't use the last 6 bytes for now
3326 fsp = file_fsp(req, SVAL(params,0));
3328 if (!check_fsp_ntquota_handle(conn, req,
3330 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3332 req, NT_STATUS_INVALID_HANDLE);
3336 if (total_data < 42) {
3337 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3341 NT_STATUS_INVALID_PARAMETER);
3345 /* unknown_1 24 NULL bytes in pdata*/
3347 /* the soft quotas 8 bytes (uint64_t)*/
3348 quotas.softlim = (uint64_t)IVAL(pdata,24);
3349 #ifdef LARGE_SMB_OFF_T
3350 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3351 #else /* LARGE_SMB_OFF_T */
3352 if ((IVAL(pdata,28) != 0)&&
3353 ((quotas.softlim != 0xFFFFFFFF)||
3354 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3355 /* more than 32 bits? */
3358 NT_STATUS_INVALID_PARAMETER);
3361 #endif /* LARGE_SMB_OFF_T */
3363 /* the hard quotas 8 bytes (uint64_t)*/
3364 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3365 #ifdef LARGE_SMB_OFF_T
3366 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3367 #else /* LARGE_SMB_OFF_T */
3368 if ((IVAL(pdata,36) != 0)&&
3369 ((quotas.hardlim != 0xFFFFFFFF)||
3370 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3371 /* more than 32 bits? */
3374 NT_STATUS_INVALID_PARAMETER);
3377 #endif /* LARGE_SMB_OFF_T */
3379 /* quota_flags 2 bytes **/
3380 quotas.qflags = SVAL(pdata,40);
3382 /* unknown_2 6 NULL bytes follow*/
3384 /* now set the quotas */
3385 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3386 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3387 reply_doserror(req, ERRSRV, ERRerror);
3394 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3396 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3402 * sending this reply works fine,
3403 * but I'm not sure it's the same
3404 * like windows do...
3407 reply_outbuf(req, 10, 0);
3410 #if defined(HAVE_POSIX_ACLS)
3411 /****************************************************************************
3412 Utility function to count the number of entries in a POSIX acl.
3413 ****************************************************************************/
3415 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3417 unsigned int ace_count = 0;
3418 int entry_id = SMB_ACL_FIRST_ENTRY;
3419 SMB_ACL_ENTRY_T entry;
3421 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3423 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3424 entry_id = SMB_ACL_NEXT_ENTRY;
3431 /****************************************************************************
3432 Utility function to marshall a POSIX acl into wire format.
3433 ****************************************************************************/
3435 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3437 int entry_id = SMB_ACL_FIRST_ENTRY;
3438 SMB_ACL_ENTRY_T entry;
3440 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3441 SMB_ACL_TAG_T tagtype;
3442 SMB_ACL_PERMSET_T permset;
3443 unsigned char perms = 0;
3444 unsigned int own_grp;
3447 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3448 entry_id = SMB_ACL_NEXT_ENTRY;
3451 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3452 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3456 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3457 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3461 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3462 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3463 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3465 SCVAL(pdata,1,perms);
3468 case SMB_ACL_USER_OBJ:
3469 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3470 own_grp = (unsigned int)pst->st_ex_uid;
3471 SIVAL(pdata,2,own_grp);
3476 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3478 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3481 own_grp = (unsigned int)*puid;
3482 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3483 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3484 SIVAL(pdata,2,own_grp);
3488 case SMB_ACL_GROUP_OBJ:
3489 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3490 own_grp = (unsigned int)pst->st_ex_gid;
3491 SIVAL(pdata,2,own_grp);
3496 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3498 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3501 own_grp = (unsigned int)*pgid;
3502 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3503 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3504 SIVAL(pdata,2,own_grp);
3509 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3510 SIVAL(pdata,2,0xFFFFFFFF);
3511 SIVAL(pdata,6,0xFFFFFFFF);
3514 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3515 SIVAL(pdata,2,0xFFFFFFFF);
3516 SIVAL(pdata,6,0xFFFFFFFF);
3519 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3522 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3529 /****************************************************************************
3530 Store the FILE_UNIX_BASIC info.
3531 ****************************************************************************/
3533 static char *store_file_unix_basic(connection_struct *conn,
3536 const SMB_STRUCT_STAT *psbuf)
3538 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3539 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3541 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3544 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3547 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3548 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3549 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3552 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3556 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3560 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3563 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3567 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3571 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3574 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3578 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3585 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3586 * the chflags(2) (or equivalent) flags.
3588 * XXX: this really should be behind the VFS interface. To do this, we would
3589 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3590 * Each VFS module could then implement its own mapping as appropriate for the
3591 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3593 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3597 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3601 { UF_IMMUTABLE, EXT_IMMUTABLE },
3605 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3609 { UF_HIDDEN, EXT_HIDDEN },
3612 /* Do not remove. We need to guarantee that this array has at least one
3613 * entry to build on HP-UX.
3619 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3620 uint32 *smb_fflags, uint32 *smb_fmask)
3624 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3625 *smb_fmask |= info2_flags_map[i].smb_fflag;
3626 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3627 *smb_fflags |= info2_flags_map[i].smb_fflag;
3632 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3633 const uint32 smb_fflags,
3634 const uint32 smb_fmask,
3637 uint32 max_fmask = 0;
3640 *stat_fflags = psbuf->st_ex_flags;
3642 /* For each flags requested in smb_fmask, check the state of the
3643 * corresponding flag in smb_fflags and set or clear the matching
3647 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3648 max_fmask |= info2_flags_map[i].smb_fflag;
3649 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3650 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3651 *stat_fflags |= info2_flags_map[i].stat_fflag;
3653 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3658 /* If smb_fmask is asking to set any bits that are not supported by
3659 * our flag mappings, we should fail.
3661 if ((smb_fmask & max_fmask) != smb_fmask) {
3669 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3670 * of file flags and birth (create) time.
3672 static char *store_file_unix_basic_info2(connection_struct *conn,
3675 const SMB_STRUCT_STAT *psbuf)
3677 uint32 file_flags = 0;
3678 uint32 flags_mask = 0;
3680 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3682 /* Create (birth) time 64 bit */
3683 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3686 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3687 SIVAL(pdata, 0, file_flags); /* flags */
3688 SIVAL(pdata, 4, flags_mask); /* mask */
3694 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3695 const struct stream_struct *streams,
3697 unsigned int max_data_bytes,
3698 unsigned int *data_size)
3701 unsigned int ofs = 0;
3703 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3704 unsigned int next_offset;
3706 smb_ucs2_t *namebuf;
3708 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3709 streams[i].name, &namelen) ||
3712 return NT_STATUS_INVALID_PARAMETER;
3716 * name_buf is now null-terminated, we need to marshall as not
3722 SIVAL(data, ofs+4, namelen);
3723 SOFF_T(data, ofs+8, streams[i].size);
3724 SOFF_T(data, ofs+16, streams[i].alloc_size);
3725 memcpy(data+ofs+24, namebuf, namelen);
3726 TALLOC_FREE(namebuf);
3728 next_offset = ofs + 24 + namelen;
3730 if (i == num_streams-1) {
3731 SIVAL(data, ofs, 0);
3734 unsigned int align = ndr_align_size(next_offset, 8);
3736 memset(data+next_offset, 0, align);
3737 next_offset += align;
3739 SIVAL(data, ofs, next_offset - ofs);
3748 return NT_STATUS_OK;
3751 /****************************************************************************
3752 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3753 ****************************************************************************/
3755 static void call_trans2qpipeinfo(connection_struct *conn,
3756 struct smb_request *req,
3757 unsigned int tran_call,
3758 char **pparams, int total_params,
3759 char **ppdata, int total_data,
3760 unsigned int max_data_bytes)
3762 char *params = *pparams;
3763 char *pdata = *ppdata;
3764 unsigned int data_size = 0;
3765 unsigned int param_size = 2;
3770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3774 if (total_params < 4) {
3775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3779 fsp = file_fsp(req, SVAL(params,0));
3780 if (!fsp_is_np(fsp)) {
3781 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3785 info_level = SVAL(params,2);
3787 *pparams = (char *)SMB_REALLOC(*pparams,2);
3788 if (*pparams == NULL) {
3789 reply_nterror(req, NT_STATUS_NO_MEMORY);
3794 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3795 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3796 if (*ppdata == NULL ) {
3797 reply_nterror(req, NT_STATUS_NO_MEMORY);
3802 switch (info_level) {
3803 case SMB_FILE_STANDARD_INFORMATION:
3805 SOFF_T(pdata,0,4096LL);
3812 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3816 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3822 /****************************************************************************
3823 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3824 file name or file id).
3825 ****************************************************************************/
3827 static void call_trans2qfilepathinfo(connection_struct *conn,
3828 struct smb_request *req,
3829 unsigned int tran_call,
3830 char **pparams, int total_params,
3831 char **ppdata, int total_data,
3832 unsigned int max_data_bytes)
3834 char *params = *pparams;
3835 char *pdata = *ppdata;
3836 char *dstart, *dend;
3840 SMB_OFF_T file_size=0;
3841 uint64_t allocation_size=0;
3842 unsigned int data_size = 0;
3843 unsigned int param_size = 2;
3844 SMB_STRUCT_STAT sbuf;
3845 char *dos_fname = NULL;
3847 struct smb_filename *smb_fname = NULL;
3852 bool delete_pending = False;
3854 time_t create_time, mtime, atime;
3855 struct timespec create_time_ts, mtime_ts, atime_ts;
3856 struct timespec write_time_ts;
3857 files_struct *fsp = NULL;
3858 struct file_id fileid;
3859 struct ea_list *ea_list = NULL;
3860 char *lock_data = NULL;
3861 bool ms_dfs_link = false;
3862 TALLOC_CTX *ctx = talloc_tos();
3865 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3870 ZERO_STRUCT(write_time_ts);
3872 if (tran_call == TRANSACT2_QFILEINFO) {
3873 if (total_params < 4) {
3874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3879 call_trans2qpipeinfo(conn, req, tran_call,
3880 pparams, total_params,
3886 fsp = file_fsp(req, SVAL(params,0));
3887 info_level = SVAL(params,2);
3889 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3891 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3892 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3896 /* Initial check for valid fsp ptr. */
3897 if (!check_fsp_open(conn, req, fsp)) {
3901 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3903 reply_nterror(req, NT_STATUS_NO_MEMORY);
3907 if(fsp->fake_file_handle) {
3909 * This is actually for the QUOTA_FAKE_FILE --metze
3912 /* We know this name is ok, it's already passed the checks. */
3914 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3916 * This is actually a QFILEINFO on a directory
3917 * handle (returned from an NT SMB). NT5.0 seems
3918 * to do this call. JRA.
3921 if (INFO_LEVEL_IS_UNIX(info_level)) {
3922 /* Always do lstat for UNIX calls. */
3923 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3924 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3925 reply_unixerror(req,ERRDOS,ERRbadpath);
3928 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3929 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3930 reply_unixerror(req, ERRDOS, ERRbadpath);
3934 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3935 get_file_infos(fileid, &delete_pending, &write_time_ts);
3938 * Original code - this is an open file.
3940 if (!check_fsp(conn, req, fsp)) {
3944 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3945 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3946 reply_unixerror(req, ERRDOS, ERRbadfid);
3949 pos = fsp->fh->position_information;
3950 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3951 get_file_infos(fileid, &delete_pending, &write_time_ts);
3955 NTSTATUS status = NT_STATUS_OK;
3958 if (total_params < 7) {
3959 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3963 info_level = SVAL(params,0);
3965 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3967 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3968 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3972 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3974 STR_TERMINATE, &status);
3975 if (!NT_STATUS_IS_OK(status)) {
3976 reply_nterror(req, status);
3980 status = resolve_dfspath(ctx,
3982 req->flags2 & FLAGS2_DFS_PATHNAMES,
3985 if (!NT_STATUS_IS_OK(status)) {
3986 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3987 reply_botherror(req,
3988 NT_STATUS_PATH_NOT_COVERED,
3989 ERRSRV, ERRbadpath);
3991 reply_nterror(req, status);
3995 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
3996 if (!NT_STATUS_IS_OK(status)) {
3997 reply_nterror(req, status);
4000 sbuf = smb_fname->st;
4002 status = get_full_smb_filename(ctx, smb_fname, &fname);
4003 TALLOC_FREE(smb_fname);
4004 if (!NT_STATUS_IS_OK(status)) {
4005 reply_nterror(req, status);
4009 status = check_name(conn, fname);
4010 if (!NT_STATUS_IS_OK(status)) {
4011 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
4012 reply_nterror(req, status);
4016 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4017 && is_ntfs_stream_name(fname)) {
4019 SMB_STRUCT_STAT bsbuf;
4021 status = split_ntfs_stream_name(talloc_tos(), fname,
4023 if (!NT_STATUS_IS_OK(status)) {
4024 DEBUG(10, ("create_file_unixpath: "
4025 "split_ntfs_stream_name failed: %s\n",
4026 nt_errstr(status)));
4027 reply_nterror(req, status);
4031 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4033 if (INFO_LEVEL_IS_UNIX(info_level)) {
4034 /* Always do lstat for UNIX calls. */
4035 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4036 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4037 reply_unixerror(req,ERRDOS,ERRbadpath);
4041 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4042 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4043 reply_unixerror(req,ERRDOS,ERRbadpath);
4048 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4049 get_file_infos(fileid, &delete_pending, NULL);
4050 if (delete_pending) {
4051 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4056 if (INFO_LEVEL_IS_UNIX(info_level)) {
4057 /* Always do lstat for UNIX calls. */
4058 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4059 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4060 reply_unixerror(req, ERRDOS, ERRbadpath);
4064 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4065 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4068 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4069 reply_unixerror(req, ERRDOS, ERRbadpath);
4074 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4075 get_file_infos(fileid, &delete_pending, &write_time_ts);
4076 if (delete_pending) {
4077 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4082 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4083 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4087 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4088 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4090 p = strrchr_m(fname,'/');
4097 mode = dos_mode_msdfs(conn,fname,&sbuf);
4099 mode = dos_mode(conn,fname,&sbuf);
4102 mode = FILE_ATTRIBUTE_NORMAL;
4104 nlink = sbuf.st_ex_nlink;
4106 if (nlink && (mode&aDIR)) {
4110 if ((nlink > 0) && delete_pending) {
4114 fullpathname = fname;
4116 file_size = get_file_size_stat(&sbuf);
4118 /* Pull out any data sent here before we realloc. */
4119 switch (info_level) {
4120 case SMB_INFO_QUERY_EAS_FROM_LIST:
4122 /* Pull any EA list from the data portion. */
4125 if (total_data < 4) {
4127 req, NT_STATUS_INVALID_PARAMETER);
4130 ea_size = IVAL(pdata,0);
4132 if (total_data > 0 && ea_size != total_data) {
4133 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4134 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4136 req, NT_STATUS_INVALID_PARAMETER);
4140 if (!lp_ea_support(SNUM(conn))) {
4141 reply_doserror(req, ERRDOS,
4142 ERReasnotsupported);
4146 /* Pull out the list of names. */
4147 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4150 req, NT_STATUS_INVALID_PARAMETER);
4156 case SMB_QUERY_POSIX_LOCK:
4158 if (fsp == NULL || fsp->fh->fd == -1) {
4159 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4163 if (total_data != POSIX_LOCK_DATA_SIZE) {
4165 req, NT_STATUS_INVALID_PARAMETER);
4169 /* Copy the lock range data. */
4170 lock_data = (char *)TALLOC_MEMDUP(
4171 ctx, pdata, total_data);
4173 reply_nterror(req, NT_STATUS_NO_MEMORY);
4181 *pparams = (char *)SMB_REALLOC(*pparams,2);
4182 if (*pparams == NULL) {
4183 reply_nterror(req, NT_STATUS_NO_MEMORY);
4188 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4189 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4190 if (*ppdata == NULL ) {
4191 reply_nterror(req, NT_STATUS_NO_MEMORY);
4196 dend = dstart + data_size - 1;
4198 create_time_ts = sbuf.st_ex_btime;
4199 mtime_ts = sbuf.st_ex_mtime;
4200 atime_ts = sbuf.st_ex_atime;
4202 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4205 /* Do we have this path open ? */
4207 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4208 fsp1 = file_find_di_first(fileid);
4209 if (fsp1 && fsp1->initial_allocation_size) {
4210 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4214 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4215 mtime_ts = write_time_ts;
4218 if (lp_dos_filetime_resolution(SNUM(conn))) {
4219 dos_filetime_timespec(&create_time_ts);
4220 dos_filetime_timespec(&mtime_ts);
4221 dos_filetime_timespec(&atime_ts);
4224 create_time = convert_timespec_to_time_t(create_time_ts);
4225 mtime = convert_timespec_to_time_t(mtime_ts);
4226 atime = convert_timespec_to_time_t(atime_ts);
4228 /* NT expects the name to be in an exact form of the *full*
4229 filename. See the trans2 torture test */
4230 if (ISDOT(base_name)) {
4231 dos_fname = talloc_strdup(ctx, "\\");
4233 reply_nterror(req, NT_STATUS_NO_MEMORY);
4237 dos_fname = talloc_asprintf(ctx,
4241 reply_nterror(req, NT_STATUS_NO_MEMORY);
4244 string_replace(dos_fname, '/', '\\');
4247 switch (info_level) {
4248 case SMB_INFO_STANDARD:
4249 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4251 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4252 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4253 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4254 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4255 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4256 SSVAL(pdata,l1_attrFile,mode);
4259 case SMB_INFO_QUERY_EA_SIZE:
4261 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4262 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4264 srv_put_dos_date2(pdata,0,create_time);
4265 srv_put_dos_date2(pdata,4,atime);
4266 srv_put_dos_date2(pdata,8,mtime); /* write time */
4267 SIVAL(pdata,12,(uint32)file_size);
4268 SIVAL(pdata,16,(uint32)allocation_size);
4269 SSVAL(pdata,20,mode);
4270 SIVAL(pdata,22,ea_size);
4274 case SMB_INFO_IS_NAME_VALID:
4275 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4276 if (tran_call == TRANSACT2_QFILEINFO) {
4277 /* os/2 needs this ? really ?*/
4278 reply_doserror(req, ERRDOS, ERRbadfunc);
4285 case SMB_INFO_QUERY_EAS_FROM_LIST:
4287 size_t total_ea_len = 0;
4288 struct ea_list *ea_file_list = NULL;
4290 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4292 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4293 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4295 if (!ea_list || (total_ea_len > data_size)) {
4297 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4301 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4305 case SMB_INFO_QUERY_ALL_EAS:
4307 /* We have data_size bytes to put EA's into. */
4308 size_t total_ea_len = 0;
4310 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4312 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4313 if (!ea_list || (total_ea_len > data_size)) {
4315 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4319 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4323 case SMB_FILE_BASIC_INFORMATION:
4324 case SMB_QUERY_FILE_BASIC_INFO:
4326 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4327 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4328 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4330 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4334 put_long_date_timespec(pdata,create_time_ts);
4335 put_long_date_timespec(pdata+8,atime_ts);
4336 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4337 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4338 SIVAL(pdata,32,mode);
4340 DEBUG(5,("SMB_QFBI - "));
4341 DEBUG(5,("create: %s ", ctime(&create_time)));
4342 DEBUG(5,("access: %s ", ctime(&atime)));
4343 DEBUG(5,("write: %s ", ctime(&mtime)));
4344 DEBUG(5,("change: %s ", ctime(&mtime)));
4345 DEBUG(5,("mode: %x\n", mode));
4348 case SMB_FILE_STANDARD_INFORMATION:
4349 case SMB_QUERY_FILE_STANDARD_INFO:
4351 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4353 SOFF_T(pdata,0,allocation_size);
4354 SOFF_T(pdata,8,file_size);
4355 SIVAL(pdata,16,nlink);
4356 SCVAL(pdata,20,delete_pending?1:0);
4357 SCVAL(pdata,21,(mode&aDIR)?1:0);
4358 SSVAL(pdata,22,0); /* Padding. */
4361 case SMB_FILE_EA_INFORMATION:
4362 case SMB_QUERY_FILE_EA_INFO:
4364 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4365 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4367 SIVAL(pdata,0,ea_size);
4371 /* Get the 8.3 name - used if NT SMB was negotiated. */
4372 case SMB_QUERY_FILE_ALT_NAME_INFO:
4373 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4375 char mangled_name[13];
4376 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4377 if (!name_to_8_3(base_name,mangled_name,
4378 True,conn->params)) {
4381 NT_STATUS_NO_MEMORY);
4383 len = srvstr_push(dstart, req->flags2,
4384 pdata+4, mangled_name,
4385 PTR_DIFF(dend, pdata+4),
4387 data_size = 4 + len;
4392 case SMB_QUERY_FILE_NAME_INFO:
4394 this must be *exactly* right for ACLs on mapped drives to work
4396 len = srvstr_push(dstart, req->flags2,
4398 PTR_DIFF(dend, pdata+4),
4400 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4401 data_size = 4 + len;
4405 case SMB_FILE_ALLOCATION_INFORMATION:
4406 case SMB_QUERY_FILE_ALLOCATION_INFO:
4407 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4409 SOFF_T(pdata,0,allocation_size);
4412 case SMB_FILE_END_OF_FILE_INFORMATION:
4413 case SMB_QUERY_FILE_END_OF_FILEINFO:
4414 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4416 SOFF_T(pdata,0,file_size);
4419 case SMB_QUERY_FILE_ALL_INFO:
4420 case SMB_FILE_ALL_INFORMATION:
4422 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4423 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4424 put_long_date_timespec(pdata,create_time_ts);
4425 put_long_date_timespec(pdata+8,atime_ts);
4426 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4427 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4428 SIVAL(pdata,32,mode);
4429 SIVAL(pdata,36,0); /* padding. */
4431 SOFF_T(pdata,0,allocation_size);
4432 SOFF_T(pdata,8,file_size);
4433 SIVAL(pdata,16,nlink);
4434 SCVAL(pdata,20,delete_pending);
4435 SCVAL(pdata,21,(mode&aDIR)?1:0);
4438 SIVAL(pdata,0,ea_size);
4439 pdata += 4; /* EA info */
4440 len = srvstr_push(dstart, req->flags2,
4442 PTR_DIFF(dend, pdata+4),
4446 data_size = PTR_DIFF(pdata,(*ppdata));
4449 case SMB_FILE_INTERNAL_INFORMATION:
4450 /* This should be an index number - looks like
4453 I think this causes us to fail the IFSKIT
4454 BasicFileInformationTest. -tpot */
4456 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4457 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4458 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4462 case SMB_FILE_ACCESS_INFORMATION:
4463 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4465 SIVAL(pdata,0,fsp->access_mask);
4467 /* GENERIC_EXECUTE mapping from Windows */
4468 SIVAL(pdata,0,0x12019F);
4473 case SMB_FILE_NAME_INFORMATION:
4474 /* Pathname with leading '\'. */
4477 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4478 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4479 SIVAL(pdata,0,byte_len);
4480 data_size = 4 + byte_len;
4484 case SMB_FILE_DISPOSITION_INFORMATION:
4485 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4487 SCVAL(pdata,0,delete_pending);
4490 case SMB_FILE_POSITION_INFORMATION:
4491 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4493 SOFF_T(pdata,0,pos);
4496 case SMB_FILE_MODE_INFORMATION:
4497 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4498 SIVAL(pdata,0,mode);
4502 case SMB_FILE_ALIGNMENT_INFORMATION:
4503 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4504 SIVAL(pdata,0,0); /* No alignment needed. */
4509 * NT4 server just returns "invalid query" to this - if we try
4510 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4513 /* The first statement above is false - verified using Thursby
4514 * client against NT4 -- gcolley.
4516 case SMB_QUERY_FILE_STREAM_INFO:
4517 case SMB_FILE_STREAM_INFORMATION: {
4518 unsigned int num_streams;
4519 struct stream_struct *streams;
4522 DEBUG(10,("call_trans2qfilepathinfo: "
4523 "SMB_FILE_STREAM_INFORMATION\n"));
4525 status = SMB_VFS_STREAMINFO(
4526 conn, fsp, fname, talloc_tos(),
4527 &num_streams, &streams);
4529 if (!NT_STATUS_IS_OK(status)) {
4530 DEBUG(10, ("could not get stream info: %s\n",
4531 nt_errstr(status)));
4532 reply_nterror(req, status);
4536 status = marshall_stream_info(num_streams, streams,
4537 pdata, max_data_bytes,
4540 if (!NT_STATUS_IS_OK(status)) {
4541 DEBUG(10, ("marshall_stream_info failed: %s\n",
4542 nt_errstr(status)));
4543 reply_nterror(req, status);
4547 TALLOC_FREE(streams);
4551 case SMB_QUERY_COMPRESSION_INFO:
4552 case SMB_FILE_COMPRESSION_INFORMATION:
4553 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4554 SOFF_T(pdata,0,file_size);
4555 SIVAL(pdata,8,0); /* ??? */
4556 SIVAL(pdata,12,0); /* ??? */
4560 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4561 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4562 put_long_date_timespec(pdata,create_time_ts);
4563 put_long_date_timespec(pdata+8,atime_ts);
4564 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4565 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4566 SOFF_T(pdata,32,allocation_size);
4567 SOFF_T(pdata,40,file_size);
4568 SIVAL(pdata,48,mode);
4569 SIVAL(pdata,52,0); /* ??? */
4573 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4574 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4575 SIVAL(pdata,0,mode);
4581 * CIFS UNIX Extensions.
4584 case SMB_QUERY_FILE_UNIX_BASIC:
4586 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4587 data_size = PTR_DIFF(pdata,(*ppdata));
4591 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4593 for (i=0; i<100; i++)
4594 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4600 case SMB_QUERY_FILE_UNIX_INFO2:
4602 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4603 data_size = PTR_DIFF(pdata,(*ppdata));
4607 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4609 for (i=0; i<100; i++)
4610 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4616 case SMB_QUERY_FILE_UNIX_LINK:
4618 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4621 reply_nterror(req, NT_STATUS_NO_MEMORY);
4625 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4627 if(!S_ISLNK(sbuf.st_ex_mode)) {
4628 reply_unixerror(req, ERRSRV,
4633 reply_unixerror(req, ERRDOS, ERRbadlink);
4636 len = SMB_VFS_READLINK(conn,fullpathname,
4639 reply_unixerror(req, ERRDOS,
4644 len = srvstr_push(dstart, req->flags2,
4646 PTR_DIFF(dend, pdata),
4649 data_size = PTR_DIFF(pdata,(*ppdata));
4654 #if defined(HAVE_POSIX_ACLS)
4655 case SMB_QUERY_POSIX_ACL:
4657 SMB_ACL_T file_acl = NULL;
4658 SMB_ACL_T def_acl = NULL;
4659 uint16 num_file_acls = 0;
4660 uint16 num_def_acls = 0;
4662 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4663 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4665 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4668 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4669 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4673 NT_STATUS_NOT_IMPLEMENTED);
4677 if (S_ISDIR(sbuf.st_ex_mode)) {
4678 if (fsp && fsp->is_directory) {
4679 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4681 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4683 def_acl = free_empty_sys_acl(conn, def_acl);
4686 num_file_acls = count_acl_entries(conn, file_acl);
4687 num_def_acls = count_acl_entries(conn, def_acl);
4689 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4690 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4692 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4693 SMB_POSIX_ACL_HEADER_SIZE) ));
4695 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4698 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4702 NT_STATUS_BUFFER_TOO_SMALL);
4706 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4707 SSVAL(pdata,2,num_file_acls);
4708 SSVAL(pdata,4,num_def_acls);
4709 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4711 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4714 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4717 req, NT_STATUS_INTERNAL_ERROR);
4720 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4722 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4725 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4729 NT_STATUS_INTERNAL_ERROR);
4734 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4737 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4739 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4745 case SMB_QUERY_POSIX_LOCK:
4747 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4751 enum brl_type lock_type;
4753 if (total_data != POSIX_LOCK_DATA_SIZE) {
4755 req, NT_STATUS_INVALID_PARAMETER);
4759 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4760 case POSIX_LOCK_TYPE_READ:
4761 lock_type = READ_LOCK;
4763 case POSIX_LOCK_TYPE_WRITE:
4764 lock_type = WRITE_LOCK;
4766 case POSIX_LOCK_TYPE_UNLOCK:
4768 /* There's no point in asking for an unlock... */
4771 NT_STATUS_INVALID_PARAMETER);
4775 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4776 #if defined(HAVE_LONGLONG)
4777 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4778 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4779 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4780 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4781 #else /* HAVE_LONGLONG */
4782 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4783 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4784 #endif /* HAVE_LONGLONG */
4786 status = query_lock(fsp,
4793 if (ERROR_WAS_LOCK_DENIED(status)) {
4794 /* Here we need to report who has it locked... */
4795 data_size = POSIX_LOCK_DATA_SIZE;
4797 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4798 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4799 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4800 #if defined(HAVE_LONGLONG)
4801 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4802 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4803 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4804 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4805 #else /* HAVE_LONGLONG */
4806 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4807 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4808 #endif /* HAVE_LONGLONG */
4810 } else if (NT_STATUS_IS_OK(status)) {
4811 /* For success we just return a copy of what we sent
4812 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4813 data_size = POSIX_LOCK_DATA_SIZE;
4814 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4815 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4817 reply_nterror(req, status);
4824 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4828 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4834 /****************************************************************************
4835 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4837 ****************************************************************************/
4839 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4840 connection_struct *conn,
4841 const char *oldname_in,
4842 const char *newname_in)
4844 struct smb_filename *smb_fname = NULL;
4845 struct smb_filename *smb_fname_new = NULL;
4846 char *oldname = NULL;
4847 char *newname = NULL;
4848 NTSTATUS status = NT_STATUS_OK;
4850 status = unix_convert(ctx, conn, oldname_in, &smb_fname, 0);
4851 if (!NT_STATUS_IS_OK(status)) {
4855 status = get_full_smb_filename(ctx, smb_fname, &oldname);
4856 if (!NT_STATUS_IS_OK(status)) {
4860 status = check_name(conn, oldname);
4861 if (!NT_STATUS_IS_OK(status)) {
4865 /* source must already exist. */
4866 if (!VALID_STAT(smb_fname->st)) {
4867 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4871 status = unix_convert(ctx, conn, newname_in, &smb_fname_new, 0);
4872 if (!NT_STATUS_IS_OK(status)) {
4876 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
4877 if (!NT_STATUS_IS_OK(status)) {
4881 status = check_name(conn, newname);
4882 if (!NT_STATUS_IS_OK(status)) {
4886 /* Disallow if newname already exists. */
4887 if (VALID_STAT(smb_fname_new->st)) {
4888 status = NT_STATUS_OBJECT_NAME_COLLISION;
4892 /* No links from a directory. */
4893 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
4894 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4898 /* Ensure this is within the share. */
4899 status = check_reduced_name(conn, oldname);
4900 if (!NT_STATUS_IS_OK(status)) {
4904 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4906 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4907 status = map_nt_error_from_unix(errno);
4908 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4909 nt_errstr(status), newname, oldname));
4912 TALLOC_FREE(smb_fname);
4913 TALLOC_FREE(smb_fname_new);
4917 /****************************************************************************
4918 Deal with setting the time from any of the setfilepathinfo functions.
4919 ****************************************************************************/
4921 NTSTATUS smb_set_file_time(connection_struct *conn,
4924 const SMB_STRUCT_STAT *psbuf,
4925 struct smb_file_time *ft,
4926 bool setting_write_time)
4929 FILE_NOTIFY_CHANGE_LAST_ACCESS
4930 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4932 if (!VALID_STAT(*psbuf)) {
4933 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4936 /* get some defaults (no modifications) if any info is zero or -1. */
4937 if (null_timespec(ft->atime)) {
4938 ft->atime= psbuf->st_ex_atime;
4939 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4942 if (null_timespec(ft->mtime)) {
4943 ft->mtime = psbuf->st_ex_mtime;
4944 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4947 if (!setting_write_time) {
4948 /* ft->mtime comes from change time, not write time. */
4949 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4952 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4953 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4954 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4955 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4956 if (!null_timespec(ft->create_time)) {
4957 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4958 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4962 * Try and set the times of this file if
4963 * they are different from the current values.
4967 struct timespec mts = psbuf->st_ex_mtime;
4968 struct timespec ats = psbuf->st_ex_atime;
4969 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4970 (timespec_compare(&ft->mtime, &mts) == 0)) {
4971 return NT_STATUS_OK;
4975 if (setting_write_time) {
4977 * This was a setfileinfo on an open file.
4978 * NT does this a lot. We also need to
4979 * set the time here, as it can be read by
4980 * FindFirst/FindNext and with the patch for bug #2045
4981 * in smbd/fileio.c it ensures that this timestamp is
4982 * kept sticky even after a write. We save the request
4983 * away and will set it on file close and after a write. JRA.
4986 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4987 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4990 if (fsp->base_fsp) {
4991 set_sticky_write_time_fsp(fsp->base_fsp,
4994 set_sticky_write_time_fsp(fsp, ft->mtime);
4997 set_sticky_write_time_path(conn, fname,
4998 vfs_file_id_from_sbuf(conn, psbuf),
5003 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5005 if (fsp && fsp->base_fsp) {
5006 fname = fsp->base_fsp->fsp_name;
5009 if(file_ntimes(conn, fname, ft)!=0) {
5010 return map_nt_error_from_unix(errno);
5012 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
5014 return NT_STATUS_OK;
5017 /****************************************************************************
5018 Deal with setting the dosmode from any of the setfilepathinfo functions.
5019 ****************************************************************************/
5021 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5024 SMB_STRUCT_STAT *psbuf,
5027 if (!VALID_STAT(*psbuf)) {
5028 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5032 if (fsp->base_fsp) {
5033 fname = fsp->base_fsp->fsp_name;
5035 fname = fsp->fsp_name;
5040 if (S_ISDIR(psbuf->st_ex_mode)) {
5047 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5049 /* check the mode isn't different, before changing it */
5050 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5052 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5053 fname, (unsigned int)dosmode ));
5055 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5056 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5057 fname, strerror(errno)));
5058 return map_nt_error_from_unix(errno);
5061 return NT_STATUS_OK;
5064 /****************************************************************************
5065 Deal with setting the size from any of the setfilepathinfo functions.
5066 ****************************************************************************/
5068 static NTSTATUS smb_set_file_size(connection_struct *conn,
5069 struct smb_request *req,
5072 SMB_STRUCT_STAT *psbuf,
5075 struct smb_filename *smb_fname = NULL;
5076 NTSTATUS status = NT_STATUS_OK;
5077 files_struct *new_fsp = NULL;
5079 if (!VALID_STAT(*psbuf)) {
5080 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5083 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5085 if (size == get_file_size_stat(psbuf)) {
5086 return NT_STATUS_OK;
5089 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5090 fname, (double)size ));
5092 if (fsp && fsp->fh->fd != -1) {
5093 /* Handle based call. */
5094 if (vfs_set_filelen(fsp, size) == -1) {
5095 return map_nt_error_from_unix(errno);
5097 trigger_write_time_update_immediate(fsp);
5098 return NT_STATUS_OK;
5101 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5103 if (!NT_STATUS_IS_OK(status)) {
5107 status = SMB_VFS_CREATE_FILE(
5110 0, /* root_dir_fid */
5111 smb_fname, /* fname */
5112 FILE_WRITE_ATTRIBUTES, /* access_mask */
5113 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5115 FILE_OPEN, /* create_disposition*/
5116 0, /* create_options */
5117 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5118 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5119 0, /* allocation_size */
5122 &new_fsp, /* result */
5125 *psbuf = smb_fname->st;
5126 TALLOC_FREE(smb_fname);
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 struct smb_filename *smb_fname = NULL;
5843 uint64_t allocation_size = 0;
5844 NTSTATUS status = NT_STATUS_OK;
5845 files_struct *new_fsp = NULL;
5847 if (!VALID_STAT(*psbuf)) {
5848 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5851 if (total_data < 8) {
5852 return NT_STATUS_INVALID_PARAMETER;
5855 allocation_size = (uint64_t)IVAL(pdata,0);
5856 #ifdef LARGE_SMB_OFF_T
5857 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5858 #else /* LARGE_SMB_OFF_T */
5859 if (IVAL(pdata,4) != 0) {
5860 /* more than 32 bits? */
5861 return NT_STATUS_INVALID_PARAMETER;
5863 #endif /* LARGE_SMB_OFF_T */
5865 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5866 fname, (double)allocation_size ));
5868 if (allocation_size) {
5869 allocation_size = smb_roundup(conn, allocation_size);
5872 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5873 fname, (double)allocation_size ));
5875 if (fsp && fsp->fh->fd != -1) {
5876 /* Open file handle. */
5877 /* Only change if needed. */
5878 if (allocation_size != get_file_size_stat(psbuf)) {
5879 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5880 return map_nt_error_from_unix(errno);
5883 /* But always update the time. */
5885 * This is equivalent to a write. Ensure it's seen immediately
5886 * if there are no pending writes.
5888 trigger_write_time_update_immediate(fsp);
5889 return NT_STATUS_OK;
5892 /* Pathname or stat or directory file. */
5894 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5896 if (!NT_STATUS_IS_OK(status)) {
5900 status = SMB_VFS_CREATE_FILE(
5903 0, /* root_dir_fid */
5904 smb_fname, /* fname */
5905 FILE_WRITE_DATA, /* access_mask */
5906 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5908 FILE_OPEN, /* create_disposition*/
5909 0, /* create_options */
5910 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5911 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5912 0, /* allocation_size */
5915 &new_fsp, /* result */
5918 *psbuf = smb_fname->st;
5919 TALLOC_FREE(smb_fname);
5921 if (!NT_STATUS_IS_OK(status)) {
5922 /* NB. We check for open_was_deferred in the caller. */
5926 /* Only change if needed. */
5927 if (allocation_size != get_file_size_stat(psbuf)) {
5928 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5929 status = map_nt_error_from_unix(errno);
5930 close_file(req, new_fsp, NORMAL_CLOSE);
5935 /* Changing the allocation size should set the last mod time. */
5937 * This is equivalent to a write. Ensure it's seen immediately
5938 * if there are no pending writes.
5940 trigger_write_time_update_immediate(new_fsp);
5942 close_file(req, new_fsp, NORMAL_CLOSE);
5943 return NT_STATUS_OK;
5946 /****************************************************************************
5947 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5948 ****************************************************************************/
5950 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5951 struct smb_request *req,
5956 SMB_STRUCT_STAT *psbuf)
5960 if (total_data < 8) {
5961 return NT_STATUS_INVALID_PARAMETER;
5964 size = IVAL(pdata,0);
5965 #ifdef LARGE_SMB_OFF_T
5966 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5967 #else /* LARGE_SMB_OFF_T */
5968 if (IVAL(pdata,4) != 0) {
5969 /* more than 32 bits? */
5970 return NT_STATUS_INVALID_PARAMETER;
5972 #endif /* LARGE_SMB_OFF_T */
5973 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5974 "file %s to %.0f\n", fname, (double)size ));
5976 return smb_set_file_size(conn, req,
5983 /****************************************************************************
5984 Allow a UNIX info mknod.
5985 ****************************************************************************/
5987 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5991 SMB_STRUCT_STAT *psbuf)
5993 uint32 file_type = IVAL(pdata,56);
5994 #if defined(HAVE_MAKEDEV)
5995 uint32 dev_major = IVAL(pdata,60);
5996 uint32 dev_minor = IVAL(pdata,68);
5998 SMB_DEV_T dev = (SMB_DEV_T)0;
5999 uint32 raw_unixmode = IVAL(pdata,84);
6003 if (total_data < 100) {
6004 return NT_STATUS_INVALID_PARAMETER;
6007 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
6008 if (!NT_STATUS_IS_OK(status)) {
6012 #if defined(HAVE_MAKEDEV)
6013 dev = makedev(dev_major, dev_minor);
6016 switch (file_type) {
6017 #if defined(S_IFIFO)
6018 case UNIX_TYPE_FIFO:
6019 unixmode |= S_IFIFO;
6022 #if defined(S_IFSOCK)
6023 case UNIX_TYPE_SOCKET:
6024 unixmode |= S_IFSOCK;
6027 #if defined(S_IFCHR)
6028 case UNIX_TYPE_CHARDEV:
6029 unixmode |= S_IFCHR;
6032 #if defined(S_IFBLK)
6033 case UNIX_TYPE_BLKDEV:
6034 unixmode |= S_IFBLK;
6038 return NT_STATUS_INVALID_PARAMETER;
6041 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6042 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6044 /* Ok - do the mknod. */
6045 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6046 return map_nt_error_from_unix(errno);
6049 /* If any of the other "set" calls fail we
6050 * don't want to end up with a half-constructed mknod.
6053 if (lp_inherit_perms(SNUM(conn))) {
6055 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6056 return NT_STATUS_NO_MEMORY;
6058 inherit_access_posix_acl(conn, parent, fname, unixmode);
6059 TALLOC_FREE(parent);
6062 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6063 status = map_nt_error_from_unix(errno);
6064 SMB_VFS_UNLINK(conn,fname);
6067 return NT_STATUS_OK;
6070 /****************************************************************************
6071 Deal with SMB_SET_FILE_UNIX_BASIC.
6072 ****************************************************************************/
6074 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6075 struct smb_request *req,
6080 SMB_STRUCT_STAT *psbuf)
6082 struct smb_file_time ft;
6083 uint32 raw_unixmode;
6086 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6087 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6088 NTSTATUS status = NT_STATUS_OK;
6089 bool delete_on_fail = False;
6090 enum perm_type ptype;
6094 if (total_data < 100) {
6095 return NT_STATUS_INVALID_PARAMETER;
6098 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6099 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6100 size=IVAL(pdata,0); /* first 8 Bytes are size */
6101 #ifdef LARGE_SMB_OFF_T
6102 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6103 #else /* LARGE_SMB_OFF_T */
6104 if (IVAL(pdata,4) != 0) {
6105 /* more than 32 bits? */
6106 return NT_STATUS_INVALID_PARAMETER;
6108 #endif /* LARGE_SMB_OFF_T */
6111 ft.atime = interpret_long_date(pdata+24); /* access_time */
6112 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6113 set_owner = (uid_t)IVAL(pdata,40);
6114 set_grp = (gid_t)IVAL(pdata,48);
6115 raw_unixmode = IVAL(pdata,84);
6117 if (VALID_STAT(*psbuf)) {
6118 if (S_ISDIR(psbuf->st_ex_mode)) {
6119 ptype = PERM_EXISTING_DIR;
6121 ptype = PERM_EXISTING_FILE;
6124 ptype = PERM_NEW_FILE;
6127 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6128 if (!NT_STATUS_IS_OK(status)) {
6132 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6133 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6134 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6136 if (!VALID_STAT(*psbuf)) {
6138 * The only valid use of this is to create character and block
6139 * devices, and named pipes. This is deprecated (IMHO) and
6140 * a new info level should be used for mknod. JRA.
6143 status = smb_unix_mknod(conn,
6148 if (!NT_STATUS_IS_OK(status)) {
6152 /* Ensure we don't try and change anything else. */
6153 raw_unixmode = SMB_MODE_NO_CHANGE;
6154 size = get_file_size_stat(psbuf);
6155 ft.atime = psbuf->st_ex_atime;
6156 ft.mtime = psbuf->st_ex_mtime;
6158 * We continue here as we might want to change the
6161 delete_on_fail = True;
6165 /* Horrible backwards compatibility hack as an old server bug
6166 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6170 size = get_file_size_stat(psbuf);
6175 * Deal with the UNIX specific mode set.
6178 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6179 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6180 (unsigned int)unixmode, fname ));
6181 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6182 return map_nt_error_from_unix(errno);
6187 * Deal with the UNIX specific uid set.
6190 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_ex_uid != set_owner)) {
6193 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6194 (unsigned int)set_owner, fname ));
6196 if (S_ISLNK(psbuf->st_ex_mode)) {
6197 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6199 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6203 status = map_nt_error_from_unix(errno);
6204 if (delete_on_fail) {
6205 SMB_VFS_UNLINK(conn,fname);
6212 * Deal with the UNIX specific gid set.
6215 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_ex_gid != set_grp)) {
6216 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6217 (unsigned int)set_owner, fname ));
6218 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6219 status = map_nt_error_from_unix(errno);
6220 if (delete_on_fail) {
6221 SMB_VFS_UNLINK(conn,fname);
6227 /* Deal with any size changes. */
6229 status = smb_set_file_size(conn, req,
6234 if (!NT_STATUS_IS_OK(status)) {
6238 /* Deal with any time changes. */
6240 return smb_set_file_time(conn,
6248 /****************************************************************************
6249 Deal with SMB_SET_FILE_UNIX_INFO2.
6250 ****************************************************************************/
6252 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6253 struct smb_request *req,
6258 SMB_STRUCT_STAT *psbuf)
6264 if (total_data < 116) {
6265 return NT_STATUS_INVALID_PARAMETER;
6268 /* Start by setting all the fields that are common between UNIX_BASIC
6271 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6273 if (!NT_STATUS_IS_OK(status)) {
6277 smb_fflags = IVAL(pdata, 108);
6278 smb_fmask = IVAL(pdata, 112);
6280 /* NB: We should only attempt to alter the file flags if the client
6281 * sends a non-zero mask.
6283 if (smb_fmask != 0) {
6284 int stat_fflags = 0;
6286 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6288 /* Client asked to alter a flag we don't understand. */
6289 return NT_STATUS_INVALID_PARAMETER;
6292 if (fsp && fsp->fh->fd != -1) {
6293 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6294 return NT_STATUS_NOT_SUPPORTED;
6296 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6297 return map_nt_error_from_unix(errno);
6302 /* XXX: need to add support for changing the create_time here. You
6303 * can do this for paths on Darwin with setattrlist(2). The right way
6304 * to hook this up is probably by extending the VFS utimes interface.
6307 return NT_STATUS_OK;
6310 /****************************************************************************
6311 Create a directory with POSIX semantics.
6312 ****************************************************************************/
6314 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6315 struct smb_request *req,
6319 SMB_STRUCT_STAT *psbuf,
6320 int *pdata_return_size)
6322 struct smb_filename *smb_fname;
6323 NTSTATUS status = NT_STATUS_OK;
6324 uint32 raw_unixmode = 0;
6325 uint32 mod_unixmode = 0;
6326 mode_t unixmode = (mode_t)0;
6327 files_struct *fsp = NULL;
6328 uint16 info_level_return = 0;
6330 char *pdata = *ppdata;
6332 if (total_data < 18) {
6333 return NT_STATUS_INVALID_PARAMETER;
6336 raw_unixmode = IVAL(pdata,8);
6337 /* Next 4 bytes are not yet defined. */
6339 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6340 if (!NT_STATUS_IS_OK(status)) {
6344 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6346 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6347 fname, (unsigned int)unixmode ));
6349 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6351 if (!NT_STATUS_IS_OK(status)) {
6355 status = SMB_VFS_CREATE_FILE(
6358 0, /* root_dir_fid */
6359 smb_fname, /* fname */
6360 FILE_READ_ATTRIBUTES, /* access_mask */
6361 FILE_SHARE_NONE, /* share_access */
6362 FILE_CREATE, /* create_disposition*/
6363 FILE_DIRECTORY_FILE, /* create_options */
6364 mod_unixmode, /* file_attributes */
6365 0, /* oplock_request */
6366 0, /* allocation_size */
6372 *psbuf = smb_fname->st;
6373 TALLOC_FREE(smb_fname);
6375 if (NT_STATUS_IS_OK(status)) {
6376 close_file(req, fsp, NORMAL_CLOSE);
6379 info_level_return = SVAL(pdata,16);
6381 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6382 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6383 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6384 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6386 *pdata_return_size = 12;
6389 /* Realloc the data size */
6390 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6391 if (*ppdata == NULL) {
6392 *pdata_return_size = 0;
6393 return NT_STATUS_NO_MEMORY;
6397 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6398 SSVAL(pdata,2,0); /* No fnum. */
6399 SIVAL(pdata,4,info); /* Was directory created. */
6401 switch (info_level_return) {
6402 case SMB_QUERY_FILE_UNIX_BASIC:
6403 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6404 SSVAL(pdata,10,0); /* Padding. */
6405 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6407 case SMB_QUERY_FILE_UNIX_INFO2:
6408 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6409 SSVAL(pdata,10,0); /* Padding. */
6410 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6413 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6414 SSVAL(pdata,10,0); /* Padding. */
6421 /****************************************************************************
6422 Open/Create a file with POSIX semantics.
6423 ****************************************************************************/
6425 static NTSTATUS smb_posix_open(connection_struct *conn,
6426 struct smb_request *req,
6430 SMB_STRUCT_STAT *psbuf,
6431 int *pdata_return_size)
6433 struct smb_filename *smb_fname = NULL;
6434 bool extended_oplock_granted = False;
6435 char *pdata = *ppdata;
6437 uint32 wire_open_mode = 0;
6438 uint32 raw_unixmode = 0;
6439 uint32 mod_unixmode = 0;
6440 uint32 create_disp = 0;
6441 uint32 access_mask = 0;
6442 uint32 create_options = 0;
6443 NTSTATUS status = NT_STATUS_OK;
6444 mode_t unixmode = (mode_t)0;
6445 files_struct *fsp = NULL;
6446 int oplock_request = 0;
6448 uint16 info_level_return = 0;
6450 if (total_data < 18) {
6451 return NT_STATUS_INVALID_PARAMETER;
6454 flags = IVAL(pdata,0);
6455 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6456 if (oplock_request) {
6457 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6460 wire_open_mode = IVAL(pdata,4);
6462 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6463 return smb_posix_mkdir(conn, req,
6471 switch (wire_open_mode & SMB_ACCMODE) {
6473 access_mask = FILE_READ_DATA;
6476 access_mask = FILE_WRITE_DATA;
6479 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6482 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6483 (unsigned int)wire_open_mode ));
6484 return NT_STATUS_INVALID_PARAMETER;
6487 wire_open_mode &= ~SMB_ACCMODE;
6489 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6490 create_disp = FILE_CREATE;
6491 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6492 create_disp = FILE_OVERWRITE_IF;
6493 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6494 create_disp = FILE_OPEN_IF;
6495 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6496 create_disp = FILE_OPEN;
6498 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6499 (unsigned int)wire_open_mode ));
6500 return NT_STATUS_INVALID_PARAMETER;
6503 raw_unixmode = IVAL(pdata,8);
6504 /* Next 4 bytes are not yet defined. */
6506 status = unix_perms_from_wire(conn,
6509 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6512 if (!NT_STATUS_IS_OK(status)) {
6516 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6518 if (wire_open_mode & SMB_O_SYNC) {
6519 create_options |= FILE_WRITE_THROUGH;
6521 if (wire_open_mode & SMB_O_APPEND) {
6522 access_mask |= FILE_APPEND_DATA;
6524 if (wire_open_mode & SMB_O_DIRECT) {
6525 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6528 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6530 (unsigned int)wire_open_mode,
6531 (unsigned int)unixmode ));
6533 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6535 if (!NT_STATUS_IS_OK(status)) {
6539 status = SMB_VFS_CREATE_FILE(
6542 0, /* root_dir_fid */
6543 smb_fname, /* fname */
6544 access_mask, /* access_mask */
6545 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6547 create_disp, /* create_disposition*/
6548 FILE_NON_DIRECTORY_FILE, /* create_options */
6549 mod_unixmode, /* file_attributes */
6550 oplock_request, /* oplock_request */
6551 0, /* allocation_size */
6557 *psbuf = smb_fname->st;
6558 TALLOC_FREE(smb_fname);
6560 if (!NT_STATUS_IS_OK(status)) {
6564 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6565 extended_oplock_granted = True;
6568 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6569 extended_oplock_granted = True;
6572 info_level_return = SVAL(pdata,16);
6574 /* Allocate the correct return size. */
6576 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6577 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6578 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6579 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6581 *pdata_return_size = 12;
6584 /* Realloc the data size */
6585 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6586 if (*ppdata == NULL) {
6587 close_file(req, fsp, ERROR_CLOSE);
6588 *pdata_return_size = 0;
6589 return NT_STATUS_NO_MEMORY;
6593 if (extended_oplock_granted) {
6594 if (flags & REQUEST_BATCH_OPLOCK) {
6595 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6597 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6599 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6600 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6602 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6605 SSVAL(pdata,2,fsp->fnum);
6606 SIVAL(pdata,4,info); /* Was file created etc. */
6608 switch (info_level_return) {
6609 case SMB_QUERY_FILE_UNIX_BASIC:
6610 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6611 SSVAL(pdata,10,0); /* padding. */
6612 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6614 case SMB_QUERY_FILE_UNIX_INFO2:
6615 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6616 SSVAL(pdata,10,0); /* padding. */
6617 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6620 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6621 SSVAL(pdata,10,0); /* padding. */
6624 return NT_STATUS_OK;
6627 /****************************************************************************
6628 Delete a file with POSIX semantics.
6629 ****************************************************************************/
6631 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6632 struct smb_request *req,
6636 SMB_STRUCT_STAT *psbuf)
6638 struct smb_filename *smb_fname = NULL;
6639 NTSTATUS status = NT_STATUS_OK;
6640 files_struct *fsp = NULL;
6644 int create_options = 0;
6646 struct share_mode_lock *lck = NULL;
6648 if (total_data < 2) {
6649 return NT_STATUS_INVALID_PARAMETER;
6652 flags = SVAL(pdata,0);
6654 if (!VALID_STAT(*psbuf)) {
6655 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6658 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6659 !VALID_STAT_OF_DIR(*psbuf)) {
6660 return NT_STATUS_NOT_A_DIRECTORY;
6663 DEBUG(10,("smb_posix_unlink: %s %s\n",
6664 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6667 if (VALID_STAT_OF_DIR(*psbuf)) {
6668 create_options |= FILE_DIRECTORY_FILE;
6671 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6673 if (!NT_STATUS_IS_OK(status)) {
6677 status = SMB_VFS_CREATE_FILE(
6680 0, /* root_dir_fid */
6681 smb_fname, /* fname */
6682 DELETE_ACCESS, /* access_mask */
6683 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6685 FILE_OPEN, /* create_disposition*/
6686 create_options, /* create_options */
6687 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6688 0, /* oplock_request */
6689 0, /* allocation_size */
6695 *psbuf = smb_fname->st;
6696 TALLOC_FREE(smb_fname);
6698 if (!NT_STATUS_IS_OK(status)) {
6703 * Don't lie to client. If we can't really delete due to
6704 * non-POSIX opens return SHARING_VIOLATION.
6707 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6710 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6711 "lock for file %s\n", fsp->fsp_name));
6712 close_file(req, fsp, NORMAL_CLOSE);
6713 return NT_STATUS_INVALID_PARAMETER;
6717 * See if others still have the file open. If this is the case, then
6718 * don't delete. If all opens are POSIX delete we can set the delete
6719 * on close disposition.
6721 for (i=0; i<lck->num_share_modes; i++) {
6722 struct share_mode_entry *e = &lck->share_modes[i];
6723 if (is_valid_share_mode_entry(e)) {
6724 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6727 /* Fail with sharing violation. */
6728 close_file(req, fsp, NORMAL_CLOSE);
6730 return NT_STATUS_SHARING_VIOLATION;
6735 * Set the delete on close.
6737 status = smb_set_file_disposition_info(conn,
6744 if (!NT_STATUS_IS_OK(status)) {
6745 close_file(req, fsp, NORMAL_CLOSE);
6750 return close_file(req, fsp, NORMAL_CLOSE);
6753 /****************************************************************************
6754 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6755 ****************************************************************************/
6757 static void call_trans2setfilepathinfo(connection_struct *conn,
6758 struct smb_request *req,
6759 unsigned int tran_call,
6760 char **pparams, int total_params,
6761 char **ppdata, int total_data,
6762 unsigned int max_data_bytes)
6764 char *params = *pparams;
6765 char *pdata = *ppdata;
6767 SMB_STRUCT_STAT sbuf;
6769 struct smb_filename *smb_fname = NULL;
6770 files_struct *fsp = NULL;
6771 NTSTATUS status = NT_STATUS_OK;
6772 int data_return_size = 0;
6773 TALLOC_CTX *ctx = talloc_tos();
6776 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6782 if (tran_call == TRANSACT2_SETFILEINFO) {
6783 if (total_params < 4) {
6784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6788 fsp = file_fsp(req, SVAL(params,0));
6789 /* Basic check for non-null fsp. */
6790 if (!check_fsp_open(conn, req, fsp)) {
6793 info_level = SVAL(params,2);
6795 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6797 reply_nterror(req, NT_STATUS_NO_MEMORY);
6801 if(fsp->is_directory || fsp->fh->fd == -1) {
6803 * This is actually a SETFILEINFO on a directory
6804 * handle (returned from an NT SMB). NT5.0 seems
6805 * to do this call. JRA.
6807 if (INFO_LEVEL_IS_UNIX(info_level)) {
6808 /* Always do lstat for UNIX calls. */
6809 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6810 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6811 reply_unixerror(req,ERRDOS,ERRbadpath);
6815 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6816 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6817 reply_unixerror(req,ERRDOS,ERRbadpath);
6821 } else if (fsp->print_file) {
6823 * Doing a DELETE_ON_CLOSE should cancel a print job.
6825 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6826 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6828 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6831 send_trans2_replies(conn, req, params, 2,
6836 reply_unixerror(req, ERRDOS, ERRbadpath);
6841 * Original code - this is an open file.
6843 if (!check_fsp(conn, req, fsp)) {
6847 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6848 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6849 reply_unixerror(req, ERRDOS, ERRbadfid);
6855 if (total_params < 7) {
6856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6860 info_level = SVAL(params,0);
6861 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6862 total_params - 6, STR_TERMINATE,
6864 if (!NT_STATUS_IS_OK(status)) {
6865 reply_nterror(req, status);
6869 status = resolve_dfspath(ctx, conn,
6870 req->flags2 & FLAGS2_DFS_PATHNAMES,
6873 if (!NT_STATUS_IS_OK(status)) {
6874 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6875 reply_botherror(req,
6876 NT_STATUS_PATH_NOT_COVERED,
6877 ERRSRV, ERRbadpath);
6880 reply_nterror(req, status);
6884 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
6885 if (!NT_STATUS_IS_OK(status)) {
6886 reply_nterror(req, status);
6889 sbuf = smb_fname->st;
6891 status = get_full_smb_filename(ctx, smb_fname, &fname);
6892 TALLOC_FREE(smb_fname);
6893 if (!NT_STATUS_IS_OK(status)) {
6894 reply_nterror(req, status);
6898 status = check_name(conn, fname);
6899 if (!NT_STATUS_IS_OK(status)) {
6900 reply_nterror(req, status);
6904 if (INFO_LEVEL_IS_UNIX(info_level)) {
6906 * For CIFS UNIX extensions the target name may not exist.
6909 /* Always do lstat for UNIX calls. */
6910 SMB_VFS_LSTAT(conn,fname,&sbuf);
6912 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6913 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6914 reply_unixerror(req, ERRDOS, ERRbadpath);
6919 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6920 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6924 if (!CAN_WRITE(conn)) {
6925 /* Allow POSIX opens. The open path will deny
6926 * any non-readonly opens. */
6927 if (info_level != SMB_POSIX_PATH_OPEN) {
6928 reply_doserror(req, ERRSRV, ERRaccess);
6933 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6934 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6936 /* Realloc the parameter size */
6937 *pparams = (char *)SMB_REALLOC(*pparams,2);
6938 if (*pparams == NULL) {
6939 reply_nterror(req, NT_STATUS_NO_MEMORY);
6946 switch (info_level) {
6948 case SMB_INFO_STANDARD:
6950 status = smb_set_info_standard(conn,
6959 case SMB_INFO_SET_EA:
6961 status = smb_info_set_ea(conn,
6969 case SMB_SET_FILE_BASIC_INFO:
6970 case SMB_FILE_BASIC_INFORMATION:
6972 status = smb_set_file_basic_info(conn,
6981 case SMB_FILE_ALLOCATION_INFORMATION:
6982 case SMB_SET_FILE_ALLOCATION_INFO:
6984 status = smb_set_file_allocation_info(conn, req,
6993 case SMB_FILE_END_OF_FILE_INFORMATION:
6994 case SMB_SET_FILE_END_OF_FILE_INFO:
6996 status = smb_set_file_end_of_file_info(conn, req,
7005 case SMB_FILE_DISPOSITION_INFORMATION:
7006 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7009 /* JRA - We used to just ignore this on a path ?
7010 * Shouldn't this be invalid level on a pathname
7013 if (tran_call != TRANSACT2_SETFILEINFO) {
7014 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7017 status = smb_set_file_disposition_info(conn,
7026 case SMB_FILE_POSITION_INFORMATION:
7028 status = smb_file_position_information(conn,
7035 /* From tridge Samba4 :
7036 * MODE_INFORMATION in setfileinfo (I have no
7037 * idea what "mode information" on a file is - it takes a value of 0,
7038 * 2, 4 or 6. What could it be?).
7041 case SMB_FILE_MODE_INFORMATION:
7043 status = smb_file_mode_information(conn,
7050 * CIFS UNIX extensions.
7053 case SMB_SET_FILE_UNIX_BASIC:
7055 status = smb_set_file_unix_basic(conn, req,
7064 case SMB_SET_FILE_UNIX_INFO2:
7066 status = smb_set_file_unix_info2(conn, req,
7075 case SMB_SET_FILE_UNIX_LINK:
7077 if (tran_call != TRANSACT2_SETPATHINFO) {
7078 /* We must have a pathname for this. */
7079 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7082 status = smb_set_file_unix_link(conn, req, pdata,
7087 case SMB_SET_FILE_UNIX_HLINK:
7089 if (tran_call != TRANSACT2_SETPATHINFO) {
7090 /* We must have a pathname for this. */
7091 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7094 status = smb_set_file_unix_hlink(conn, req,
7100 case SMB_FILE_RENAME_INFORMATION:
7102 status = smb_file_rename_information(conn, req,
7108 #if defined(HAVE_POSIX_ACLS)
7109 case SMB_SET_POSIX_ACL:
7111 status = smb_set_posix_acl(conn,
7121 case SMB_SET_POSIX_LOCK:
7123 if (tran_call != TRANSACT2_SETFILEINFO) {
7124 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7127 status = smb_set_posix_lock(conn, req,
7128 pdata, total_data, fsp);
7132 case SMB_POSIX_PATH_OPEN:
7134 if (tran_call != TRANSACT2_SETPATHINFO) {
7135 /* We must have a pathname for this. */
7136 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7140 status = smb_posix_open(conn, req,
7149 case SMB_POSIX_PATH_UNLINK:
7151 if (tran_call != TRANSACT2_SETPATHINFO) {
7152 /* We must have a pathname for this. */
7153 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7157 status = smb_posix_unlink(conn, req,
7166 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7170 if (!NT_STATUS_IS_OK(status)) {
7171 if (open_was_deferred(req->mid)) {
7172 /* We have re-scheduled this call. */
7175 if (blocking_lock_was_deferred(req->mid)) {
7176 /* We have re-scheduled this call. */
7179 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7180 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7181 ERRSRV, ERRbadpath);
7184 if (info_level == SMB_POSIX_PATH_OPEN) {
7185 reply_openerror(req, status);
7189 reply_nterror(req, status);
7194 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7200 /****************************************************************************
7201 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7202 ****************************************************************************/
7204 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7205 char **pparams, int total_params,
7206 char **ppdata, int total_data,
7207 unsigned int max_data_bytes)
7209 struct smb_filename *smb_dname = NULL;
7210 char *params = *pparams;
7211 char *pdata = *ppdata;
7212 char *directory = NULL;
7213 NTSTATUS status = NT_STATUS_OK;
7214 struct ea_list *ea_list = NULL;
7215 TALLOC_CTX *ctx = talloc_tos();
7217 if (!CAN_WRITE(conn)) {
7218 reply_doserror(req, ERRSRV, ERRaccess);
7222 if (total_params < 5) {
7223 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7227 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7228 total_params - 4, STR_TERMINATE,
7230 if (!NT_STATUS_IS_OK(status)) {
7231 reply_nterror(req, status);
7235 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7237 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
7238 if (!NT_STATUS_IS_OK(status)) {
7239 reply_nterror(req, status);
7243 status = check_name(conn, smb_dname->base_name);
7244 if (!NT_STATUS_IS_OK(status)) {
7245 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7246 reply_nterror(req, status);
7250 /* Any data in this call is an EA list. */
7251 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7252 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7257 * OS/2 workplace shell seems to send SET_EA requests of "null"
7258 * length (4 bytes containing IVAL 4).
7259 * They seem to have no effect. Bug #3212. JRA.
7262 if (total_data != 4) {
7263 if (total_data < 10) {
7264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7268 if (IVAL(pdata,0) > total_data) {
7269 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7270 IVAL(pdata,0), (unsigned int)total_data));
7271 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7275 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7282 /* If total_data == 4 Windows doesn't care what values
7283 * are placed in that field, it just ignores them.
7284 * The System i QNTC IBM SMB client puts bad values here,
7285 * so ignore them. */
7287 status = create_directory(conn, req, smb_dname);
7289 if (!NT_STATUS_IS_OK(status)) {
7290 reply_nterror(req, status);
7294 /* Try and set any given EA. */
7296 status = set_ea(conn, NULL, smb_dname->base_name, ea_list);
7297 if (!NT_STATUS_IS_OK(status)) {
7298 reply_nterror(req, status);
7303 /* Realloc the parameter and data sizes */
7304 *pparams = (char *)SMB_REALLOC(*pparams,2);
7305 if(*pparams == NULL) {
7306 reply_nterror(req, NT_STATUS_NO_MEMORY);
7313 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7316 TALLOC_FREE(smb_dname);
7320 /****************************************************************************
7321 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7322 We don't actually do this - we just send a null response.
7323 ****************************************************************************/
7325 static void call_trans2findnotifyfirst(connection_struct *conn,
7326 struct smb_request *req,
7327 char **pparams, int total_params,
7328 char **ppdata, int total_data,
7329 unsigned int max_data_bytes)
7331 char *params = *pparams;
7334 if (total_params < 6) {
7335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7339 info_level = SVAL(params,4);
7340 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7342 switch (info_level) {
7347 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7351 /* Realloc the parameter and data sizes */
7352 *pparams = (char *)SMB_REALLOC(*pparams,6);
7353 if (*pparams == NULL) {
7354 reply_nterror(req, NT_STATUS_NO_MEMORY);
7359 SSVAL(params,0,fnf_handle);
7360 SSVAL(params,2,0); /* No changes */
7361 SSVAL(params,4,0); /* No EA errors */
7368 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7373 /****************************************************************************
7374 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7375 changes). Currently this does nothing.
7376 ****************************************************************************/
7378 static void call_trans2findnotifynext(connection_struct *conn,
7379 struct smb_request *req,
7380 char **pparams, int total_params,
7381 char **ppdata, int total_data,
7382 unsigned int max_data_bytes)
7384 char *params = *pparams;
7386 DEBUG(3,("call_trans2findnotifynext\n"));
7388 /* Realloc the parameter and data sizes */
7389 *pparams = (char *)SMB_REALLOC(*pparams,4);
7390 if (*pparams == NULL) {
7391 reply_nterror(req, NT_STATUS_NO_MEMORY);
7396 SSVAL(params,0,0); /* No changes */
7397 SSVAL(params,2,0); /* No EA errors */
7399 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7404 /****************************************************************************
7405 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7406 ****************************************************************************/
7408 static void call_trans2getdfsreferral(connection_struct *conn,
7409 struct smb_request *req,
7410 char **pparams, int total_params,
7411 char **ppdata, int total_data,
7412 unsigned int max_data_bytes)
7414 char *params = *pparams;
7415 char *pathname = NULL;
7417 int max_referral_level;
7418 NTSTATUS status = NT_STATUS_OK;
7419 TALLOC_CTX *ctx = talloc_tos();
7421 DEBUG(10,("call_trans2getdfsreferral\n"));
7423 if (total_params < 3) {
7424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7428 max_referral_level = SVAL(params,0);
7430 if(!lp_host_msdfs()) {
7431 reply_doserror(req, ERRDOS, ERRbadfunc);
7435 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7436 total_params - 2, STR_TERMINATE);
7438 reply_nterror(req, NT_STATUS_NOT_FOUND);
7441 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7442 ppdata,&status)) < 0) {
7443 reply_nterror(req, status);
7447 SSVAL(req->inbuf, smb_flg2,
7448 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7449 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7454 #define LMCAT_SPL 0x53
7455 #define LMFUNC_GETJOBID 0x60
7457 /****************************************************************************
7458 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7459 ****************************************************************************/
7461 static void call_trans2ioctl(connection_struct *conn,
7462 struct smb_request *req,
7463 char **pparams, int total_params,
7464 char **ppdata, int total_data,
7465 unsigned int max_data_bytes)
7467 char *pdata = *ppdata;
7468 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7470 /* check for an invalid fid before proceeding */
7473 reply_doserror(req, ERRDOS, ERRbadfid);
7477 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7478 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7479 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7480 if (*ppdata == NULL) {
7481 reply_nterror(req, NT_STATUS_NO_MEMORY);
7486 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7487 CAN ACCEPT THIS IN UNICODE. JRA. */
7489 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7490 srvstr_push(pdata, req->flags2, pdata + 2,
7491 global_myname(), 15,
7492 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7493 srvstr_push(pdata, req->flags2, pdata+18,
7494 lp_servicename(SNUM(conn)), 13,
7495 STR_ASCII|STR_TERMINATE); /* Service name */
7496 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7501 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7502 reply_doserror(req, ERRSRV, ERRerror);
7505 /****************************************************************************
7506 Reply to a SMBfindclose (stop trans2 directory search).
7507 ****************************************************************************/
7509 void reply_findclose(struct smb_request *req)
7513 START_PROFILE(SMBfindclose);
7516 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7517 END_PROFILE(SMBfindclose);
7521 dptr_num = SVALS(req->vwv+0, 0);
7523 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7525 dptr_close(&dptr_num);
7527 reply_outbuf(req, 0, 0);
7529 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7531 END_PROFILE(SMBfindclose);
7535 /****************************************************************************
7536 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7537 ****************************************************************************/
7539 void reply_findnclose(struct smb_request *req)
7543 START_PROFILE(SMBfindnclose);
7546 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7547 END_PROFILE(SMBfindnclose);
7551 dptr_num = SVAL(req->vwv+0, 0);
7553 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7555 /* We never give out valid handles for a
7556 findnotifyfirst - so any dptr_num is ok here.
7559 reply_outbuf(req, 0, 0);
7561 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7563 END_PROFILE(SMBfindnclose);
7567 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7568 struct trans_state *state)
7570 if (Protocol >= PROTOCOL_NT1) {
7571 req->flags2 |= 0x40; /* IS_LONG_NAME */
7572 SSVAL(req->inbuf,smb_flg2,req->flags2);
7575 if (conn->encrypt_level == Required && !req->encrypted) {
7576 if (state->call != TRANSACT2_QFSINFO &&
7577 state->call != TRANSACT2_SETFSINFO) {
7578 DEBUG(0,("handle_trans2: encryption required "
7580 (unsigned int)state->call));
7581 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7586 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7588 /* Now we must call the relevant TRANS2 function */
7589 switch(state->call) {
7590 case TRANSACT2_OPEN:
7592 START_PROFILE(Trans2_open);
7593 call_trans2open(conn, req,
7594 &state->param, state->total_param,
7595 &state->data, state->total_data,
7596 state->max_data_return);
7597 END_PROFILE(Trans2_open);
7601 case TRANSACT2_FINDFIRST:
7603 START_PROFILE(Trans2_findfirst);
7604 call_trans2findfirst(conn, req,
7605 &state->param, state->total_param,
7606 &state->data, state->total_data,
7607 state->max_data_return);
7608 END_PROFILE(Trans2_findfirst);
7612 case TRANSACT2_FINDNEXT:
7614 START_PROFILE(Trans2_findnext);
7615 call_trans2findnext(conn, req,
7616 &state->param, state->total_param,
7617 &state->data, state->total_data,
7618 state->max_data_return);
7619 END_PROFILE(Trans2_findnext);
7623 case TRANSACT2_QFSINFO:
7625 START_PROFILE(Trans2_qfsinfo);
7626 call_trans2qfsinfo(conn, req,
7627 &state->param, state->total_param,
7628 &state->data, state->total_data,
7629 state->max_data_return);
7630 END_PROFILE(Trans2_qfsinfo);
7634 case TRANSACT2_SETFSINFO:
7636 START_PROFILE(Trans2_setfsinfo);
7637 call_trans2setfsinfo(conn, req,
7638 &state->param, state->total_param,
7639 &state->data, state->total_data,
7640 state->max_data_return);
7641 END_PROFILE(Trans2_setfsinfo);
7645 case TRANSACT2_QPATHINFO:
7646 case TRANSACT2_QFILEINFO:
7648 START_PROFILE(Trans2_qpathinfo);
7649 call_trans2qfilepathinfo(conn, req, state->call,
7650 &state->param, state->total_param,
7651 &state->data, state->total_data,
7652 state->max_data_return);
7653 END_PROFILE(Trans2_qpathinfo);
7657 case TRANSACT2_SETPATHINFO:
7658 case TRANSACT2_SETFILEINFO:
7660 START_PROFILE(Trans2_setpathinfo);
7661 call_trans2setfilepathinfo(conn, req, state->call,
7662 &state->param, state->total_param,
7663 &state->data, state->total_data,
7664 state->max_data_return);
7665 END_PROFILE(Trans2_setpathinfo);
7669 case TRANSACT2_FINDNOTIFYFIRST:
7671 START_PROFILE(Trans2_findnotifyfirst);
7672 call_trans2findnotifyfirst(conn, req,
7673 &state->param, state->total_param,
7674 &state->data, state->total_data,
7675 state->max_data_return);
7676 END_PROFILE(Trans2_findnotifyfirst);
7680 case TRANSACT2_FINDNOTIFYNEXT:
7682 START_PROFILE(Trans2_findnotifynext);
7683 call_trans2findnotifynext(conn, req,
7684 &state->param, state->total_param,
7685 &state->data, state->total_data,
7686 state->max_data_return);
7687 END_PROFILE(Trans2_findnotifynext);
7691 case TRANSACT2_MKDIR:
7693 START_PROFILE(Trans2_mkdir);
7694 call_trans2mkdir(conn, req,
7695 &state->param, state->total_param,
7696 &state->data, state->total_data,
7697 state->max_data_return);
7698 END_PROFILE(Trans2_mkdir);
7702 case TRANSACT2_GET_DFS_REFERRAL:
7704 START_PROFILE(Trans2_get_dfs_referral);
7705 call_trans2getdfsreferral(conn, req,
7706 &state->param, state->total_param,
7707 &state->data, state->total_data,
7708 state->max_data_return);
7709 END_PROFILE(Trans2_get_dfs_referral);
7713 case TRANSACT2_IOCTL:
7715 START_PROFILE(Trans2_ioctl);
7716 call_trans2ioctl(conn, req,
7717 &state->param, state->total_param,
7718 &state->data, state->total_data,
7719 state->max_data_return);
7720 END_PROFILE(Trans2_ioctl);
7725 /* Error in request */
7726 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7727 reply_doserror(req, ERRSRV,ERRerror);
7731 /****************************************************************************
7732 Reply to a SMBtrans2.
7733 ****************************************************************************/
7735 void reply_trans2(struct smb_request *req)
7737 connection_struct *conn = req->conn;
7742 unsigned int tran_call;
7743 struct trans_state *state;
7746 START_PROFILE(SMBtrans2);
7748 if (req->wct < 14) {
7749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7750 END_PROFILE(SMBtrans2);
7754 dsoff = SVAL(req->vwv+12, 0);
7755 dscnt = SVAL(req->vwv+11, 0);
7756 psoff = SVAL(req->vwv+10, 0);
7757 pscnt = SVAL(req->vwv+9, 0);
7758 tran_call = SVAL(req->vwv+14, 0);
7760 result = allow_new_trans(conn->pending_trans, req->mid);
7761 if (!NT_STATUS_IS_OK(result)) {
7762 DEBUG(2, ("Got invalid trans2 request: %s\n",
7763 nt_errstr(result)));
7764 reply_nterror(req, result);
7765 END_PROFILE(SMBtrans2);
7770 switch (tran_call) {
7771 /* List the allowed trans2 calls on IPC$ */
7772 case TRANSACT2_OPEN:
7773 case TRANSACT2_GET_DFS_REFERRAL:
7774 case TRANSACT2_QFILEINFO:
7775 case TRANSACT2_QFSINFO:
7776 case TRANSACT2_SETFSINFO:
7779 reply_doserror(req, ERRSRV, ERRaccess);
7780 END_PROFILE(SMBtrans2);
7785 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7786 DEBUG(0, ("talloc failed\n"));
7787 reply_nterror(req, NT_STATUS_NO_MEMORY);
7788 END_PROFILE(SMBtrans2);
7792 state->cmd = SMBtrans2;
7794 state->mid = req->mid;
7795 state->vuid = req->vuid;
7796 state->setup_count = SVAL(req->vwv+13, 0);
7797 state->setup = NULL;
7798 state->total_param = SVAL(req->vwv+0, 0);
7799 state->param = NULL;
7800 state->total_data = SVAL(req->vwv+1, 0);
7802 state->max_param_return = SVAL(req->vwv+2, 0);
7803 state->max_data_return = SVAL(req->vwv+3, 0);
7804 state->max_setup_return = SVAL(req->vwv+4, 0);
7805 state->close_on_completion = BITSETW(req->vwv+5, 0);
7806 state->one_way = BITSETW(req->vwv+5, 1);
7808 state->call = tran_call;
7810 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7811 is so as a sanity check */
7812 if (state->setup_count != 1) {
7814 * Need to have rc=0 for ioctl to get job id for OS/2.
7815 * Network printing will fail if function is not successful.
7816 * Similar function in reply.c will be used if protocol
7817 * is LANMAN1.0 instead of LM1.2X002.
7818 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7819 * outbuf doesn't have to be set(only job id is used).
7821 if ( (state->setup_count == 4)
7822 && (tran_call == TRANSACT2_IOCTL)
7823 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7824 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7825 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7827 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7828 DEBUG(2,("Transaction is %d\n",tran_call));
7830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7831 END_PROFILE(SMBtrans2);
7836 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7839 if (state->total_data) {
7841 if (trans_oob(state->total_data, 0, dscnt)
7842 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7846 /* Can't use talloc here, the core routines do realloc on the
7847 * params and data. */
7848 state->data = (char *)SMB_MALLOC(state->total_data);
7849 if (state->data == NULL) {
7850 DEBUG(0,("reply_trans2: data malloc fail for %u "
7851 "bytes !\n", (unsigned int)state->total_data));
7853 reply_nterror(req, NT_STATUS_NO_MEMORY);
7854 END_PROFILE(SMBtrans2);
7858 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7861 if (state->total_param) {
7863 if (trans_oob(state->total_param, 0, pscnt)
7864 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7868 /* Can't use talloc here, the core routines do realloc on the
7869 * params and data. */
7870 state->param = (char *)SMB_MALLOC(state->total_param);
7871 if (state->param == NULL) {
7872 DEBUG(0,("reply_trans: param malloc fail for %u "
7873 "bytes !\n", (unsigned int)state->total_param));
7874 SAFE_FREE(state->data);
7876 reply_nterror(req, NT_STATUS_NO_MEMORY);
7877 END_PROFILE(SMBtrans2);
7881 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7884 state->received_data = dscnt;
7885 state->received_param = pscnt;
7887 if ((state->received_param == state->total_param) &&
7888 (state->received_data == state->total_data)) {
7890 handle_trans2(conn, req, state);
7892 SAFE_FREE(state->data);
7893 SAFE_FREE(state->param);
7895 END_PROFILE(SMBtrans2);
7899 DLIST_ADD(conn->pending_trans, state);
7901 /* We need to send an interim response then receive the rest
7902 of the parameter/data bytes */
7903 reply_outbuf(req, 0, 0);
7904 show_msg((char *)req->outbuf);
7905 END_PROFILE(SMBtrans2);
7910 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7911 SAFE_FREE(state->data);
7912 SAFE_FREE(state->param);
7914 END_PROFILE(SMBtrans2);
7915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7919 /****************************************************************************
7920 Reply to a SMBtranss2
7921 ****************************************************************************/
7923 void reply_transs2(struct smb_request *req)
7925 connection_struct *conn = req->conn;
7926 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7927 struct trans_state *state;
7929 START_PROFILE(SMBtranss2);
7931 show_msg((char *)req->inbuf);
7934 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7935 END_PROFILE(SMBtranss2);
7939 for (state = conn->pending_trans; state != NULL;
7940 state = state->next) {
7941 if (state->mid == req->mid) {
7946 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7948 END_PROFILE(SMBtranss2);
7952 /* Revise state->total_param and state->total_data in case they have
7953 changed downwards */
7955 if (SVAL(req->vwv+0, 0) < state->total_param)
7956 state->total_param = SVAL(req->vwv+0, 0);
7957 if (SVAL(req->vwv+1, 0) < state->total_data)
7958 state->total_data = SVAL(req->vwv+1, 0);
7960 pcnt = SVAL(req->vwv+2, 0);
7961 poff = SVAL(req->vwv+3, 0);
7962 pdisp = SVAL(req->vwv+4, 0);
7964 dcnt = SVAL(req->vwv+5, 0);
7965 doff = SVAL(req->vwv+6, 0);
7966 ddisp = SVAL(req->vwv+7, 0);
7968 state->received_param += pcnt;
7969 state->received_data += dcnt;
7971 if ((state->received_data > state->total_data) ||
7972 (state->received_param > state->total_param))
7976 if (trans_oob(state->total_param, pdisp, pcnt)
7977 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7980 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7984 if (trans_oob(state->total_data, ddisp, dcnt)
7985 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7988 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7991 if ((state->received_param < state->total_param) ||
7992 (state->received_data < state->total_data)) {
7993 END_PROFILE(SMBtranss2);
7997 handle_trans2(conn, req, state);
7999 DLIST_REMOVE(conn->pending_trans, state);
8000 SAFE_FREE(state->data);
8001 SAFE_FREE(state->param);
8004 END_PROFILE(SMBtranss2);
8009 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8010 DLIST_REMOVE(conn->pending_trans, state);
8011 SAFE_FREE(state->data);
8012 SAFE_FREE(state->param);
8014 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8015 END_PROFILE(SMBtranss2);