2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
247 *pnum_names = num_names;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list *ea_list_head = NULL;
266 if (!lp_ea_support(SNUM(conn))) {
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
285 listp = TALLOC_P(mem_ctx, struct ea_list);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
346 if (ea_list->ea.value.length > 65535) {
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
372 size_t total_ea_len = 0;
373 TALLOC_CTX *mem_ctx = NULL;
375 if (!lp_ea_support(SNUM(conn))) {
378 mem_ctx = talloc_tos();
379 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
383 /****************************************************************************
384 Ensure the EA name is case insensitive by matching any existing EA name.
385 ****************************************************************************/
387 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
390 TALLOC_CTX *mem_ctx = talloc_tos();
391 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
393 for (; ea_list; ea_list = ea_list->next) {
394 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
395 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
396 &unix_ea_name[5], ea_list->ea.name));
397 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
403 /****************************************************************************
404 Set or delete an extended attribute.
405 ****************************************************************************/
407 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
409 if (!lp_ea_support(SNUM(conn))) {
410 return NT_STATUS_EAS_NOT_SUPPORTED;
413 for (;ea_list; ea_list = ea_list->next) {
415 fstring unix_ea_name;
417 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
418 fstrcat(unix_ea_name, ea_list->ea.name);
420 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
422 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
424 if (samba_private_attr_name(unix_ea_name)) {
425 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
426 return NT_STATUS_ACCESS_DENIED;
429 if (ea_list->ea.value.length == 0) {
430 /* Remove the attribute. */
431 if (fsp && (fsp->fh->fd != -1)) {
432 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
433 unix_ea_name, fsp->fsp_name));
434 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
436 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
437 unix_ea_name, fname));
438 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
441 /* Removing a non existent attribute always succeeds. */
442 if (ret == -1 && errno == ENOATTR) {
443 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
449 if (fsp && (fsp->fh->fd != -1)) {
450 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
451 unix_ea_name, fsp->fsp_name));
452 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
453 ea_list->ea.value.data, ea_list->ea.value.length, 0);
455 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
456 unix_ea_name, fname));
457 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
458 ea_list->ea.value.data, ea_list->ea.value.length, 0);
464 if (errno == ENOTSUP) {
465 return NT_STATUS_EAS_NOT_SUPPORTED;
468 return map_nt_error_from_unix(errno);
474 /****************************************************************************
475 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
476 ****************************************************************************/
478 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
480 struct ea_list *ea_list_head = NULL;
481 size_t converted_size, offset = 0;
483 while (offset + 2 < data_size) {
484 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
485 unsigned int namelen = CVAL(pdata,offset);
487 offset++; /* Go past the namelen byte. */
489 /* integer wrap paranioa. */
490 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
491 (offset > data_size) || (namelen > data_size) ||
492 (offset + namelen >= data_size)) {
495 /* Ensure the name is null terminated. */
496 if (pdata[offset + namelen] != '\0') {
499 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
501 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
502 "failed: %s", strerror(errno)));
508 offset += (namelen + 1); /* Go past the name + terminating zero. */
509 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
510 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
516 /****************************************************************************
517 Read one EA list entry from the buffer.
518 ****************************************************************************/
520 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
522 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
524 unsigned int namelen;
525 size_t converted_size;
535 eal->ea.flags = CVAL(pdata,0);
536 namelen = CVAL(pdata,1);
537 val_len = SVAL(pdata,2);
539 if (4 + namelen + 1 + val_len > data_size) {
543 /* Ensure the name is null terminated. */
544 if (pdata[namelen + 4] != '\0') {
547 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
548 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
555 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
556 if (!eal->ea.value.data) {
560 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
562 /* Ensure we're null terminated just in case we print the value. */
563 eal->ea.value.data[val_len] = '\0';
564 /* But don't count the null. */
565 eal->ea.value.length--;
568 *pbytes_used = 4 + namelen + 1 + val_len;
571 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
572 dump_data(10, eal->ea.value.data, eal->ea.value.length);
577 /****************************************************************************
578 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
579 ****************************************************************************/
581 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
583 struct ea_list *ea_list_head = NULL;
585 size_t bytes_used = 0;
587 while (offset < data_size) {
588 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
594 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
595 offset += bytes_used;
601 /****************************************************************************
602 Count the total EA size needed.
603 ****************************************************************************/
605 static size_t ea_list_size(struct ea_list *ealist)
608 struct ea_list *listp;
611 for (listp = ealist; listp; listp = listp->next) {
612 push_ascii_fstring(dos_ea_name, listp->ea.name);
613 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
615 /* Add on 4 for total length. */
623 /****************************************************************************
624 Return a union of EA's from a file list and a list of names.
625 The TALLOC context for the two lists *MUST* be identical as we steal
626 memory from one list to add to another. JRA.
627 ****************************************************************************/
629 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
631 struct ea_list *nlistp, *flistp;
633 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
634 for (flistp = file_list; flistp; flistp = flistp->next) {
635 if (strequal(nlistp->ea.name, flistp->ea.name)) {
641 /* Copy the data from this entry. */
642 nlistp->ea.flags = flistp->ea.flags;
643 nlistp->ea.value = flistp->ea.value;
646 nlistp->ea.flags = 0;
647 ZERO_STRUCT(nlistp->ea.value);
651 *total_ea_len = ea_list_size(name_list);
655 /****************************************************************************
656 Send the required number of replies back.
657 We assume all fields other than the data fields are
658 set correctly for the type of call.
659 HACK ! Always assumes smb_setup field is zero.
660 ****************************************************************************/
662 void send_trans2_replies(connection_struct *conn,
663 struct smb_request *req,
670 /* As we are using a protocol > LANMAN1 then the max_send
671 variable must have been set in the sessetupX call.
672 This takes precedence over the max_xmit field in the
673 global struct. These different max_xmit variables should
674 be merged as this is now too confusing */
676 int data_to_send = datasize;
677 int params_to_send = paramsize;
679 const char *pp = params;
680 const char *pd = pdata;
681 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
682 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
683 int data_alignment_offset = 0;
684 bool overflow = False;
685 struct smbd_server_connection *sconn = smbd_server_conn;
686 int max_send = sconn->smb1.sessions.max_send;
688 /* Modify the data_to_send and datasize and set the error if
689 we're trying to send more than max_data_bytes. We still send
690 the part of the packet(s) that fit. Strange, but needed
693 if (max_data_bytes > 0 && datasize > max_data_bytes) {
694 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
695 max_data_bytes, datasize ));
696 datasize = data_to_send = max_data_bytes;
700 /* If there genuinely are no parameters or data to send just send the empty packet */
702 if(params_to_send == 0 && data_to_send == 0) {
703 reply_outbuf(req, 10, 0);
704 show_msg((char *)req->outbuf);
708 /* When sending params and data ensure that both are nicely aligned */
709 /* Only do this alignment when there is also data to send - else
710 can cause NT redirector problems. */
712 if (((params_to_send % 4) != 0) && (data_to_send != 0))
713 data_alignment_offset = 4 - (params_to_send % 4);
715 /* Space is bufsize minus Netbios over TCP header minus SMB header */
716 /* The alignment_offset is to align the param bytes on an even byte
717 boundary. NT 4.0 Beta needs this to work correctly. */
719 useable_space = max_send - (smb_size
722 + data_alignment_offset);
724 if (useable_space < 0) {
725 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
726 "= %d!!!", useable_space));
727 exit_server_cleanly("send_trans2_replies: Not enough space");
730 while (params_to_send || data_to_send) {
731 /* Calculate whether we will totally or partially fill this packet */
733 total_sent_thistime = params_to_send + data_to_send;
735 /* We can never send more than useable_space */
737 * Note that 'useable_space' does not include the alignment offsets,
738 * but we must include the alignment offsets in the calculation of
739 * the length of the data we send over the wire, as the alignment offsets
740 * are sent here. Fix from Marc_Jacobsen@hp.com.
743 total_sent_thistime = MIN(total_sent_thistime, useable_space);
745 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
746 + data_alignment_offset);
749 * We might have SMBtrans2s in req which was transferred to
750 * the outbuf, fix that.
752 SCVAL(req->outbuf, smb_com, SMBtrans2);
754 /* Set total params and data to be sent */
755 SSVAL(req->outbuf,smb_tprcnt,paramsize);
756 SSVAL(req->outbuf,smb_tdrcnt,datasize);
758 /* Calculate how many parameters and data we can fit into
759 * this packet. Parameters get precedence
762 params_sent_thistime = MIN(params_to_send,useable_space);
763 data_sent_thistime = useable_space - params_sent_thistime;
764 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
766 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
768 /* smb_proff is the offset from the start of the SMB header to the
769 parameter bytes, however the first 4 bytes of outbuf are
770 the Netbios over TCP header. Thus use smb_base() to subtract
771 them from the calculation */
773 SSVAL(req->outbuf,smb_proff,
774 ((smb_buf(req->outbuf)+alignment_offset)
775 - smb_base(req->outbuf)));
777 if(params_sent_thistime == 0)
778 SSVAL(req->outbuf,smb_prdisp,0);
780 /* Absolute displacement of param bytes sent in this packet */
781 SSVAL(req->outbuf,smb_prdisp,pp - params);
783 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
784 if(data_sent_thistime == 0) {
785 SSVAL(req->outbuf,smb_droff,0);
786 SSVAL(req->outbuf,smb_drdisp, 0);
788 /* The offset of the data bytes is the offset of the
789 parameter bytes plus the number of parameters being sent this time */
790 SSVAL(req->outbuf, smb_droff,
791 ((smb_buf(req->outbuf)+alignment_offset)
792 - smb_base(req->outbuf))
793 + params_sent_thistime + data_alignment_offset);
794 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
797 /* Initialize the padding for alignment */
799 if (alignment_offset != 0) {
800 memset(smb_buf(req->outbuf), 0, alignment_offset);
803 /* Copy the param bytes into the packet */
805 if(params_sent_thistime) {
806 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
807 params_sent_thistime);
810 /* Copy in the data bytes */
811 if(data_sent_thistime) {
812 if (data_alignment_offset != 0) {
813 memset((smb_buf(req->outbuf)+alignment_offset+
814 params_sent_thistime), 0,
815 data_alignment_offset);
817 memcpy(smb_buf(req->outbuf)+alignment_offset
818 +params_sent_thistime+data_alignment_offset,
819 pd,data_sent_thistime);
822 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
823 params_sent_thistime, data_sent_thistime, useable_space));
824 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
825 params_to_send, data_to_send, paramsize, datasize));
828 error_packet_set((char *)req->outbuf,
829 ERRDOS,ERRbufferoverflow,
830 STATUS_BUFFER_OVERFLOW,
834 /* Send the packet */
835 show_msg((char *)req->outbuf);
836 if (!srv_send_smb(smbd_server_fd(),
839 IS_CONN_ENCRYPTED(conn),
841 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
843 TALLOC_FREE(req->outbuf);
845 pp += params_sent_thistime;
846 pd += data_sent_thistime;
848 params_to_send -= params_sent_thistime;
849 data_to_send -= data_sent_thistime;
852 if(params_to_send < 0 || data_to_send < 0) {
853 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
854 params_to_send, data_to_send));
862 /****************************************************************************
863 Reply to a TRANSACT2_OPEN.
864 ****************************************************************************/
866 static void call_trans2open(connection_struct *conn,
867 struct smb_request *req,
868 char **pparams, int total_params,
869 char **ppdata, int total_data,
870 unsigned int max_data_bytes)
872 struct smb_filename *smb_fname = NULL;
873 char *params = *pparams;
874 char *pdata = *ppdata;
879 bool return_additional_info;
892 struct ea_list *ea_list = NULL;
897 uint32 create_disposition;
898 uint32 create_options = 0;
899 TALLOC_CTX *ctx = talloc_tos();
902 * Ensure we have enough parameters to perform the operation.
905 if (total_params < 29) {
906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
910 flags = SVAL(params, 0);
911 deny_mode = SVAL(params, 2);
912 open_attr = SVAL(params,6);
913 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
914 if (oplock_request) {
915 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
919 return_additional_info = BITSETW(params,0);
920 open_sattr = SVAL(params, 4);
921 open_time = make_unix_date3(params+8);
923 open_ofun = SVAL(params,12);
924 open_size = IVAL(params,14);
928 reply_doserror(req, ERRSRV, ERRaccess);
932 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
933 total_params - 28, STR_TERMINATE,
935 if (!NT_STATUS_IS_OK(status)) {
936 reply_nterror(req, status);
940 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
941 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
942 (unsigned int)open_ofun, open_size));
944 status = resolve_dfspath(ctx,
946 req->flags2 & FLAGS2_DFS_PATHNAMES,
949 if (!NT_STATUS_IS_OK(status)) {
950 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
952 NT_STATUS_PATH_NOT_COVERED,
956 reply_nterror(req, status);
960 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
961 if (!NT_STATUS_IS_OK(status)) {
962 reply_nterror(req, status);
966 if (open_ofun == 0) {
967 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
971 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
976 reply_doserror(req, ERRDOS, ERRbadaccess);
980 /* Any data in this call is an EA list. */
981 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
982 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
986 if (total_data != 4) {
987 if (total_data < 10) {
988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
992 if (IVAL(pdata,0) > total_data) {
993 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
994 IVAL(pdata,0), (unsigned int)total_data));
995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
999 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1005 } else if (IVAL(pdata,0) != 4) {
1006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1010 status = SMB_VFS_CREATE_FILE(
1013 0, /* root_dir_fid */
1014 smb_fname, /* fname */
1015 access_mask, /* access_mask */
1016 share_mode, /* share_access */
1017 create_disposition, /* create_disposition*/
1018 create_options, /* create_options */
1019 open_attr, /* file_attributes */
1020 oplock_request, /* oplock_request */
1021 open_size, /* allocation_size */
1023 ea_list, /* ea_list */
1025 &smb_action); /* psbuf */
1027 if (!NT_STATUS_IS_OK(status)) {
1028 if (open_was_deferred(req->mid)) {
1029 /* We have re-scheduled this call. */
1032 reply_openerror(req, status);
1036 size = get_file_size_stat(&smb_fname->st);
1037 fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st);
1038 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1039 inode = smb_fname->st.st_ex_ino;
1041 close_file(req, fsp, ERROR_CLOSE);
1042 reply_doserror(req, ERRDOS,ERRnoaccess);
1046 /* Realloc the size of parameters and data we will return */
1047 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1048 if(*pparams == NULL ) {
1049 reply_nterror(req, NT_STATUS_NO_MEMORY);
1054 SSVAL(params,0,fsp->fnum);
1055 SSVAL(params,2,fattr);
1056 srv_put_dos_date2(params,4, mtime);
1057 SIVAL(params,8, (uint32)size);
1058 SSVAL(params,12,deny_mode);
1059 SSVAL(params,14,0); /* open_type - file or directory. */
1060 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1062 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1063 smb_action |= EXTENDED_OPLOCK_GRANTED;
1066 SSVAL(params,18,smb_action);
1069 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1071 SIVAL(params,20,inode);
1072 SSVAL(params,24,0); /* Padding. */
1074 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1075 SIVAL(params, 26, ea_size);
1077 SIVAL(params, 26, 0);
1080 /* Send the required number of replies */
1081 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1083 TALLOC_FREE(smb_fname);
1086 /*********************************************************
1087 Routine to check if a given string matches exactly.
1088 as a special case a mask of "." does NOT match. That
1089 is required for correct wildcard semantics
1090 Case can be significant or not.
1091 **********************************************************/
1093 static bool exact_match(connection_struct *conn,
1097 if (mask[0] == '.' && mask[1] == 0)
1099 if (dptr_has_wild(conn->dirptr)) {
1102 if (conn->case_sensitive)
1103 return strcmp(str,mask)==0;
1105 return StrCaseCmp(str,mask) == 0;
1108 /****************************************************************************
1109 Return the filetype for UNIX extensions.
1110 ****************************************************************************/
1112 static uint32 unix_filetype(mode_t mode)
1115 return UNIX_TYPE_FILE;
1116 else if(S_ISDIR(mode))
1117 return UNIX_TYPE_DIR;
1119 else if(S_ISLNK(mode))
1120 return UNIX_TYPE_SYMLINK;
1123 else if(S_ISCHR(mode))
1124 return UNIX_TYPE_CHARDEV;
1127 else if(S_ISBLK(mode))
1128 return UNIX_TYPE_BLKDEV;
1131 else if(S_ISFIFO(mode))
1132 return UNIX_TYPE_FIFO;
1135 else if(S_ISSOCK(mode))
1136 return UNIX_TYPE_SOCKET;
1139 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1140 return UNIX_TYPE_UNKNOWN;
1143 /****************************************************************************
1144 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1145 ****************************************************************************/
1147 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1149 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1150 SMB_STRUCT_STAT *psbuf,
1152 enum perm_type ptype,
1157 if (perms == SMB_MODE_NO_CHANGE) {
1158 if (!VALID_STAT(*psbuf)) {
1159 return NT_STATUS_INVALID_PARAMETER;
1161 *ret_perms = psbuf->st_ex_mode;
1162 return NT_STATUS_OK;
1166 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1167 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1168 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1169 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1170 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1171 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1172 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1173 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1174 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1176 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1179 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1182 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1187 /* Apply mode mask */
1188 ret &= lp_create_mask(SNUM(conn));
1189 /* Add in force bits */
1190 ret |= lp_force_create_mode(SNUM(conn));
1193 ret &= lp_dir_mask(SNUM(conn));
1194 /* Add in force bits */
1195 ret |= lp_force_dir_mode(SNUM(conn));
1197 case PERM_EXISTING_FILE:
1198 /* Apply mode mask */
1199 ret &= lp_security_mask(SNUM(conn));
1200 /* Add in force bits */
1201 ret |= lp_force_security_mode(SNUM(conn));
1203 case PERM_EXISTING_DIR:
1204 /* Apply mode mask */
1205 ret &= lp_dir_security_mask(SNUM(conn));
1206 /* Add in force bits */
1207 ret |= lp_force_dir_security_mode(SNUM(conn));
1212 return NT_STATUS_OK;
1215 /****************************************************************************
1216 Needed to show the msdfs symlinks as directories. Modifies psbuf
1217 to be a directory if it's a msdfs link.
1218 ****************************************************************************/
1220 static bool check_msdfs_link(connection_struct *conn,
1221 const char *pathname,
1222 SMB_STRUCT_STAT *psbuf)
1224 int saved_errno = errno;
1225 if(lp_host_msdfs() &&
1226 lp_msdfs_root(SNUM(conn)) &&
1227 is_msdfs_link(conn, pathname, psbuf)) {
1229 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1232 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1233 errno = saved_errno;
1236 errno = saved_errno;
1241 /****************************************************************************
1242 Get a level dependent lanman2 dir entry.
1243 ****************************************************************************/
1245 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1246 connection_struct *conn,
1248 const char *path_mask,
1251 int requires_resume_key,
1257 int space_remaining,
1259 bool *got_exact_match,
1260 int *last_entry_off,
1261 struct ea_list *name_list)
1265 SMB_STRUCT_STAT sbuf;
1266 const char *mask = NULL;
1267 char *pathreal = NULL;
1269 char *p, *q, *pdata = *ppdata;
1273 SMB_OFF_T file_size = 0;
1274 uint64_t allocation_size = 0;
1276 struct timespec mdate_ts, adate_ts, create_date_ts;
1277 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1279 char *last_entry_ptr;
1281 uint32 nt_extmode; /* Used for NT connections instead of mode */
1282 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1283 bool check_mangled_names = lp_manglednames(conn->params);
1284 char mangled_name[13]; /* mangled 8.3 name. */
1286 *out_of_space = False;
1287 *got_exact_match = False;
1289 ZERO_STRUCT(mdate_ts);
1290 ZERO_STRUCT(adate_ts);
1291 ZERO_STRUCT(create_date_ts);
1293 if (!conn->dirptr) {
1297 p = strrchr_m(path_mask,'/');
1300 mask = talloc_strdup(ctx,"*.*");
1310 bool ms_dfs_link = False;
1312 /* Needed if we run out of space */
1313 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1314 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1317 * Due to bugs in NT client redirectors we are not using
1318 * resume keys any more - set them to zero.
1319 * Check out the related comments in findfirst/findnext.
1325 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1326 (long)conn->dirptr,curr_dirpos));
1333 * fname may get mangled, dname is never mangled.
1334 * Whenever we're accessing the filesystem we use
1335 * pathreal which is composed from dname.
1341 /* Mangle fname if it's an illegal name. */
1342 if (mangle_must_mangle(dname,conn->params)) {
1343 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1345 continue; /* Error - couldn't mangle. */
1347 fname = talloc_strdup(ctx, mangled_name);
1353 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1354 got_match = mask_match(fname, mask, conn->case_sensitive);
1357 if(!got_match && check_mangled_names &&
1358 !mangle_is_8_3(fname, False, conn->params)) {
1360 * It turns out that NT matches wildcards against
1361 * both long *and* short names. This may explain some
1362 * of the wildcard wierdness from old DOS clients
1363 * that some people have been seeing.... JRA.
1365 /* Force the mangling into 8.3. */
1366 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1368 continue; /* Error - couldn't mangle. */
1371 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1372 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1377 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1379 if (dont_descend && !isdots) {
1386 pathreal = talloc_asprintf(ctx,
1391 pathreal = talloc_asprintf(ctx,
1402 if (INFO_LEVEL_IS_UNIX(info_level)) {
1403 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1404 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1405 pathreal,strerror(errno)));
1406 TALLOC_FREE(pathreal);
1410 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1411 /* Needed to show the msdfs symlinks as
1414 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1416 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1417 pathreal,strerror(errno)));
1418 TALLOC_FREE(pathreal);
1425 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1427 mode = dos_mode(conn,pathreal,&sbuf);
1430 if (!dir_check_ftype(conn,mode,dirtype)) {
1431 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1432 TALLOC_FREE(pathreal);
1437 if (!(mode & aDIR)) {
1438 file_size = get_file_size_stat(&sbuf);
1440 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1442 mdate_ts = sbuf.st_ex_mtime;
1443 adate_ts = sbuf.st_ex_atime;
1444 create_date_ts = sbuf.st_ex_btime;
1446 if (ask_sharemode) {
1447 struct timespec write_time_ts;
1448 struct file_id fileid;
1450 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1451 get_file_infos(fileid, NULL, &write_time_ts);
1452 if (!null_timespec(write_time_ts)) {
1453 mdate_ts = write_time_ts;
1457 if (lp_dos_filetime_resolution(SNUM(conn))) {
1458 dos_filetime_timespec(&create_date_ts);
1459 dos_filetime_timespec(&mdate_ts);
1460 dos_filetime_timespec(&adate_ts);
1463 create_date = convert_timespec_to_time_t(create_date_ts);
1464 mdate = convert_timespec_to_time_t(mdate_ts);
1465 adate = convert_timespec_to_time_t(adate_ts);
1467 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1472 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1482 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1484 switch (info_level) {
1485 case SMB_FIND_INFO_STANDARD:
1486 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1487 if(requires_resume_key) {
1491 srv_put_dos_date2(p,0,create_date);
1492 srv_put_dos_date2(p,4,adate);
1493 srv_put_dos_date2(p,8,mdate);
1494 SIVAL(p,12,(uint32)file_size);
1495 SIVAL(p,16,(uint32)allocation_size);
1499 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1500 p += ucs2_align(base_data, p, 0);
1502 len = srvstr_push(base_data, flags2, p,
1503 fname, PTR_DIFF(end_data, p),
1505 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1507 SCVAL(nameptr, -1, len - 2);
1509 SCVAL(nameptr, -1, 0);
1513 SCVAL(nameptr, -1, len - 1);
1515 SCVAL(nameptr, -1, 0);
1521 case SMB_FIND_EA_SIZE:
1522 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1523 if(requires_resume_key) {
1527 srv_put_dos_date2(p,0,create_date);
1528 srv_put_dos_date2(p,4,adate);
1529 srv_put_dos_date2(p,8,mdate);
1530 SIVAL(p,12,(uint32)file_size);
1531 SIVAL(p,16,(uint32)allocation_size);
1534 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1535 SIVAL(p,22,ea_size); /* Extended attributes */
1539 len = srvstr_push(base_data, flags2,
1540 p, fname, PTR_DIFF(end_data, p),
1541 STR_TERMINATE | STR_NOALIGN);
1542 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1555 SCVAL(nameptr,0,len);
1557 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1560 case SMB_FIND_EA_LIST:
1562 struct ea_list *file_list = NULL;
1565 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1569 if(requires_resume_key) {
1573 srv_put_dos_date2(p,0,create_date);
1574 srv_put_dos_date2(p,4,adate);
1575 srv_put_dos_date2(p,8,mdate);
1576 SIVAL(p,12,(uint32)file_size);
1577 SIVAL(p,16,(uint32)allocation_size);
1579 p += 22; /* p now points to the EA area. */
1581 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1582 name_list = ea_list_union(name_list, file_list, &ea_len);
1584 /* We need to determine if this entry will fit in the space available. */
1585 /* Max string size is 255 bytes. */
1586 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1587 /* Move the dirptr back to prev_dirpos */
1588 dptr_SeekDir(conn->dirptr, prev_dirpos);
1589 *out_of_space = True;
1590 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1591 return False; /* Not finished - just out of space */
1594 /* Push the ea_data followed by the name. */
1595 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1597 len = srvstr_push(base_data, flags2,
1598 p + 1, fname, PTR_DIFF(end_data, p+1),
1599 STR_TERMINATE | STR_NOALIGN);
1600 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1613 SCVAL(nameptr,0,len);
1615 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1619 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1620 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1621 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1623 SIVAL(p,0,reskey); p += 4;
1624 put_long_date_timespec(p,create_date_ts); p += 8;
1625 put_long_date_timespec(p,adate_ts); p += 8;
1626 put_long_date_timespec(p,mdate_ts); p += 8;
1627 put_long_date_timespec(p,mdate_ts); p += 8;
1628 SOFF_T(p,0,file_size); p += 8;
1629 SOFF_T(p,0,allocation_size); p += 8;
1630 SIVAL(p,0,nt_extmode); p += 4;
1631 q = p; p += 4; /* q is placeholder for name length. */
1633 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1634 SIVAL(p,0,ea_size); /* Extended attributes */
1637 /* Clear the short name buffer. This is
1638 * IMPORTANT as not doing so will trigger
1639 * a Win2k client bug. JRA.
1641 if (!was_8_3 && check_mangled_names) {
1642 if (!name_to_8_3(fname,mangled_name,True,
1644 /* Error - mangle failed ! */
1645 memset(mangled_name,'\0',12);
1647 mangled_name[12] = 0;
1648 len = srvstr_push(base_data, flags2,
1649 p+2, mangled_name, 24,
1650 STR_UPPER|STR_UNICODE);
1652 memset(p + 2 + len,'\0',24 - len);
1659 len = srvstr_push(base_data, flags2, p,
1660 fname, PTR_DIFF(end_data, p),
1661 STR_TERMINATE_ASCII);
1664 SIVAL(p,0,0); /* Ensure any padding is null. */
1665 len = PTR_DIFF(p, pdata);
1666 len = (len + 3) & ~3;
1671 case SMB_FIND_FILE_DIRECTORY_INFO:
1672 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1674 SIVAL(p,0,reskey); p += 4;
1675 put_long_date_timespec(p,create_date_ts); p += 8;
1676 put_long_date_timespec(p,adate_ts); p += 8;
1677 put_long_date_timespec(p,mdate_ts); p += 8;
1678 put_long_date_timespec(p,mdate_ts); p += 8;
1679 SOFF_T(p,0,file_size); p += 8;
1680 SOFF_T(p,0,allocation_size); p += 8;
1681 SIVAL(p,0,nt_extmode); p += 4;
1682 len = srvstr_push(base_data, flags2,
1683 p + 4, fname, PTR_DIFF(end_data, p+4),
1684 STR_TERMINATE_ASCII);
1687 SIVAL(p,0,0); /* Ensure any padding is null. */
1688 len = PTR_DIFF(p, pdata);
1689 len = (len + 3) & ~3;
1694 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1695 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1697 SIVAL(p,0,reskey); p += 4;
1698 put_long_date_timespec(p,create_date_ts); p += 8;
1699 put_long_date_timespec(p,adate_ts); p += 8;
1700 put_long_date_timespec(p,mdate_ts); p += 8;
1701 put_long_date_timespec(p,mdate_ts); p += 8;
1702 SOFF_T(p,0,file_size); p += 8;
1703 SOFF_T(p,0,allocation_size); p += 8;
1704 SIVAL(p,0,nt_extmode); p += 4;
1705 q = p; p += 4; /* q is placeholder for name length. */
1707 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1708 SIVAL(p,0,ea_size); /* Extended attributes */
1711 len = srvstr_push(base_data, flags2, p,
1712 fname, PTR_DIFF(end_data, p),
1713 STR_TERMINATE_ASCII);
1717 SIVAL(p,0,0); /* Ensure any padding is null. */
1718 len = PTR_DIFF(p, pdata);
1719 len = (len + 3) & ~3;
1724 case SMB_FIND_FILE_NAMES_INFO:
1725 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1727 SIVAL(p,0,reskey); p += 4;
1729 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1730 acl on a dir (tridge) */
1731 len = srvstr_push(base_data, flags2, p,
1732 fname, PTR_DIFF(end_data, p),
1733 STR_TERMINATE_ASCII);
1736 SIVAL(p,0,0); /* Ensure any padding is null. */
1737 len = PTR_DIFF(p, pdata);
1738 len = (len + 3) & ~3;
1743 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1744 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1746 SIVAL(p,0,reskey); p += 4;
1747 put_long_date_timespec(p,create_date_ts); p += 8;
1748 put_long_date_timespec(p,adate_ts); p += 8;
1749 put_long_date_timespec(p,mdate_ts); p += 8;
1750 put_long_date_timespec(p,mdate_ts); p += 8;
1751 SOFF_T(p,0,file_size); p += 8;
1752 SOFF_T(p,0,allocation_size); p += 8;
1753 SIVAL(p,0,nt_extmode); p += 4;
1754 q = p; p += 4; /* q is placeholder for name length. */
1756 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1757 SIVAL(p,0,ea_size); /* Extended attributes */
1760 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1761 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1762 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1763 len = srvstr_push(base_data, flags2, p,
1764 fname, PTR_DIFF(end_data, p),
1765 STR_TERMINATE_ASCII);
1768 SIVAL(p,0,0); /* Ensure any padding is null. */
1769 len = PTR_DIFF(p, pdata);
1770 len = (len + 3) & ~3;
1775 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1776 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1777 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1779 SIVAL(p,0,reskey); p += 4;
1780 put_long_date_timespec(p,create_date_ts); p += 8;
1781 put_long_date_timespec(p,adate_ts); p += 8;
1782 put_long_date_timespec(p,mdate_ts); p += 8;
1783 put_long_date_timespec(p,mdate_ts); p += 8;
1784 SOFF_T(p,0,file_size); p += 8;
1785 SOFF_T(p,0,allocation_size); p += 8;
1786 SIVAL(p,0,nt_extmode); p += 4;
1787 q = p; p += 4; /* q is placeholder for name length */
1789 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1790 SIVAL(p,0,ea_size); /* Extended attributes */
1793 /* Clear the short name buffer. This is
1794 * IMPORTANT as not doing so will trigger
1795 * a Win2k client bug. JRA.
1797 if (!was_8_3 && check_mangled_names) {
1798 if (!name_to_8_3(fname,mangled_name,True,
1800 /* Error - mangle failed ! */
1801 memset(mangled_name,'\0',12);
1803 mangled_name[12] = 0;
1804 len = srvstr_push(base_data, flags2,
1805 p+2, mangled_name, 24,
1806 STR_UPPER|STR_UNICODE);
1809 memset(p + 2 + len,'\0',24 - len);
1816 SSVAL(p,0,0); p += 2; /* Reserved ? */
1817 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1818 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1819 len = srvstr_push(base_data, flags2, p,
1820 fname, PTR_DIFF(end_data, p),
1821 STR_TERMINATE_ASCII);
1824 SIVAL(p,0,0); /* Ensure any padding is null. */
1825 len = PTR_DIFF(p, pdata);
1826 len = (len + 3) & ~3;
1831 /* CIFS UNIX Extension. */
1833 case SMB_FIND_FILE_UNIX:
1834 case SMB_FIND_FILE_UNIX_INFO2:
1836 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1838 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1840 if (info_level == SMB_FIND_FILE_UNIX) {
1841 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1842 p = store_file_unix_basic(conn, p,
1844 len = srvstr_push(base_data, flags2, p,
1845 fname, PTR_DIFF(end_data, p),
1848 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1849 p = store_file_unix_basic_info2(conn, p,
1853 len = srvstr_push(base_data, flags2, p, fname,
1854 PTR_DIFF(end_data, p), 0);
1855 SIVAL(nameptr, 0, len);
1859 SIVAL(p,0,0); /* Ensure any padding is null. */
1861 len = PTR_DIFF(p, pdata);
1862 len = (len + 3) & ~3;
1863 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1865 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1875 if (PTR_DIFF(p,pdata) > space_remaining) {
1876 /* Move the dirptr back to prev_dirpos */
1877 dptr_SeekDir(conn->dirptr, prev_dirpos);
1878 *out_of_space = True;
1879 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1880 return False; /* Not finished - just out of space */
1883 /* Setup the last entry pointer, as an offset from base_data */
1884 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1885 /* Advance the data pointer to the next slot */
1891 /****************************************************************************
1892 Reply to a TRANS2_FINDFIRST.
1893 ****************************************************************************/
1895 static void call_trans2findfirst(connection_struct *conn,
1896 struct smb_request *req,
1897 char **pparams, int total_params,
1898 char **ppdata, int total_data,
1899 unsigned int max_data_bytes)
1901 /* We must be careful here that we don't return more than the
1902 allowed number of data bytes. If this means returning fewer than
1903 maxentries then so be it. We assume that the redirector has
1904 enough room for the fixed number of parameter bytes it has
1906 struct smb_filename *smb_dname = NULL;
1907 char *params = *pparams;
1908 char *pdata = *ppdata;
1912 uint16 findfirst_flags;
1913 bool close_after_first;
1915 bool requires_resume_key;
1917 char *directory = NULL;
1920 int last_entry_off=0;
1924 bool finished = False;
1925 bool dont_descend = False;
1926 bool out_of_space = False;
1927 int space_remaining;
1928 bool mask_contains_wcard = False;
1929 struct ea_list *ea_list = NULL;
1930 NTSTATUS ntstatus = NT_STATUS_OK;
1931 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1932 TALLOC_CTX *ctx = talloc_tos();
1934 if (total_params < 13) {
1935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1939 dirtype = SVAL(params,0);
1940 maxentries = SVAL(params,2);
1941 findfirst_flags = SVAL(params,4);
1942 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1943 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1944 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1945 info_level = SVAL(params,6);
1947 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1948 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1949 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1950 info_level, max_data_bytes));
1953 /* W2K3 seems to treat zero as 1. */
1957 switch (info_level) {
1958 case SMB_FIND_INFO_STANDARD:
1959 case SMB_FIND_EA_SIZE:
1960 case SMB_FIND_EA_LIST:
1961 case SMB_FIND_FILE_DIRECTORY_INFO:
1962 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1963 case SMB_FIND_FILE_NAMES_INFO:
1964 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1965 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1966 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1968 case SMB_FIND_FILE_UNIX:
1969 case SMB_FIND_FILE_UNIX_INFO2:
1970 /* Always use filesystem for UNIX mtime query. */
1971 ask_sharemode = false;
1972 if (!lp_unix_extensions()) {
1973 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1978 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1982 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1983 params+12, total_params - 12,
1984 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1985 if (!NT_STATUS_IS_OK(ntstatus)) {
1986 reply_nterror(req, ntstatus);
1990 ntstatus = resolve_dfspath_wcard(ctx, conn,
1991 req->flags2 & FLAGS2_DFS_PATHNAMES,
1994 &mask_contains_wcard);
1995 if (!NT_STATUS_IS_OK(ntstatus)) {
1996 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1997 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1998 ERRSRV, ERRbadpath);
2001 reply_nterror(req, ntstatus);
2005 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2006 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2007 if (!NT_STATUS_IS_OK(ntstatus)) {
2008 reply_nterror(req, ntstatus);
2012 mask = smb_dname->original_lcomp;
2014 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2015 TALLOC_FREE(smb_dname);
2016 if (!NT_STATUS_IS_OK(ntstatus)) {
2017 reply_nterror(req, ntstatus);
2021 ntstatus = check_name(conn, directory);
2022 if (!NT_STATUS_IS_OK(ntstatus)) {
2023 reply_nterror(req, ntstatus);
2027 p = strrchr_m(directory,'/');
2029 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2030 if((directory[0] == '.') && (directory[1] == '\0')) {
2031 mask = talloc_strdup(ctx,"*");
2033 reply_nterror(req, NT_STATUS_NO_MEMORY);
2036 mask_contains_wcard = True;
2038 directory = talloc_strdup(talloc_tos(), "./");
2040 reply_nterror(req, NT_STATUS_NO_MEMORY);
2047 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2049 if (info_level == SMB_FIND_EA_LIST) {
2052 if (total_data < 4) {
2053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2057 ea_size = IVAL(pdata,0);
2058 if (ea_size != total_data) {
2059 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2060 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2061 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2065 if (!lp_ea_support(SNUM(conn))) {
2066 reply_doserror(req, ERRDOS, ERReasnotsupported);
2070 /* Pull out the list of names. */
2071 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2073 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2078 *ppdata = (char *)SMB_REALLOC(
2079 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2080 if(*ppdata == NULL ) {
2081 reply_nterror(req, NT_STATUS_NO_MEMORY);
2085 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2087 /* Realloc the params space */
2088 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2089 if (*pparams == NULL) {
2090 reply_nterror(req, NT_STATUS_NO_MEMORY);
2095 /* Save the wildcard match and attribs we are using on this directory -
2096 needed as lanman2 assumes these are being saved between calls */
2098 ntstatus = dptr_create(conn,
2104 mask_contains_wcard,
2108 if (!NT_STATUS_IS_OK(ntstatus)) {
2109 reply_nterror(req, ntstatus);
2113 dptr_num = dptr_dnum(conn->dirptr);
2114 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2116 /* Initialize per TRANS2_FIND_FIRST operation data */
2117 dptr_init_search_op(conn->dirptr);
2119 /* We don't need to check for VOL here as this is returned by
2120 a different TRANS2 call. */
2122 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2123 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2124 dont_descend = True;
2127 space_remaining = max_data_bytes;
2128 out_of_space = False;
2130 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2131 bool got_exact_match = False;
2133 /* this is a heuristic to avoid seeking the dirptr except when
2134 absolutely necessary. It allows for a filename of about 40 chars */
2135 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2136 out_of_space = True;
2139 finished = !get_lanman2_dir_entry(ctx,
2142 mask,dirtype,info_level,
2143 requires_resume_key,dont_descend,
2146 space_remaining, &out_of_space,
2148 &last_entry_off, ea_list);
2151 if (finished && out_of_space)
2154 if (!finished && !out_of_space)
2158 * As an optimisation if we know we aren't looking
2159 * for a wildcard name (ie. the name matches the wildcard exactly)
2160 * then we can finish on any (first) match.
2161 * This speeds up large directory searches. JRA.
2167 /* Ensure space_remaining never goes -ve. */
2168 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2169 space_remaining = 0;
2170 out_of_space = true;
2172 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2176 /* Check if we can close the dirptr */
2177 if(close_after_first || (finished && close_if_end)) {
2178 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2179 dptr_close(&dptr_num);
2183 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2184 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2185 * the protocol level is less than NT1. Tested with smbclient. JRA.
2186 * This should fix the OS/2 client bug #2335.
2189 if(numentries == 0) {
2190 dptr_close(&dptr_num);
2191 if (Protocol < PROTOCOL_NT1) {
2192 reply_doserror(req, ERRDOS, ERRnofiles);
2195 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2196 ERRDOS, ERRbadfile);
2201 /* At this point pdata points to numentries directory entries. */
2203 /* Set up the return parameter block */
2204 SSVAL(params,0,dptr_num);
2205 SSVAL(params,2,numentries);
2206 SSVAL(params,4,finished);
2207 SSVAL(params,6,0); /* Never an EA error */
2208 SSVAL(params,8,last_entry_off);
2210 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2213 if ((! *directory) && dptr_path(dptr_num)) {
2214 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2216 reply_nterror(req, NT_STATUS_NO_MEMORY);
2220 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2221 smb_fn_name(req->cmd),
2222 mask, directory, dirtype, numentries ) );
2225 * Force a name mangle here to ensure that the
2226 * mask as an 8.3 name is top of the mangled cache.
2227 * The reasons for this are subtle. Don't remove
2228 * this code unless you know what you are doing
2229 * (see PR#13758). JRA.
2232 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2233 char mangled_name[13];
2234 name_to_8_3(mask, mangled_name, True, conn->params);
2240 /****************************************************************************
2241 Reply to a TRANS2_FINDNEXT.
2242 ****************************************************************************/
2244 static void call_trans2findnext(connection_struct *conn,
2245 struct smb_request *req,
2246 char **pparams, int total_params,
2247 char **ppdata, int total_data,
2248 unsigned int max_data_bytes)
2250 /* We must be careful here that we don't return more than the
2251 allowed number of data bytes. If this means returning fewer than
2252 maxentries then so be it. We assume that the redirector has
2253 enough room for the fixed number of parameter bytes it has
2255 char *params = *pparams;
2256 char *pdata = *ppdata;
2262 uint16 findnext_flags;
2263 bool close_after_request;
2265 bool requires_resume_key;
2267 bool mask_contains_wcard = False;
2268 char *resume_name = NULL;
2269 const char *mask = NULL;
2270 const char *directory = NULL;
2274 int i, last_entry_off=0;
2275 bool finished = False;
2276 bool dont_descend = False;
2277 bool out_of_space = False;
2278 int space_remaining;
2279 struct ea_list *ea_list = NULL;
2280 NTSTATUS ntstatus = NT_STATUS_OK;
2281 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2282 TALLOC_CTX *ctx = talloc_tos();
2284 if (total_params < 13) {
2285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2289 dptr_num = SVAL(params,0);
2290 maxentries = SVAL(params,2);
2291 info_level = SVAL(params,4);
2292 resume_key = IVAL(params,6);
2293 findnext_flags = SVAL(params,10);
2294 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2295 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2296 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2297 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2299 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2301 total_params - 12, STR_TERMINATE, &ntstatus,
2302 &mask_contains_wcard);
2303 if (!NT_STATUS_IS_OK(ntstatus)) {
2304 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2305 complain (it thinks we're asking for the directory above the shared
2306 path or an invalid name). Catch this as the resume name is only compared, never used in
2307 a file access. JRA. */
2308 srvstr_pull_talloc(ctx, params, req->flags2,
2309 &resume_name, params+12,
2313 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2314 reply_nterror(req, ntstatus);
2319 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2320 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2321 resume_key = %d resume name = %s continue=%d level = %d\n",
2322 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2323 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2326 /* W2K3 seems to treat zero as 1. */
2330 switch (info_level) {
2331 case SMB_FIND_INFO_STANDARD:
2332 case SMB_FIND_EA_SIZE:
2333 case SMB_FIND_EA_LIST:
2334 case SMB_FIND_FILE_DIRECTORY_INFO:
2335 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2336 case SMB_FIND_FILE_NAMES_INFO:
2337 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2338 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2339 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2341 case SMB_FIND_FILE_UNIX:
2342 case SMB_FIND_FILE_UNIX_INFO2:
2343 /* Always use filesystem for UNIX mtime query. */
2344 ask_sharemode = false;
2345 if (!lp_unix_extensions()) {
2346 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2351 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2355 if (info_level == SMB_FIND_EA_LIST) {
2358 if (total_data < 4) {
2359 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2363 ea_size = IVAL(pdata,0);
2364 if (ea_size != total_data) {
2365 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2366 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2367 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2371 if (!lp_ea_support(SNUM(conn))) {
2372 reply_doserror(req, ERRDOS, ERReasnotsupported);
2376 /* Pull out the list of names. */
2377 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2384 *ppdata = (char *)SMB_REALLOC(
2385 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2386 if(*ppdata == NULL) {
2387 reply_nterror(req, NT_STATUS_NO_MEMORY);
2392 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2394 /* Realloc the params space */
2395 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2396 if(*pparams == NULL ) {
2397 reply_nterror(req, NT_STATUS_NO_MEMORY);
2403 /* Check that the dptr is valid */
2404 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2405 reply_doserror(req, ERRDOS, ERRnofiles);
2409 string_set(&conn->dirpath,dptr_path(dptr_num));
2411 /* Get the wildcard mask from the dptr */
2412 if((p = dptr_wcard(dptr_num))== NULL) {
2413 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2414 reply_doserror(req, ERRDOS, ERRnofiles);
2419 directory = conn->dirpath;
2421 /* Get the attr mask from the dptr */
2422 dirtype = dptr_attr(dptr_num);
2424 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2425 dptr_num, mask, dirtype,
2427 dptr_TellDir(conn->dirptr)));
2429 /* Initialize per TRANS2_FIND_NEXT operation data */
2430 dptr_init_search_op(conn->dirptr);
2432 /* We don't need to check for VOL here as this is returned by
2433 a different TRANS2 call. */
2435 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2436 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2437 dont_descend = True;
2440 space_remaining = max_data_bytes;
2441 out_of_space = False;
2444 * Seek to the correct position. We no longer use the resume key but
2445 * depend on the last file name instead.
2448 if(*resume_name && !continue_bit) {
2451 long current_pos = 0;
2453 * Remember, name_to_8_3 is called by
2454 * get_lanman2_dir_entry(), so the resume name
2455 * could be mangled. Ensure we check the unmangled name.
2458 if (mangle_is_mangled(resume_name, conn->params)) {
2459 char *new_resume_name = NULL;
2460 mangle_lookup_name_from_8_3(ctx,
2464 if (new_resume_name) {
2465 resume_name = new_resume_name;
2470 * Fix for NT redirector problem triggered by resume key indexes
2471 * changing between directory scans. We now return a resume key of 0
2472 * and instead look for the filename to continue from (also given
2473 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2474 * findfirst/findnext (as is usual) then the directory pointer
2475 * should already be at the correct place.
2478 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2479 } /* end if resume_name && !continue_bit */
2481 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2482 bool got_exact_match = False;
2484 /* this is a heuristic to avoid seeking the dirptr except when
2485 absolutely necessary. It allows for a filename of about 40 chars */
2486 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2487 out_of_space = True;
2490 finished = !get_lanman2_dir_entry(ctx,
2493 mask,dirtype,info_level,
2494 requires_resume_key,dont_descend,
2497 space_remaining, &out_of_space,
2499 &last_entry_off, ea_list);
2502 if (finished && out_of_space)
2505 if (!finished && !out_of_space)
2509 * As an optimisation if we know we aren't looking
2510 * for a wildcard name (ie. the name matches the wildcard exactly)
2511 * then we can finish on any (first) match.
2512 * This speeds up large directory searches. JRA.
2518 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2521 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2522 smb_fn_name(req->cmd),
2523 mask, directory, dirtype, numentries ) );
2525 /* Check if we can close the dirptr */
2526 if(close_after_request || (finished && close_if_end)) {
2527 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2528 dptr_close(&dptr_num); /* This frees up the saved mask */
2531 /* Set up the return parameter block */
2532 SSVAL(params,0,numentries);
2533 SSVAL(params,2,finished);
2534 SSVAL(params,4,0); /* Never an EA error */
2535 SSVAL(params,6,last_entry_off);
2537 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2543 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2545 E_md4hash(lp_servicename(SNUM(conn)),objid);
2549 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2551 SMB_ASSERT(extended_info != NULL);
2553 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2554 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2555 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2556 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2557 #ifdef SAMBA_VERSION_REVISION
2558 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2560 extended_info->samba_subversion = 0;
2561 #ifdef SAMBA_VERSION_RC_RELEASE
2562 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2564 #ifdef SAMBA_VERSION_PRE_RELEASE
2565 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2568 #ifdef SAMBA_VERSION_VENDOR_PATCH
2569 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2571 extended_info->samba_gitcommitdate = 0;
2572 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2573 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2576 memset(extended_info->samba_version_string, 0,
2577 sizeof(extended_info->samba_version_string));
2579 snprintf (extended_info->samba_version_string,
2580 sizeof(extended_info->samba_version_string),
2581 "%s", samba_version_string());
2584 /****************************************************************************
2585 Reply to a TRANS2_QFSINFO (query filesystem info).
2586 ****************************************************************************/
2588 static void call_trans2qfsinfo(connection_struct *conn,
2589 struct smb_request *req,
2590 char **pparams, int total_params,
2591 char **ppdata, int total_data,
2592 unsigned int max_data_bytes)
2594 char *pdata, *end_data;
2595 char *params = *pparams;
2599 const char *vname = volume_label(SNUM(conn));
2600 int snum = SNUM(conn);
2601 char *fstype = lp_fstype(SNUM(conn));
2602 uint32 additional_flags = 0;
2604 if (total_params < 2) {
2605 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2609 info_level = SVAL(params,0);
2612 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2613 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2614 "info level (0x%x) on IPC$.\n",
2615 (unsigned int)info_level));
2616 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2621 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2622 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2623 DEBUG(0,("call_trans2qfsinfo: encryption required "
2624 "and info level 0x%x sent.\n",
2625 (unsigned int)info_level));
2626 exit_server_cleanly("encryption required "
2632 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2634 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2635 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2636 reply_doserror(req, ERRSRV, ERRinvdevice);
2640 *ppdata = (char *)SMB_REALLOC(
2641 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2642 if (*ppdata == NULL ) {
2643 reply_nterror(req, NT_STATUS_NO_MEMORY);
2648 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2649 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2651 switch (info_level) {
2652 case SMB_INFO_ALLOCATION:
2654 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2656 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2657 reply_unixerror(req, ERRHRD, ERRgeneral);
2661 block_size = lp_block_size(snum);
2662 if (bsize < block_size) {
2663 uint64_t factor = block_size/bsize;
2668 if (bsize > block_size) {
2669 uint64_t factor = bsize/block_size;
2674 bytes_per_sector = 512;
2675 sectors_per_unit = bsize/bytes_per_sector;
2677 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2678 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2679 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2681 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2682 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2683 SIVAL(pdata,l1_cUnit,dsize);
2684 SIVAL(pdata,l1_cUnitAvail,dfree);
2685 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2689 case SMB_INFO_VOLUME:
2690 /* Return volume name */
2692 * Add volume serial number - hash of a combination of
2693 * the called hostname and the service name.
2695 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2697 * Win2k3 and previous mess this up by sending a name length
2698 * one byte short. I believe only older clients (OS/2 Win9x) use
2699 * this call so try fixing this by adding a terminating null to
2700 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2704 pdata+l2_vol_szVolLabel, vname,
2705 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2706 STR_NOALIGN|STR_TERMINATE);
2707 SCVAL(pdata,l2_vol_cch,len);
2708 data_len = l2_vol_szVolLabel + len;
2709 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2710 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2714 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2715 case SMB_FS_ATTRIBUTE_INFORMATION:
2717 additional_flags = 0;
2718 #if defined(HAVE_SYS_QUOTAS)
2719 additional_flags |= FILE_VOLUME_QUOTAS;
2722 if(lp_nt_acl_support(SNUM(conn))) {
2723 additional_flags |= FILE_PERSISTENT_ACLS;
2726 /* Capabilities are filled in at connection time through STATVFS call */
2727 additional_flags |= conn->fs_capabilities;
2729 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2730 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2731 additional_flags); /* FS ATTRIBUTES */
2733 SIVAL(pdata,4,255); /* Max filename component length */
2734 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2735 and will think we can't do long filenames */
2736 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2737 PTR_DIFF(end_data, pdata+12),
2740 data_len = 12 + len;
2743 case SMB_QUERY_FS_LABEL_INFO:
2744 case SMB_FS_LABEL_INFORMATION:
2745 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2746 PTR_DIFF(end_data, pdata+4), 0);
2751 case SMB_QUERY_FS_VOLUME_INFO:
2752 case SMB_FS_VOLUME_INFORMATION:
2755 * Add volume serial number - hash of a combination of
2756 * the called hostname and the service name.
2758 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2759 (str_checksum(get_local_machine_name())<<16));
2761 /* Max label len is 32 characters. */
2762 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2763 PTR_DIFF(end_data, pdata+18),
2765 SIVAL(pdata,12,len);
2768 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2769 (int)strlen(vname),vname, lp_servicename(snum)));
2772 case SMB_QUERY_FS_SIZE_INFO:
2773 case SMB_FS_SIZE_INFORMATION:
2775 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2777 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2778 reply_unixerror(req, ERRHRD, ERRgeneral);
2781 block_size = lp_block_size(snum);
2782 if (bsize < block_size) {
2783 uint64_t factor = block_size/bsize;
2788 if (bsize > block_size) {
2789 uint64_t factor = bsize/block_size;
2794 bytes_per_sector = 512;
2795 sectors_per_unit = bsize/bytes_per_sector;
2796 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2797 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2798 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2799 SBIG_UINT(pdata,0,dsize);
2800 SBIG_UINT(pdata,8,dfree);
2801 SIVAL(pdata,16,sectors_per_unit);
2802 SIVAL(pdata,20,bytes_per_sector);
2806 case SMB_FS_FULL_SIZE_INFORMATION:
2808 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2810 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2811 reply_unixerror(req, ERRHRD, ERRgeneral);
2814 block_size = lp_block_size(snum);
2815 if (bsize < block_size) {
2816 uint64_t factor = block_size/bsize;
2821 if (bsize > block_size) {
2822 uint64_t factor = bsize/block_size;
2827 bytes_per_sector = 512;
2828 sectors_per_unit = bsize/bytes_per_sector;
2829 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2830 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2831 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2832 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2833 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2834 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2835 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2836 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2840 case SMB_QUERY_FS_DEVICE_INFO:
2841 case SMB_FS_DEVICE_INFORMATION:
2843 SIVAL(pdata,0,0); /* dev type */
2844 SIVAL(pdata,4,0); /* characteristics */
2847 #ifdef HAVE_SYS_QUOTAS
2848 case SMB_FS_QUOTA_INFORMATION:
2850 * what we have to send --metze:
2852 * Unknown1: 24 NULL bytes
2853 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2854 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2855 * Quota Flags: 2 byte :
2856 * Unknown3: 6 NULL bytes
2860 * details for Quota Flags:
2862 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2863 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2864 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2865 * 0x0001 Enable Quotas: enable quota for this fs
2869 /* we need to fake up a fsp here,
2870 * because its not send in this call
2873 SMB_NTQUOTA_STRUCT quotas;
2876 ZERO_STRUCT(quotas);
2882 if (conn->server_info->utok.uid != 0) {
2883 DEBUG(0,("set_user_quota: access_denied "
2884 "service [%s] user [%s]\n",
2885 lp_servicename(SNUM(conn)),
2886 conn->server_info->unix_name));
2887 reply_doserror(req, ERRDOS, ERRnoaccess);
2891 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2892 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2893 reply_doserror(req, ERRSRV, ERRerror);
2899 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2901 /* Unknown1 24 NULL bytes*/
2902 SBIG_UINT(pdata,0,(uint64_t)0);
2903 SBIG_UINT(pdata,8,(uint64_t)0);
2904 SBIG_UINT(pdata,16,(uint64_t)0);
2906 /* Default Soft Quota 8 bytes */
2907 SBIG_UINT(pdata,24,quotas.softlim);
2909 /* Default Hard Quota 8 bytes */
2910 SBIG_UINT(pdata,32,quotas.hardlim);
2912 /* Quota flag 2 bytes */
2913 SSVAL(pdata,40,quotas.qflags);
2915 /* Unknown3 6 NULL bytes */
2921 #endif /* HAVE_SYS_QUOTAS */
2922 case SMB_FS_OBJECTID_INFORMATION:
2924 unsigned char objid[16];
2925 struct smb_extended_info extended_info;
2926 memcpy(pdata,create_volume_objectid(conn, objid),16);
2927 samba_extended_info_version (&extended_info);
2928 SIVAL(pdata,16,extended_info.samba_magic);
2929 SIVAL(pdata,20,extended_info.samba_version);
2930 SIVAL(pdata,24,extended_info.samba_subversion);
2931 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2932 memcpy(pdata+36,extended_info.samba_version_string,28);
2938 * Query the version and capabilities of the CIFS UNIX extensions
2942 case SMB_QUERY_CIFS_UNIX_INFO:
2944 bool large_write = lp_min_receive_file_size() &&
2945 !srv_is_signing_active(smbd_server_conn);
2946 bool large_read = !srv_is_signing_active(smbd_server_conn);
2947 int encrypt_caps = 0;
2949 if (!lp_unix_extensions()) {
2950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2954 switch (conn->encrypt_level) {
2960 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2963 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2964 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2965 large_write = false;
2971 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2972 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2974 /* We have POSIX ACLs, pathname, encryption,
2975 * large read/write, and locking capability. */
2977 SBIG_UINT(pdata,4,((uint64_t)(
2978 CIFS_UNIX_POSIX_ACLS_CAP|
2979 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2980 CIFS_UNIX_FCNTL_LOCKS_CAP|
2981 CIFS_UNIX_EXTATTR_CAP|
2982 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2984 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2986 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2990 case SMB_QUERY_POSIX_FS_INFO:
2993 vfs_statvfs_struct svfs;
2995 if (!lp_unix_extensions()) {
2996 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3000 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3004 SIVAL(pdata,0,svfs.OptimalTransferSize);
3005 SIVAL(pdata,4,svfs.BlockSize);
3006 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3007 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3008 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3009 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3010 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3011 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3012 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3014 } else if (rc == EOPNOTSUPP) {
3015 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3017 #endif /* EOPNOTSUPP */
3019 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3020 reply_doserror(req, ERRSRV, ERRerror);
3026 case SMB_QUERY_POSIX_WHOAMI:
3032 if (!lp_unix_extensions()) {
3033 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3037 if (max_data_bytes < 40) {
3038 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3042 /* We ARE guest if global_sid_Builtin_Guests is
3043 * in our list of SIDs.
3045 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3046 conn->server_info->ptok)) {
3047 flags |= SMB_WHOAMI_GUEST;
3050 /* We are NOT guest if global_sid_Authenticated_Users
3051 * is in our list of SIDs.
3053 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3054 conn->server_info->ptok)) {
3055 flags &= ~SMB_WHOAMI_GUEST;
3058 /* NOTE: 8 bytes for UID/GID, irrespective of native
3059 * platform size. This matches
3060 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3062 data_len = 4 /* flags */
3069 + 4 /* pad/reserved */
3070 + (conn->server_info->utok.ngroups * 8)
3072 + (conn->server_info->ptok->num_sids *
3076 SIVAL(pdata, 0, flags);
3077 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3079 (uint64_t)conn->server_info->utok.uid);
3080 SBIG_UINT(pdata, 16,
3081 (uint64_t)conn->server_info->utok.gid);
3084 if (data_len >= max_data_bytes) {
3085 /* Potential overflow, skip the GIDs and SIDs. */
3087 SIVAL(pdata, 24, 0); /* num_groups */
3088 SIVAL(pdata, 28, 0); /* num_sids */
3089 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3090 SIVAL(pdata, 36, 0); /* reserved */
3096 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3097 SIVAL(pdata, 28, conn->server_info->num_sids);
3099 /* We walk the SID list twice, but this call is fairly
3100 * infrequent, and I don't expect that it's performance
3101 * sensitive -- jpeach
3103 for (i = 0, sid_bytes = 0;
3104 i < conn->server_info->ptok->num_sids; ++i) {
3105 sid_bytes += ndr_size_dom_sid(
3106 &conn->server_info->ptok->user_sids[i],
3111 /* SID list byte count */
3112 SIVAL(pdata, 32, sid_bytes);
3114 /* 4 bytes pad/reserved - must be zero */
3115 SIVAL(pdata, 36, 0);
3119 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3120 SBIG_UINT(pdata, data_len,
3121 (uint64_t)conn->server_info->utok.groups[i]);
3127 i < conn->server_info->ptok->num_sids; ++i) {
3128 int sid_len = ndr_size_dom_sid(
3129 &conn->server_info->ptok->user_sids[i],
3133 sid_linearize(pdata + data_len, sid_len,
3134 &conn->server_info->ptok->user_sids[i]);
3135 data_len += sid_len;
3141 case SMB_MAC_QUERY_FS_INFO:
3143 * Thursby MAC extension... ONLY on NTFS filesystems
3144 * once we do streams then we don't need this
3146 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3148 SIVAL(pdata,84,0x100); /* Don't support mac... */
3153 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3158 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3161 DEBUG( 4, ( "%s info_level = %d\n",
3162 smb_fn_name(req->cmd), info_level) );
3167 /****************************************************************************
3168 Reply to a TRANS2_SETFSINFO (set filesystem info).
3169 ****************************************************************************/
3171 static void call_trans2setfsinfo(connection_struct *conn,
3172 struct smb_request *req,
3173 char **pparams, int total_params,
3174 char **ppdata, int total_data,
3175 unsigned int max_data_bytes)
3177 char *pdata = *ppdata;
3178 char *params = *pparams;
3181 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3184 if (total_params < 4) {
3185 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3191 info_level = SVAL(params,2);
3194 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3195 info_level != SMB_SET_CIFS_UNIX_INFO) {
3196 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3197 "info level (0x%x) on IPC$.\n",
3198 (unsigned int)info_level));
3199 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3204 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3205 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3206 DEBUG(0,("call_trans2setfsinfo: encryption required "
3207 "and info level 0x%x sent.\n",
3208 (unsigned int)info_level));
3209 exit_server_cleanly("encryption required "
3215 switch(info_level) {
3216 case SMB_SET_CIFS_UNIX_INFO:
3218 uint16 client_unix_major;
3219 uint16 client_unix_minor;
3220 uint32 client_unix_cap_low;
3221 uint32 client_unix_cap_high;
3223 if (!lp_unix_extensions()) {
3225 NT_STATUS_INVALID_LEVEL);
3229 /* There should be 12 bytes of capabilities set. */
3230 if (total_data < 8) {
3233 NT_STATUS_INVALID_PARAMETER);
3236 client_unix_major = SVAL(pdata,0);
3237 client_unix_minor = SVAL(pdata,2);
3238 client_unix_cap_low = IVAL(pdata,4);
3239 client_unix_cap_high = IVAL(pdata,8);
3240 /* Just print these values for now. */
3241 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3242 cap_low = 0x%x, cap_high = 0x%x\n",
3243 (unsigned int)client_unix_major,
3244 (unsigned int)client_unix_minor,
3245 (unsigned int)client_unix_cap_low,
3246 (unsigned int)client_unix_cap_high ));
3248 /* Here is where we must switch to posix pathname processing... */
3249 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3250 lp_set_posix_pathnames();
3251 mangle_change_to_posix();
3254 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3255 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3256 /* Client that knows how to do posix locks,
3257 * but not posix open/mkdir operations. Set a
3258 * default type for read/write checks. */
3260 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3266 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3269 size_t param_len = 0;
3270 size_t data_len = total_data;
3272 if (!lp_unix_extensions()) {
3275 NT_STATUS_INVALID_LEVEL);
3279 if (lp_smb_encrypt(SNUM(conn)) == false) {
3282 NT_STATUS_NOT_SUPPORTED);
3286 DEBUG( 4,("call_trans2setfsinfo: "
3287 "request transport encryption.\n"));
3289 status = srv_request_encryption_setup(conn,
3290 (unsigned char **)ppdata,
3292 (unsigned char **)pparams,
3295 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3296 !NT_STATUS_IS_OK(status)) {
3297 reply_nterror(req, status);
3301 send_trans2_replies(conn, req,
3308 if (NT_STATUS_IS_OK(status)) {
3309 /* Server-side transport
3310 * encryption is now *on*. */
3311 status = srv_encryption_start(conn);
3312 if (!NT_STATUS_IS_OK(status)) {
3313 exit_server_cleanly(
3314 "Failure in setting "
3315 "up encrypted transport");
3321 case SMB_FS_QUOTA_INFORMATION:
3323 files_struct *fsp = NULL;
3324 SMB_NTQUOTA_STRUCT quotas;
3326 ZERO_STRUCT(quotas);
3329 if ((conn->server_info->utok.uid != 0)
3330 ||!CAN_WRITE(conn)) {
3331 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3332 lp_servicename(SNUM(conn)),
3333 conn->server_info->unix_name));
3334 reply_doserror(req, ERRSRV, ERRaccess);
3338 /* note: normaly there're 48 bytes,
3339 * but we didn't use the last 6 bytes for now
3342 fsp = file_fsp(req, SVAL(params,0));
3344 if (!check_fsp_ntquota_handle(conn, req,
3346 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3348 req, NT_STATUS_INVALID_HANDLE);
3352 if (total_data < 42) {
3353 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3357 NT_STATUS_INVALID_PARAMETER);
3361 /* unknown_1 24 NULL bytes in pdata*/
3363 /* the soft quotas 8 bytes (uint64_t)*/
3364 quotas.softlim = (uint64_t)IVAL(pdata,24);
3365 #ifdef LARGE_SMB_OFF_T
3366 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3367 #else /* LARGE_SMB_OFF_T */
3368 if ((IVAL(pdata,28) != 0)&&
3369 ((quotas.softlim != 0xFFFFFFFF)||
3370 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3371 /* more than 32 bits? */
3374 NT_STATUS_INVALID_PARAMETER);
3377 #endif /* LARGE_SMB_OFF_T */
3379 /* the hard quotas 8 bytes (uint64_t)*/
3380 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3381 #ifdef LARGE_SMB_OFF_T
3382 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3383 #else /* LARGE_SMB_OFF_T */
3384 if ((IVAL(pdata,36) != 0)&&
3385 ((quotas.hardlim != 0xFFFFFFFF)||
3386 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3387 /* more than 32 bits? */
3390 NT_STATUS_INVALID_PARAMETER);
3393 #endif /* LARGE_SMB_OFF_T */
3395 /* quota_flags 2 bytes **/
3396 quotas.qflags = SVAL(pdata,40);
3398 /* unknown_2 6 NULL bytes follow*/
3400 /* now set the quotas */
3401 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3402 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3403 reply_doserror(req, ERRSRV, ERRerror);
3410 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3412 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3418 * sending this reply works fine,
3419 * but I'm not sure it's the same
3420 * like windows do...
3423 reply_outbuf(req, 10, 0);
3426 #if defined(HAVE_POSIX_ACLS)
3427 /****************************************************************************
3428 Utility function to count the number of entries in a POSIX acl.
3429 ****************************************************************************/
3431 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3433 unsigned int ace_count = 0;
3434 int entry_id = SMB_ACL_FIRST_ENTRY;
3435 SMB_ACL_ENTRY_T entry;
3437 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3439 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3440 entry_id = SMB_ACL_NEXT_ENTRY;
3447 /****************************************************************************
3448 Utility function to marshall a POSIX acl into wire format.
3449 ****************************************************************************/
3451 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3453 int entry_id = SMB_ACL_FIRST_ENTRY;
3454 SMB_ACL_ENTRY_T entry;
3456 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3457 SMB_ACL_TAG_T tagtype;
3458 SMB_ACL_PERMSET_T permset;
3459 unsigned char perms = 0;
3460 unsigned int own_grp;
3463 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3464 entry_id = SMB_ACL_NEXT_ENTRY;
3467 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3468 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3472 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3473 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3477 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3478 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3479 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3481 SCVAL(pdata,1,perms);
3484 case SMB_ACL_USER_OBJ:
3485 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3486 own_grp = (unsigned int)pst->st_ex_uid;
3487 SIVAL(pdata,2,own_grp);
3492 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3494 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3497 own_grp = (unsigned int)*puid;
3498 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3499 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3500 SIVAL(pdata,2,own_grp);
3504 case SMB_ACL_GROUP_OBJ:
3505 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3506 own_grp = (unsigned int)pst->st_ex_gid;
3507 SIVAL(pdata,2,own_grp);
3512 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3514 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3517 own_grp = (unsigned int)*pgid;
3518 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3519 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3520 SIVAL(pdata,2,own_grp);
3525 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3526 SIVAL(pdata,2,0xFFFFFFFF);
3527 SIVAL(pdata,6,0xFFFFFFFF);
3530 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3531 SIVAL(pdata,2,0xFFFFFFFF);
3532 SIVAL(pdata,6,0xFFFFFFFF);
3535 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3538 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3545 /****************************************************************************
3546 Store the FILE_UNIX_BASIC info.
3547 ****************************************************************************/
3549 static char *store_file_unix_basic(connection_struct *conn,
3552 const SMB_STRUCT_STAT *psbuf)
3554 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3555 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3557 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3560 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3563 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3564 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3565 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3568 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3572 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3576 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3579 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3583 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3587 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3590 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3594 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3601 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3602 * the chflags(2) (or equivalent) flags.
3604 * XXX: this really should be behind the VFS interface. To do this, we would
3605 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3606 * Each VFS module could then implement its own mapping as appropriate for the
3607 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3609 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3613 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3617 { UF_IMMUTABLE, EXT_IMMUTABLE },
3621 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3625 { UF_HIDDEN, EXT_HIDDEN },
3628 /* Do not remove. We need to guarantee that this array has at least one
3629 * entry to build on HP-UX.
3635 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3636 uint32 *smb_fflags, uint32 *smb_fmask)
3640 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3641 *smb_fmask |= info2_flags_map[i].smb_fflag;
3642 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3643 *smb_fflags |= info2_flags_map[i].smb_fflag;
3648 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3649 const uint32 smb_fflags,
3650 const uint32 smb_fmask,
3653 uint32 max_fmask = 0;
3656 *stat_fflags = psbuf->st_ex_flags;
3658 /* For each flags requested in smb_fmask, check the state of the
3659 * corresponding flag in smb_fflags and set or clear the matching
3663 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3664 max_fmask |= info2_flags_map[i].smb_fflag;
3665 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3666 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3667 *stat_fflags |= info2_flags_map[i].stat_fflag;
3669 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3674 /* If smb_fmask is asking to set any bits that are not supported by
3675 * our flag mappings, we should fail.
3677 if ((smb_fmask & max_fmask) != smb_fmask) {
3685 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3686 * of file flags and birth (create) time.
3688 static char *store_file_unix_basic_info2(connection_struct *conn,
3691 const SMB_STRUCT_STAT *psbuf)
3693 uint32 file_flags = 0;
3694 uint32 flags_mask = 0;
3696 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3698 /* Create (birth) time 64 bit */
3699 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3702 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3703 SIVAL(pdata, 0, file_flags); /* flags */
3704 SIVAL(pdata, 4, flags_mask); /* mask */
3710 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3711 const struct stream_struct *streams,
3713 unsigned int max_data_bytes,
3714 unsigned int *data_size)
3717 unsigned int ofs = 0;
3719 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3720 unsigned int next_offset;
3722 smb_ucs2_t *namebuf;
3724 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3725 streams[i].name, &namelen) ||
3728 return NT_STATUS_INVALID_PARAMETER;
3732 * name_buf is now null-terminated, we need to marshall as not
3738 SIVAL(data, ofs+4, namelen);
3739 SOFF_T(data, ofs+8, streams[i].size);
3740 SOFF_T(data, ofs+16, streams[i].alloc_size);
3741 memcpy(data+ofs+24, namebuf, namelen);
3742 TALLOC_FREE(namebuf);
3744 next_offset = ofs + 24 + namelen;
3746 if (i == num_streams-1) {
3747 SIVAL(data, ofs, 0);
3750 unsigned int align = ndr_align_size(next_offset, 8);
3752 memset(data+next_offset, 0, align);
3753 next_offset += align;
3755 SIVAL(data, ofs, next_offset - ofs);
3764 return NT_STATUS_OK;
3767 /****************************************************************************
3768 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3769 ****************************************************************************/
3771 static void call_trans2qpipeinfo(connection_struct *conn,
3772 struct smb_request *req,
3773 unsigned int tran_call,
3774 char **pparams, int total_params,
3775 char **ppdata, int total_data,
3776 unsigned int max_data_bytes)
3778 char *params = *pparams;
3779 char *pdata = *ppdata;
3780 unsigned int data_size = 0;
3781 unsigned int param_size = 2;
3786 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3790 if (total_params < 4) {
3791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3795 fsp = file_fsp(req, SVAL(params,0));
3796 if (!fsp_is_np(fsp)) {
3797 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3801 info_level = SVAL(params,2);
3803 *pparams = (char *)SMB_REALLOC(*pparams,2);
3804 if (*pparams == NULL) {
3805 reply_nterror(req, NT_STATUS_NO_MEMORY);
3810 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3811 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3812 if (*ppdata == NULL ) {
3813 reply_nterror(req, NT_STATUS_NO_MEMORY);
3818 switch (info_level) {
3819 case SMB_FILE_STANDARD_INFORMATION:
3821 SOFF_T(pdata,0,4096LL);
3828 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3832 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3838 /****************************************************************************
3839 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3840 file name or file id).
3841 ****************************************************************************/
3843 static void call_trans2qfilepathinfo(connection_struct *conn,
3844 struct smb_request *req,
3845 unsigned int tran_call,
3846 char **pparams, int total_params,
3847 char **ppdata, int total_data,
3848 unsigned int max_data_bytes)
3850 char *params = *pparams;
3851 char *pdata = *ppdata;
3852 char *dstart, *dend;
3856 SMB_OFF_T file_size=0;
3857 uint64_t allocation_size=0;
3858 unsigned int data_size = 0;
3859 unsigned int param_size = 2;
3860 SMB_STRUCT_STAT sbuf;
3861 char *dos_fname = NULL;
3863 struct smb_filename *smb_fname = NULL;
3868 bool delete_pending = False;
3870 time_t create_time, mtime, atime;
3871 struct timespec create_time_ts, mtime_ts, atime_ts;
3872 struct timespec write_time_ts;
3873 files_struct *fsp = NULL;
3874 struct file_id fileid;
3875 struct ea_list *ea_list = NULL;
3876 char *lock_data = NULL;
3877 bool ms_dfs_link = false;
3878 TALLOC_CTX *ctx = talloc_tos();
3881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3886 ZERO_STRUCT(write_time_ts);
3888 if (tran_call == TRANSACT2_QFILEINFO) {
3889 if (total_params < 4) {
3890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3895 call_trans2qpipeinfo(conn, req, tran_call,
3896 pparams, total_params,
3902 fsp = file_fsp(req, SVAL(params,0));
3903 info_level = SVAL(params,2);
3905 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3907 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3908 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3912 /* Initial check for valid fsp ptr. */
3913 if (!check_fsp_open(conn, req, fsp)) {
3917 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3919 reply_nterror(req, NT_STATUS_NO_MEMORY);
3923 if(fsp->fake_file_handle) {
3925 * This is actually for the QUOTA_FAKE_FILE --metze
3928 /* We know this name is ok, it's already passed the checks. */
3930 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3932 * This is actually a QFILEINFO on a directory
3933 * handle (returned from an NT SMB). NT5.0 seems
3934 * to do this call. JRA.
3937 if (INFO_LEVEL_IS_UNIX(info_level)) {
3938 /* Always do lstat for UNIX calls. */
3939 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3940 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3941 reply_unixerror(req,ERRDOS,ERRbadpath);
3944 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3945 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3946 reply_unixerror(req, ERRDOS, ERRbadpath);
3950 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3951 get_file_infos(fileid, &delete_pending, &write_time_ts);
3954 * Original code - this is an open file.
3956 if (!check_fsp(conn, req, fsp)) {
3960 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3961 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3962 reply_unixerror(req, ERRDOS, ERRbadfid);
3965 pos = fsp->fh->position_information;
3966 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3967 get_file_infos(fileid, &delete_pending, &write_time_ts);
3971 NTSTATUS status = NT_STATUS_OK;
3974 if (total_params < 7) {
3975 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3979 info_level = SVAL(params,0);
3981 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3983 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3984 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3988 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3990 STR_TERMINATE, &status);
3991 if (!NT_STATUS_IS_OK(status)) {
3992 reply_nterror(req, status);
3996 status = resolve_dfspath(ctx,
3998 req->flags2 & FLAGS2_DFS_PATHNAMES,
4001 if (!NT_STATUS_IS_OK(status)) {
4002 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4003 reply_botherror(req,
4004 NT_STATUS_PATH_NOT_COVERED,
4005 ERRSRV, ERRbadpath);
4008 reply_nterror(req, status);
4012 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
4013 if (!NT_STATUS_IS_OK(status)) {
4014 reply_nterror(req, status);
4017 sbuf = smb_fname->st;
4019 status = get_full_smb_filename(ctx, smb_fname, &fname);
4020 TALLOC_FREE(smb_fname);
4021 if (!NT_STATUS_IS_OK(status)) {
4022 reply_nterror(req, status);
4026 status = check_name(conn, fname);
4027 if (!NT_STATUS_IS_OK(status)) {
4028 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
4029 reply_nterror(req, status);
4033 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4034 && is_ntfs_stream_name(fname)) {
4036 SMB_STRUCT_STAT bsbuf;
4038 status = split_ntfs_stream_name(talloc_tos(), fname,
4040 if (!NT_STATUS_IS_OK(status)) {
4041 DEBUG(10, ("create_file_unixpath: "
4042 "split_ntfs_stream_name failed: %s\n",
4043 nt_errstr(status)));
4044 reply_nterror(req, status);
4048 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4050 if (INFO_LEVEL_IS_UNIX(info_level)) {
4051 /* Always do lstat for UNIX calls. */
4052 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4053 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4054 reply_unixerror(req,ERRDOS,ERRbadpath);
4058 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4059 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4060 reply_unixerror(req,ERRDOS,ERRbadpath);
4065 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4066 get_file_infos(fileid, &delete_pending, NULL);
4067 if (delete_pending) {
4068 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4073 if (INFO_LEVEL_IS_UNIX(info_level)) {
4074 /* Always do lstat for UNIX calls. */
4075 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4076 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4077 reply_unixerror(req, ERRDOS, ERRbadpath);
4081 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4082 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4085 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4086 reply_unixerror(req, ERRDOS, ERRbadpath);
4091 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4092 get_file_infos(fileid, &delete_pending, &write_time_ts);
4093 if (delete_pending) {
4094 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4099 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4100 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4104 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4105 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4107 p = strrchr_m(fname,'/');
4114 mode = dos_mode_msdfs(conn,fname,&sbuf);
4116 mode = dos_mode(conn,fname,&sbuf);
4119 mode = FILE_ATTRIBUTE_NORMAL;
4121 nlink = sbuf.st_ex_nlink;
4123 if (nlink && (mode&aDIR)) {
4127 if ((nlink > 0) && delete_pending) {
4131 fullpathname = fname;
4133 file_size = get_file_size_stat(&sbuf);
4135 /* Pull out any data sent here before we realloc. */
4136 switch (info_level) {
4137 case SMB_INFO_QUERY_EAS_FROM_LIST:
4139 /* Pull any EA list from the data portion. */
4142 if (total_data < 4) {
4144 req, NT_STATUS_INVALID_PARAMETER);
4147 ea_size = IVAL(pdata,0);
4149 if (total_data > 0 && ea_size != total_data) {
4150 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4151 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4153 req, NT_STATUS_INVALID_PARAMETER);
4157 if (!lp_ea_support(SNUM(conn))) {
4158 reply_doserror(req, ERRDOS,
4159 ERReasnotsupported);
4163 /* Pull out the list of names. */
4164 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4167 req, NT_STATUS_INVALID_PARAMETER);
4173 case SMB_QUERY_POSIX_LOCK:
4175 if (fsp == NULL || fsp->fh->fd == -1) {
4176 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4180 if (total_data != POSIX_LOCK_DATA_SIZE) {
4182 req, NT_STATUS_INVALID_PARAMETER);
4186 /* Copy the lock range data. */
4187 lock_data = (char *)TALLOC_MEMDUP(
4188 ctx, pdata, total_data);
4190 reply_nterror(req, NT_STATUS_NO_MEMORY);
4198 *pparams = (char *)SMB_REALLOC(*pparams,2);
4199 if (*pparams == NULL) {
4200 reply_nterror(req, NT_STATUS_NO_MEMORY);
4205 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4206 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4207 if (*ppdata == NULL ) {
4208 reply_nterror(req, NT_STATUS_NO_MEMORY);
4213 dend = dstart + data_size - 1;
4215 create_time_ts = sbuf.st_ex_btime;
4216 mtime_ts = sbuf.st_ex_mtime;
4217 atime_ts = sbuf.st_ex_atime;
4219 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4222 /* Do we have this path open ? */
4224 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4225 fsp1 = file_find_di_first(fileid);
4226 if (fsp1 && fsp1->initial_allocation_size) {
4227 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4231 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4232 mtime_ts = write_time_ts;
4235 if (lp_dos_filetime_resolution(SNUM(conn))) {
4236 dos_filetime_timespec(&create_time_ts);
4237 dos_filetime_timespec(&mtime_ts);
4238 dos_filetime_timespec(&atime_ts);
4241 create_time = convert_timespec_to_time_t(create_time_ts);
4242 mtime = convert_timespec_to_time_t(mtime_ts);
4243 atime = convert_timespec_to_time_t(atime_ts);
4245 /* NT expects the name to be in an exact form of the *full*
4246 filename. See the trans2 torture test */
4247 if (ISDOT(base_name)) {
4248 dos_fname = talloc_strdup(ctx, "\\");
4250 reply_nterror(req, NT_STATUS_NO_MEMORY);
4254 dos_fname = talloc_asprintf(ctx,
4258 reply_nterror(req, NT_STATUS_NO_MEMORY);
4261 string_replace(dos_fname, '/', '\\');
4264 switch (info_level) {
4265 case SMB_INFO_STANDARD:
4266 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4268 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4269 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4270 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4271 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4272 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4273 SSVAL(pdata,l1_attrFile,mode);
4276 case SMB_INFO_QUERY_EA_SIZE:
4278 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4279 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4281 srv_put_dos_date2(pdata,0,create_time);
4282 srv_put_dos_date2(pdata,4,atime);
4283 srv_put_dos_date2(pdata,8,mtime); /* write time */
4284 SIVAL(pdata,12,(uint32)file_size);
4285 SIVAL(pdata,16,(uint32)allocation_size);
4286 SSVAL(pdata,20,mode);
4287 SIVAL(pdata,22,ea_size);
4291 case SMB_INFO_IS_NAME_VALID:
4292 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4293 if (tran_call == TRANSACT2_QFILEINFO) {
4294 /* os/2 needs this ? really ?*/
4295 reply_doserror(req, ERRDOS, ERRbadfunc);
4302 case SMB_INFO_QUERY_EAS_FROM_LIST:
4304 size_t total_ea_len = 0;
4305 struct ea_list *ea_file_list = NULL;
4307 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4309 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4310 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4312 if (!ea_list || (total_ea_len > data_size)) {
4314 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4318 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4322 case SMB_INFO_QUERY_ALL_EAS:
4324 /* We have data_size bytes to put EA's into. */
4325 size_t total_ea_len = 0;
4327 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4329 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4330 if (!ea_list || (total_ea_len > data_size)) {
4332 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4336 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4340 case SMB_FILE_BASIC_INFORMATION:
4341 case SMB_QUERY_FILE_BASIC_INFO:
4343 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4344 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4345 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4347 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4351 put_long_date_timespec(pdata,create_time_ts);
4352 put_long_date_timespec(pdata+8,atime_ts);
4353 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4354 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4355 SIVAL(pdata,32,mode);
4357 DEBUG(5,("SMB_QFBI - "));
4358 DEBUG(5,("create: %s ", ctime(&create_time)));
4359 DEBUG(5,("access: %s ", ctime(&atime)));
4360 DEBUG(5,("write: %s ", ctime(&mtime)));
4361 DEBUG(5,("change: %s ", ctime(&mtime)));
4362 DEBUG(5,("mode: %x\n", mode));
4365 case SMB_FILE_STANDARD_INFORMATION:
4366 case SMB_QUERY_FILE_STANDARD_INFO:
4368 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4370 SOFF_T(pdata,0,allocation_size);
4371 SOFF_T(pdata,8,file_size);
4372 SIVAL(pdata,16,nlink);
4373 SCVAL(pdata,20,delete_pending?1:0);
4374 SCVAL(pdata,21,(mode&aDIR)?1:0);
4375 SSVAL(pdata,22,0); /* Padding. */
4378 case SMB_FILE_EA_INFORMATION:
4379 case SMB_QUERY_FILE_EA_INFO:
4381 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4382 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4384 SIVAL(pdata,0,ea_size);
4388 /* Get the 8.3 name - used if NT SMB was negotiated. */
4389 case SMB_QUERY_FILE_ALT_NAME_INFO:
4390 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4392 char mangled_name[13];
4393 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4394 if (!name_to_8_3(base_name,mangled_name,
4395 True,conn->params)) {
4398 NT_STATUS_NO_MEMORY);
4400 len = srvstr_push(dstart, req->flags2,
4401 pdata+4, mangled_name,
4402 PTR_DIFF(dend, pdata+4),
4404 data_size = 4 + len;
4409 case SMB_QUERY_FILE_NAME_INFO:
4411 this must be *exactly* right for ACLs on mapped drives to work
4413 len = srvstr_push(dstart, req->flags2,
4415 PTR_DIFF(dend, pdata+4),
4417 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4418 data_size = 4 + len;
4422 case SMB_FILE_ALLOCATION_INFORMATION:
4423 case SMB_QUERY_FILE_ALLOCATION_INFO:
4424 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4426 SOFF_T(pdata,0,allocation_size);
4429 case SMB_FILE_END_OF_FILE_INFORMATION:
4430 case SMB_QUERY_FILE_END_OF_FILEINFO:
4431 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4433 SOFF_T(pdata,0,file_size);
4436 case SMB_QUERY_FILE_ALL_INFO:
4437 case SMB_FILE_ALL_INFORMATION:
4439 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4440 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4441 put_long_date_timespec(pdata,create_time_ts);
4442 put_long_date_timespec(pdata+8,atime_ts);
4443 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4444 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4445 SIVAL(pdata,32,mode);
4446 SIVAL(pdata,36,0); /* padding. */
4448 SOFF_T(pdata,0,allocation_size);
4449 SOFF_T(pdata,8,file_size);
4450 SIVAL(pdata,16,nlink);
4451 SCVAL(pdata,20,delete_pending);
4452 SCVAL(pdata,21,(mode&aDIR)?1:0);
4455 SIVAL(pdata,0,ea_size);
4456 pdata += 4; /* EA info */
4457 len = srvstr_push(dstart, req->flags2,
4459 PTR_DIFF(dend, pdata+4),
4463 data_size = PTR_DIFF(pdata,(*ppdata));
4466 case SMB_FILE_INTERNAL_INFORMATION:
4467 /* This should be an index number - looks like
4470 I think this causes us to fail the IFSKIT
4471 BasicFileInformationTest. -tpot */
4473 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4474 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4475 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4479 case SMB_FILE_ACCESS_INFORMATION:
4480 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4482 SIVAL(pdata,0,fsp->access_mask);
4484 /* GENERIC_EXECUTE mapping from Windows */
4485 SIVAL(pdata,0,0x12019F);
4490 case SMB_FILE_NAME_INFORMATION:
4491 /* Pathname with leading '\'. */
4494 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4495 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4496 SIVAL(pdata,0,byte_len);
4497 data_size = 4 + byte_len;
4501 case SMB_FILE_DISPOSITION_INFORMATION:
4502 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4504 SCVAL(pdata,0,delete_pending);
4507 case SMB_FILE_POSITION_INFORMATION:
4508 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4510 SOFF_T(pdata,0,pos);
4513 case SMB_FILE_MODE_INFORMATION:
4514 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4515 SIVAL(pdata,0,mode);
4519 case SMB_FILE_ALIGNMENT_INFORMATION:
4520 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4521 SIVAL(pdata,0,0); /* No alignment needed. */
4526 * NT4 server just returns "invalid query" to this - if we try
4527 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4530 /* The first statement above is false - verified using Thursby
4531 * client against NT4 -- gcolley.
4533 case SMB_QUERY_FILE_STREAM_INFO:
4534 case SMB_FILE_STREAM_INFORMATION: {
4535 unsigned int num_streams;
4536 struct stream_struct *streams;
4539 DEBUG(10,("call_trans2qfilepathinfo: "
4540 "SMB_FILE_STREAM_INFORMATION\n"));
4542 status = SMB_VFS_STREAMINFO(
4543 conn, fsp, fname, talloc_tos(),
4544 &num_streams, &streams);
4546 if (!NT_STATUS_IS_OK(status)) {
4547 DEBUG(10, ("could not get stream info: %s\n",
4548 nt_errstr(status)));
4549 reply_nterror(req, status);
4553 status = marshall_stream_info(num_streams, streams,
4554 pdata, max_data_bytes,
4557 if (!NT_STATUS_IS_OK(status)) {
4558 DEBUG(10, ("marshall_stream_info failed: %s\n",
4559 nt_errstr(status)));
4560 reply_nterror(req, status);
4564 TALLOC_FREE(streams);
4568 case SMB_QUERY_COMPRESSION_INFO:
4569 case SMB_FILE_COMPRESSION_INFORMATION:
4570 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4571 SOFF_T(pdata,0,file_size);
4572 SIVAL(pdata,8,0); /* ??? */
4573 SIVAL(pdata,12,0); /* ??? */
4577 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4578 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4579 put_long_date_timespec(pdata,create_time_ts);
4580 put_long_date_timespec(pdata+8,atime_ts);
4581 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4582 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4583 SOFF_T(pdata,32,allocation_size);
4584 SOFF_T(pdata,40,file_size);
4585 SIVAL(pdata,48,mode);
4586 SIVAL(pdata,52,0); /* ??? */
4590 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4591 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4592 SIVAL(pdata,0,mode);
4598 * CIFS UNIX Extensions.
4601 case SMB_QUERY_FILE_UNIX_BASIC:
4603 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4604 data_size = PTR_DIFF(pdata,(*ppdata));
4608 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4610 for (i=0; i<100; i++)
4611 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4617 case SMB_QUERY_FILE_UNIX_INFO2:
4619 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4620 data_size = PTR_DIFF(pdata,(*ppdata));
4624 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4626 for (i=0; i<100; i++)
4627 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4633 case SMB_QUERY_FILE_UNIX_LINK:
4635 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4638 reply_nterror(req, NT_STATUS_NO_MEMORY);
4642 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4644 if(!S_ISLNK(sbuf.st_ex_mode)) {
4645 reply_unixerror(req, ERRSRV,
4650 reply_unixerror(req, ERRDOS, ERRbadlink);
4653 len = SMB_VFS_READLINK(conn,fullpathname,
4656 reply_unixerror(req, ERRDOS,
4661 len = srvstr_push(dstart, req->flags2,
4663 PTR_DIFF(dend, pdata),
4666 data_size = PTR_DIFF(pdata,(*ppdata));
4671 #if defined(HAVE_POSIX_ACLS)
4672 case SMB_QUERY_POSIX_ACL:
4674 SMB_ACL_T file_acl = NULL;
4675 SMB_ACL_T def_acl = NULL;
4676 uint16 num_file_acls = 0;
4677 uint16 num_def_acls = 0;
4679 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4680 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4682 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4685 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4686 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4690 NT_STATUS_NOT_IMPLEMENTED);
4694 if (S_ISDIR(sbuf.st_ex_mode)) {
4695 if (fsp && fsp->is_directory) {
4696 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4698 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4700 def_acl = free_empty_sys_acl(conn, def_acl);
4703 num_file_acls = count_acl_entries(conn, file_acl);
4704 num_def_acls = count_acl_entries(conn, def_acl);
4706 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4707 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4709 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4710 SMB_POSIX_ACL_HEADER_SIZE) ));
4712 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4715 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4719 NT_STATUS_BUFFER_TOO_SMALL);
4723 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4724 SSVAL(pdata,2,num_file_acls);
4725 SSVAL(pdata,4,num_def_acls);
4726 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4728 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4731 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4734 req, NT_STATUS_INTERNAL_ERROR);
4737 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4739 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4742 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4746 NT_STATUS_INTERNAL_ERROR);
4751 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4754 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4756 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4762 case SMB_QUERY_POSIX_LOCK:
4764 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4768 enum brl_type lock_type;
4770 if (total_data != POSIX_LOCK_DATA_SIZE) {
4772 req, NT_STATUS_INVALID_PARAMETER);
4776 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4777 case POSIX_LOCK_TYPE_READ:
4778 lock_type = READ_LOCK;
4780 case POSIX_LOCK_TYPE_WRITE:
4781 lock_type = WRITE_LOCK;
4783 case POSIX_LOCK_TYPE_UNLOCK:
4785 /* There's no point in asking for an unlock... */
4788 NT_STATUS_INVALID_PARAMETER);
4792 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4793 #if defined(HAVE_LONGLONG)
4794 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4795 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4796 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4797 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4798 #else /* HAVE_LONGLONG */
4799 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4800 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4801 #endif /* HAVE_LONGLONG */
4803 status = query_lock(fsp,
4810 if (ERROR_WAS_LOCK_DENIED(status)) {
4811 /* Here we need to report who has it locked... */
4812 data_size = POSIX_LOCK_DATA_SIZE;
4814 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4815 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4816 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4817 #if defined(HAVE_LONGLONG)
4818 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4819 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4820 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4821 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4822 #else /* HAVE_LONGLONG */
4823 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4824 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4825 #endif /* HAVE_LONGLONG */
4827 } else if (NT_STATUS_IS_OK(status)) {
4828 /* For success we just return a copy of what we sent
4829 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4830 data_size = POSIX_LOCK_DATA_SIZE;
4831 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4832 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4834 reply_nterror(req, status);
4841 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4845 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4851 /****************************************************************************
4852 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4854 ****************************************************************************/
4856 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4857 connection_struct *conn,
4858 const char *oldname_in,
4859 const char *newname_in)
4861 struct smb_filename *smb_fname = NULL;
4862 struct smb_filename *smb_fname_new = NULL;
4863 char *oldname = NULL;
4864 char *newname = NULL;
4865 NTSTATUS status = NT_STATUS_OK;
4867 status = unix_convert(ctx, conn, oldname_in, &smb_fname, 0);
4868 if (!NT_STATUS_IS_OK(status)) {
4872 status = get_full_smb_filename(ctx, smb_fname, &oldname);
4873 if (!NT_STATUS_IS_OK(status)) {
4877 status = check_name(conn, oldname);
4878 if (!NT_STATUS_IS_OK(status)) {
4882 /* source must already exist. */
4883 if (!VALID_STAT(smb_fname->st)) {
4884 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4888 status = unix_convert(ctx, conn, newname_in, &smb_fname_new, 0);
4889 if (!NT_STATUS_IS_OK(status)) {
4893 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
4894 if (!NT_STATUS_IS_OK(status)) {
4898 status = check_name(conn, newname);
4899 if (!NT_STATUS_IS_OK(status)) {
4903 /* Disallow if newname already exists. */
4904 if (VALID_STAT(smb_fname_new->st)) {
4905 status = NT_STATUS_OBJECT_NAME_COLLISION;
4909 /* No links from a directory. */
4910 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
4911 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4915 /* Ensure this is within the share. */
4916 status = check_reduced_name(conn, oldname);
4917 if (!NT_STATUS_IS_OK(status)) {
4921 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4923 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4924 status = map_nt_error_from_unix(errno);
4925 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4926 nt_errstr(status), newname, oldname));
4929 TALLOC_FREE(smb_fname);
4930 TALLOC_FREE(smb_fname_new);
4934 /****************************************************************************
4935 Deal with setting the time from any of the setfilepathinfo functions.
4936 ****************************************************************************/
4938 NTSTATUS smb_set_file_time(connection_struct *conn,
4941 const SMB_STRUCT_STAT *psbuf,
4942 struct smb_file_time *ft,
4943 bool setting_write_time)
4946 FILE_NOTIFY_CHANGE_LAST_ACCESS
4947 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4949 if (!VALID_STAT(*psbuf)) {
4950 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4953 /* get some defaults (no modifications) if any info is zero or -1. */
4954 if (null_timespec(ft->atime)) {
4955 ft->atime= psbuf->st_ex_atime;
4956 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4959 if (null_timespec(ft->mtime)) {
4960 ft->mtime = psbuf->st_ex_mtime;
4961 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4964 if (!setting_write_time) {
4965 /* ft->mtime comes from change time, not write time. */
4966 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4969 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4970 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4971 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4972 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4973 if (!null_timespec(ft->create_time)) {
4974 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4975 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4979 * Try and set the times of this file if
4980 * they are different from the current values.
4984 struct timespec mts = psbuf->st_ex_mtime;
4985 struct timespec ats = psbuf->st_ex_atime;
4986 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4987 (timespec_compare(&ft->mtime, &mts) == 0)) {
4988 return NT_STATUS_OK;
4992 if (setting_write_time) {
4994 * This was a setfileinfo on an open file.
4995 * NT does this a lot. We also need to
4996 * set the time here, as it can be read by
4997 * FindFirst/FindNext and with the patch for bug #2045
4998 * in smbd/fileio.c it ensures that this timestamp is
4999 * kept sticky even after a write. We save the request
5000 * away and will set it on file close and after a write. JRA.
5003 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5004 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5007 if (fsp->base_fsp) {
5008 set_sticky_write_time_fsp(fsp->base_fsp,
5011 set_sticky_write_time_fsp(fsp, ft->mtime);
5014 set_sticky_write_time_path(conn, fname,
5015 vfs_file_id_from_sbuf(conn, psbuf),
5020 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5022 if (fsp && fsp->base_fsp) {
5023 fname = fsp->base_fsp->fsp_name;
5026 if(file_ntimes(conn, fname, ft)!=0) {
5027 return map_nt_error_from_unix(errno);
5029 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
5031 return NT_STATUS_OK;
5034 /****************************************************************************
5035 Deal with setting the dosmode from any of the setfilepathinfo functions.
5036 ****************************************************************************/
5038 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5041 SMB_STRUCT_STAT *psbuf,
5044 if (!VALID_STAT(*psbuf)) {
5045 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5049 if (fsp->base_fsp) {
5050 fname = fsp->base_fsp->fsp_name;
5052 fname = fsp->fsp_name;
5057 if (S_ISDIR(psbuf->st_ex_mode)) {
5064 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5066 /* check the mode isn't different, before changing it */
5067 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5069 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5070 fname, (unsigned int)dosmode ));
5072 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5073 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5074 fname, strerror(errno)));
5075 return map_nt_error_from_unix(errno);
5078 return NT_STATUS_OK;
5081 /****************************************************************************
5082 Deal with setting the size from any of the setfilepathinfo functions.
5083 ****************************************************************************/
5085 static NTSTATUS smb_set_file_size(connection_struct *conn,
5086 struct smb_request *req,
5089 SMB_STRUCT_STAT *psbuf,
5092 struct smb_filename *smb_fname = NULL;
5093 NTSTATUS status = NT_STATUS_OK;
5094 files_struct *new_fsp = NULL;
5096 if (!VALID_STAT(*psbuf)) {
5097 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5100 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5102 if (size == get_file_size_stat(psbuf)) {
5103 return NT_STATUS_OK;
5106 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5107 fname, (double)size ));
5109 if (fsp && fsp->fh->fd != -1) {
5110 /* Handle based call. */
5111 if (vfs_set_filelen(fsp, size) == -1) {
5112 return map_nt_error_from_unix(errno);
5114 trigger_write_time_update_immediate(fsp);
5115 return NT_STATUS_OK;
5118 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5120 if (!NT_STATUS_IS_OK(status)) {
5124 status = SMB_VFS_CREATE_FILE(
5127 0, /* root_dir_fid */
5128 smb_fname, /* fname */
5129 FILE_WRITE_ATTRIBUTES, /* access_mask */
5130 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5132 FILE_OPEN, /* create_disposition*/
5133 0, /* create_options */
5134 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5135 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5136 0, /* allocation_size */
5139 &new_fsp, /* result */
5142 *psbuf = smb_fname->st;
5143 TALLOC_FREE(smb_fname);
5145 if (!NT_STATUS_IS_OK(status)) {
5146 /* NB. We check for open_was_deferred in the caller. */
5150 if (vfs_set_filelen(new_fsp, size) == -1) {
5151 status = map_nt_error_from_unix(errno);
5152 close_file(req, new_fsp,NORMAL_CLOSE);
5156 trigger_write_time_update_immediate(new_fsp);
5157 close_file(req, new_fsp,NORMAL_CLOSE);
5158 return NT_STATUS_OK;
5161 /****************************************************************************
5162 Deal with SMB_INFO_SET_EA.
5163 ****************************************************************************/
5165 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5171 struct ea_list *ea_list = NULL;
5172 TALLOC_CTX *ctx = NULL;
5173 NTSTATUS status = NT_STATUS_OK;
5175 if (total_data < 10) {
5177 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5178 length. They seem to have no effect. Bug #3212. JRA */
5180 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5181 /* We're done. We only get EA info in this call. */
5182 return NT_STATUS_OK;
5185 return NT_STATUS_INVALID_PARAMETER;
5188 if (IVAL(pdata,0) > total_data) {
5189 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5190 IVAL(pdata,0), (unsigned int)total_data));
5191 return NT_STATUS_INVALID_PARAMETER;
5195 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5197 return NT_STATUS_INVALID_PARAMETER;
5199 status = set_ea(conn, fsp, fname, ea_list);
5204 /****************************************************************************
5205 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5206 ****************************************************************************/
5208 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5213 SMB_STRUCT_STAT *psbuf)
5215 NTSTATUS status = NT_STATUS_OK;
5216 bool delete_on_close;
5219 if (total_data < 1) {
5220 return NT_STATUS_INVALID_PARAMETER;
5224 return NT_STATUS_INVALID_HANDLE;
5227 delete_on_close = (CVAL(pdata,0) ? True : False);
5228 dosmode = dos_mode(conn, fname, psbuf);
5230 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5231 "delete_on_close = %u\n",
5233 (unsigned int)dosmode,
5234 (unsigned int)delete_on_close ));
5236 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5238 if (!NT_STATUS_IS_OK(status)) {
5242 /* The set is across all open files on this dev/inode pair. */
5243 if (!set_delete_on_close(fsp, delete_on_close,
5244 &conn->server_info->utok)) {
5245 return NT_STATUS_ACCESS_DENIED;
5247 return NT_STATUS_OK;
5250 /****************************************************************************
5251 Deal with SMB_FILE_POSITION_INFORMATION.
5252 ****************************************************************************/
5254 static NTSTATUS smb_file_position_information(connection_struct *conn,
5259 uint64_t position_information;
5261 if (total_data < 8) {
5262 return NT_STATUS_INVALID_PARAMETER;
5266 /* Ignore on pathname based set. */
5267 return NT_STATUS_OK;
5270 position_information = (uint64_t)IVAL(pdata,0);
5271 #ifdef LARGE_SMB_OFF_T
5272 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5273 #else /* LARGE_SMB_OFF_T */
5274 if (IVAL(pdata,4) != 0) {
5275 /* more than 32 bits? */
5276 return NT_STATUS_INVALID_PARAMETER;
5278 #endif /* LARGE_SMB_OFF_T */
5280 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5281 fsp->fsp_name, (double)position_information ));
5282 fsp->fh->position_information = position_information;
5283 return NT_STATUS_OK;
5286 /****************************************************************************
5287 Deal with SMB_FILE_MODE_INFORMATION.
5288 ****************************************************************************/
5290 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5296 if (total_data < 4) {
5297 return NT_STATUS_INVALID_PARAMETER;
5299 mode = IVAL(pdata,0);
5300 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5301 return NT_STATUS_INVALID_PARAMETER;
5303 return NT_STATUS_OK;
5306 /****************************************************************************
5307 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5308 ****************************************************************************/
5310 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5311 struct smb_request *req,
5316 char *link_target = NULL;
5317 const char *newname = fname;
5318 NTSTATUS status = NT_STATUS_OK;
5319 TALLOC_CTX *ctx = talloc_tos();
5321 /* Set a symbolic link. */
5322 /* Don't allow this if follow links is false. */
5324 if (total_data == 0) {
5325 return NT_STATUS_INVALID_PARAMETER;
5328 if (!lp_symlinks(SNUM(conn))) {
5329 return NT_STATUS_ACCESS_DENIED;
5332 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5333 total_data, STR_TERMINATE);
5336 return NT_STATUS_INVALID_PARAMETER;
5339 /* !widelinks forces the target path to be within the share. */
5340 /* This means we can interpret the target as a pathname. */
5341 if (!lp_widelinks(SNUM(conn))) {
5342 char *rel_name = NULL;
5343 char *last_dirp = NULL;
5345 if (*link_target == '/') {
5346 /* No absolute paths allowed. */
5347 return NT_STATUS_ACCESS_DENIED;
5349 rel_name = talloc_strdup(ctx,newname);
5351 return NT_STATUS_NO_MEMORY;
5353 last_dirp = strrchr_m(rel_name, '/');
5355 last_dirp[1] = '\0';
5357 rel_name = talloc_strdup(ctx,"./");
5359 return NT_STATUS_NO_MEMORY;
5362 rel_name = talloc_asprintf_append(rel_name,
5366 return NT_STATUS_NO_MEMORY;
5369 status = check_name(conn, rel_name);
5370 if (!NT_STATUS_IS_OK(status)) {
5375 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5376 newname, link_target ));
5378 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5379 return map_nt_error_from_unix(errno);
5382 return NT_STATUS_OK;
5385 /****************************************************************************
5386 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5387 ****************************************************************************/
5389 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5390 struct smb_request *req,
5391 const char *pdata, int total_data,
5394 char *oldname = NULL;
5395 TALLOC_CTX *ctx = talloc_tos();
5396 NTSTATUS status = NT_STATUS_OK;
5398 /* Set a hard link. */
5399 if (total_data == 0) {
5400 return NT_STATUS_INVALID_PARAMETER;
5403 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5404 total_data, STR_TERMINATE, &status);
5405 if (!NT_STATUS_IS_OK(status)) {
5409 status = resolve_dfspath(ctx, conn,
5410 req->flags2 & FLAGS2_DFS_PATHNAMES,
5413 if (!NT_STATUS_IS_OK(status)) {
5417 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5420 return hardlink_internals(ctx, conn, oldname, fname);
5423 /****************************************************************************
5424 Deal with SMB_FILE_RENAME_INFORMATION.
5425 ****************************************************************************/
5427 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5428 struct smb_request *req,
5437 char *newname = NULL;
5438 char *base_name = NULL;
5439 struct smb_filename *smb_fname = NULL;
5440 bool dest_has_wcard = False;
5441 NTSTATUS status = NT_STATUS_OK;
5443 TALLOC_CTX *ctx = talloc_tos();
5445 if (total_data < 13) {
5446 return NT_STATUS_INVALID_PARAMETER;
5449 overwrite = (CVAL(pdata,0) ? True : False);
5450 root_fid = IVAL(pdata,4);
5451 len = IVAL(pdata,8);
5453 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5454 return NT_STATUS_INVALID_PARAMETER;
5457 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5460 if (!NT_STATUS_IS_OK(status)) {
5464 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5467 status = resolve_dfspath_wcard(ctx, conn,
5468 req->flags2 & FLAGS2_DFS_PATHNAMES,
5472 if (!NT_STATUS_IS_OK(status)) {
5476 /* Check the new name has no '/' characters. */
5477 if (strchr_m(newname, '/')) {
5478 return NT_STATUS_NOT_SUPPORTED;
5481 if (fsp && fsp->base_fsp) {
5482 /* newname must be a stream name. */
5483 if (newname[0] != ':') {
5484 return NT_STATUS_NOT_SUPPORTED;
5486 base_name = talloc_asprintf(ctx, "%s%s",
5487 fsp->base_fsp->fsp_name,
5490 return NT_STATUS_NO_MEMORY;
5493 /* newname must *not* be a stream name. */
5494 if (is_ntfs_stream_name(newname)) {
5495 return NT_STATUS_NOT_SUPPORTED;
5498 /* Create the base directory. */
5499 base_name = talloc_strdup(ctx, fname);
5501 return NT_STATUS_NO_MEMORY;
5503 p = strrchr_m(base_name, '/');
5507 base_name = talloc_strdup(ctx, "./");
5509 return NT_STATUS_NO_MEMORY;
5512 /* Append the new name. */
5513 base_name = talloc_asprintf_append(base_name,
5517 return NT_STATUS_NO_MEMORY;
5520 status = unix_convert(ctx, conn, newname, &smb_fname,
5523 /* If an error we expect this to be
5524 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5526 if (!NT_STATUS_IS_OK(status)
5527 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5534 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5535 fsp->fnum, fsp->fsp_name, base_name ));
5536 status = rename_internals_fsp(conn, fsp, base_name,
5538 smb_fname->original_lcomp : NULL,
5541 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5542 fname, base_name ));
5543 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5544 overwrite, False, dest_has_wcard,
5545 FILE_WRITE_ATTRIBUTES);
5548 TALLOC_FREE(smb_fname);
5552 /****************************************************************************
5553 Deal with SMB_SET_POSIX_ACL.
5554 ****************************************************************************/
5556 #if defined(HAVE_POSIX_ACLS)
5557 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5562 SMB_STRUCT_STAT *psbuf)
5564 uint16 posix_acl_version;
5565 uint16 num_file_acls;
5566 uint16 num_def_acls;
5567 bool valid_file_acls = True;
5568 bool valid_def_acls = True;
5570 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5571 return NT_STATUS_INVALID_PARAMETER;
5573 posix_acl_version = SVAL(pdata,0);
5574 num_file_acls = SVAL(pdata,2);
5575 num_def_acls = SVAL(pdata,4);
5577 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5578 valid_file_acls = False;
5582 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5583 valid_def_acls = False;
5587 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5588 return NT_STATUS_INVALID_PARAMETER;
5591 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5592 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5593 return NT_STATUS_INVALID_PARAMETER;
5596 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5597 fname ? fname : fsp->fsp_name,
5598 (unsigned int)num_file_acls,
5599 (unsigned int)num_def_acls));
5601 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5602 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5603 return map_nt_error_from_unix(errno);
5606 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5607 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5608 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5609 return map_nt_error_from_unix(errno);
5611 return NT_STATUS_OK;
5615 /****************************************************************************
5616 Deal with SMB_SET_POSIX_LOCK.
5617 ****************************************************************************/
5619 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5620 struct smb_request *req,
5628 bool blocking_lock = False;
5629 enum brl_type lock_type;
5631 NTSTATUS status = NT_STATUS_OK;
5633 if (fsp == NULL || fsp->fh->fd == -1) {
5634 return NT_STATUS_INVALID_HANDLE;
5637 if (total_data != POSIX_LOCK_DATA_SIZE) {
5638 return NT_STATUS_INVALID_PARAMETER;
5641 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5642 case POSIX_LOCK_TYPE_READ:
5643 lock_type = READ_LOCK;
5645 case POSIX_LOCK_TYPE_WRITE:
5646 /* Return the right POSIX-mappable error code for files opened read-only. */
5647 if (!fsp->can_write) {
5648 return NT_STATUS_INVALID_HANDLE;
5650 lock_type = WRITE_LOCK;
5652 case POSIX_LOCK_TYPE_UNLOCK:
5653 lock_type = UNLOCK_LOCK;
5656 return NT_STATUS_INVALID_PARAMETER;
5659 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5660 blocking_lock = False;
5661 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5662 blocking_lock = True;
5664 return NT_STATUS_INVALID_PARAMETER;
5667 if (!lp_blocking_locks(SNUM(conn))) {
5668 blocking_lock = False;
5671 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5672 #if defined(HAVE_LONGLONG)
5673 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5674 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5675 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5676 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5677 #else /* HAVE_LONGLONG */
5678 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5679 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5680 #endif /* HAVE_LONGLONG */
5682 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5683 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5685 (unsigned int)lock_type,
5686 (unsigned int)lock_pid,
5690 if (lock_type == UNLOCK_LOCK) {
5691 status = do_unlock(smbd_messaging_context(),
5698 uint32 block_smbpid;
5700 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5712 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5714 * A blocking lock was requested. Package up
5715 * this smb into a queued request and push it
5716 * onto the blocking lock queue.
5718 if(push_blocking_lock_request(br_lck,
5721 -1, /* infinite timeout. */
5729 TALLOC_FREE(br_lck);
5733 TALLOC_FREE(br_lck);
5739 /****************************************************************************
5740 Deal with SMB_INFO_STANDARD.
5741 ****************************************************************************/
5743 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5748 const SMB_STRUCT_STAT *psbuf)
5750 struct smb_file_time ft;
5753 if (total_data < 12) {
5754 return NT_STATUS_INVALID_PARAMETER;
5758 ft.create_time = interpret_long_date(pdata);
5761 ft.atime = interpret_long_date(pdata + 8);
5764 ft.mtime = interpret_long_date(pdata + 16);
5766 DEBUG(10,("smb_set_info_standard: file %s\n",
5767 fname ? fname : fsp->fsp_name ));
5769 return smb_set_file_time(conn,
5777 /****************************************************************************
5778 Deal with SMB_SET_FILE_BASIC_INFO.
5779 ****************************************************************************/
5781 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5786 SMB_STRUCT_STAT *psbuf)
5788 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5789 struct timespec write_time;
5790 struct timespec changed_time;
5791 struct smb_file_time ft;
5793 NTSTATUS status = NT_STATUS_OK;
5794 bool setting_write_time = true;
5798 if (total_data < 36) {
5799 return NT_STATUS_INVALID_PARAMETER;
5802 /* Set the attributes */
5803 dosmode = IVAL(pdata,32);
5804 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5805 if (!NT_STATUS_IS_OK(status)) {
5810 ft.atime = interpret_long_date(pdata+8);
5812 write_time = interpret_long_date(pdata+16);
5813 changed_time = interpret_long_date(pdata+24);
5816 ft.mtime = timespec_min(&write_time, &changed_time);
5819 ft.create_time = interpret_long_date(pdata);
5821 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5822 !null_timespec(write_time)) {
5823 ft.mtime = write_time;
5826 /* Prefer a defined time to an undefined one. */
5827 if (null_timespec(ft.mtime)) {
5828 if (null_timespec(write_time)) {
5829 ft.mtime = changed_time;
5830 setting_write_time = false;
5832 ft.mtime = write_time;
5836 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5837 fname ? fname : fsp->fsp_name ));
5839 return smb_set_file_time(conn,
5844 setting_write_time);
5847 /****************************************************************************
5848 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5849 ****************************************************************************/
5851 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5852 struct smb_request *req,
5857 SMB_STRUCT_STAT *psbuf)
5859 struct smb_filename *smb_fname = NULL;
5860 uint64_t allocation_size = 0;
5861 NTSTATUS status = NT_STATUS_OK;
5862 files_struct *new_fsp = NULL;
5864 if (!VALID_STAT(*psbuf)) {
5865 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5868 if (total_data < 8) {
5869 return NT_STATUS_INVALID_PARAMETER;
5872 allocation_size = (uint64_t)IVAL(pdata,0);
5873 #ifdef LARGE_SMB_OFF_T
5874 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5875 #else /* LARGE_SMB_OFF_T */
5876 if (IVAL(pdata,4) != 0) {
5877 /* more than 32 bits? */
5878 return NT_STATUS_INVALID_PARAMETER;
5880 #endif /* LARGE_SMB_OFF_T */
5882 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5883 fname, (double)allocation_size ));
5885 if (allocation_size) {
5886 allocation_size = smb_roundup(conn, allocation_size);
5889 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5890 fname, (double)allocation_size ));
5892 if (fsp && fsp->fh->fd != -1) {
5893 /* Open file handle. */
5894 /* Only change if needed. */
5895 if (allocation_size != get_file_size_stat(psbuf)) {
5896 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5897 return map_nt_error_from_unix(errno);
5900 /* But always update the time. */
5902 * This is equivalent to a write. Ensure it's seen immediately
5903 * if there are no pending writes.
5905 trigger_write_time_update_immediate(fsp);
5906 return NT_STATUS_OK;
5909 /* Pathname or stat or directory file. */
5911 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
5913 if (!NT_STATUS_IS_OK(status)) {
5917 status = SMB_VFS_CREATE_FILE(
5920 0, /* root_dir_fid */
5921 smb_fname, /* fname */
5922 FILE_WRITE_DATA, /* access_mask */
5923 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5925 FILE_OPEN, /* create_disposition*/
5926 0, /* create_options */
5927 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5928 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5929 0, /* allocation_size */
5932 &new_fsp, /* result */
5935 *psbuf = smb_fname->st;
5936 TALLOC_FREE(smb_fname);
5938 if (!NT_STATUS_IS_OK(status)) {
5939 /* NB. We check for open_was_deferred in the caller. */
5943 /* Only change if needed. */
5944 if (allocation_size != get_file_size_stat(psbuf)) {
5945 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5946 status = map_nt_error_from_unix(errno);
5947 close_file(req, new_fsp, NORMAL_CLOSE);
5952 /* Changing the allocation size should set the last mod time. */
5954 * This is equivalent to a write. Ensure it's seen immediately
5955 * if there are no pending writes.
5957 trigger_write_time_update_immediate(new_fsp);
5959 close_file(req, new_fsp, NORMAL_CLOSE);
5960 return NT_STATUS_OK;
5963 /****************************************************************************
5964 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5965 ****************************************************************************/
5967 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5968 struct smb_request *req,
5973 SMB_STRUCT_STAT *psbuf)
5977 if (total_data < 8) {
5978 return NT_STATUS_INVALID_PARAMETER;
5981 size = IVAL(pdata,0);
5982 #ifdef LARGE_SMB_OFF_T
5983 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5984 #else /* LARGE_SMB_OFF_T */
5985 if (IVAL(pdata,4) != 0) {
5986 /* more than 32 bits? */
5987 return NT_STATUS_INVALID_PARAMETER;
5989 #endif /* LARGE_SMB_OFF_T */
5990 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5991 "file %s to %.0f\n", fname, (double)size ));
5993 return smb_set_file_size(conn, req,
6000 /****************************************************************************
6001 Allow a UNIX info mknod.
6002 ****************************************************************************/
6004 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6008 SMB_STRUCT_STAT *psbuf)
6010 uint32 file_type = IVAL(pdata,56);
6011 #if defined(HAVE_MAKEDEV)
6012 uint32 dev_major = IVAL(pdata,60);
6013 uint32 dev_minor = IVAL(pdata,68);
6015 SMB_DEV_T dev = (SMB_DEV_T)0;
6016 uint32 raw_unixmode = IVAL(pdata,84);
6020 if (total_data < 100) {
6021 return NT_STATUS_INVALID_PARAMETER;
6024 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
6025 if (!NT_STATUS_IS_OK(status)) {
6029 #if defined(HAVE_MAKEDEV)
6030 dev = makedev(dev_major, dev_minor);
6033 switch (file_type) {
6034 #if defined(S_IFIFO)
6035 case UNIX_TYPE_FIFO:
6036 unixmode |= S_IFIFO;
6039 #if defined(S_IFSOCK)
6040 case UNIX_TYPE_SOCKET:
6041 unixmode |= S_IFSOCK;
6044 #if defined(S_IFCHR)
6045 case UNIX_TYPE_CHARDEV:
6046 unixmode |= S_IFCHR;
6049 #if defined(S_IFBLK)
6050 case UNIX_TYPE_BLKDEV:
6051 unixmode |= S_IFBLK;
6055 return NT_STATUS_INVALID_PARAMETER;
6058 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6059 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6061 /* Ok - do the mknod. */
6062 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6063 return map_nt_error_from_unix(errno);
6066 /* If any of the other "set" calls fail we
6067 * don't want to end up with a half-constructed mknod.
6070 if (lp_inherit_perms(SNUM(conn))) {
6072 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6073 return NT_STATUS_NO_MEMORY;
6075 inherit_access_posix_acl(conn, parent, fname, unixmode);
6076 TALLOC_FREE(parent);
6079 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6080 status = map_nt_error_from_unix(errno);
6081 SMB_VFS_UNLINK(conn,fname);
6084 return NT_STATUS_OK;
6087 /****************************************************************************
6088 Deal with SMB_SET_FILE_UNIX_BASIC.
6089 ****************************************************************************/
6091 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6092 struct smb_request *req,
6097 SMB_STRUCT_STAT *psbuf)
6099 struct smb_file_time ft;
6100 uint32 raw_unixmode;
6103 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6104 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6105 NTSTATUS status = NT_STATUS_OK;
6106 bool delete_on_fail = False;
6107 enum perm_type ptype;
6111 if (total_data < 100) {
6112 return NT_STATUS_INVALID_PARAMETER;
6115 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6116 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6117 size=IVAL(pdata,0); /* first 8 Bytes are size */
6118 #ifdef LARGE_SMB_OFF_T
6119 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6120 #else /* LARGE_SMB_OFF_T */
6121 if (IVAL(pdata,4) != 0) {
6122 /* more than 32 bits? */
6123 return NT_STATUS_INVALID_PARAMETER;
6125 #endif /* LARGE_SMB_OFF_T */
6128 ft.atime = interpret_long_date(pdata+24); /* access_time */
6129 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6130 set_owner = (uid_t)IVAL(pdata,40);
6131 set_grp = (gid_t)IVAL(pdata,48);
6132 raw_unixmode = IVAL(pdata,84);
6134 if (VALID_STAT(*psbuf)) {
6135 if (S_ISDIR(psbuf->st_ex_mode)) {
6136 ptype = PERM_EXISTING_DIR;
6138 ptype = PERM_EXISTING_FILE;
6141 ptype = PERM_NEW_FILE;
6144 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6145 if (!NT_STATUS_IS_OK(status)) {
6149 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6150 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6151 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6153 if (!VALID_STAT(*psbuf)) {
6155 * The only valid use of this is to create character and block
6156 * devices, and named pipes. This is deprecated (IMHO) and
6157 * a new info level should be used for mknod. JRA.
6160 status = smb_unix_mknod(conn,
6165 if (!NT_STATUS_IS_OK(status)) {
6169 /* Ensure we don't try and change anything else. */
6170 raw_unixmode = SMB_MODE_NO_CHANGE;
6171 size = get_file_size_stat(psbuf);
6172 ft.atime = psbuf->st_ex_atime;
6173 ft.mtime = psbuf->st_ex_mtime;
6175 * We continue here as we might want to change the
6178 delete_on_fail = True;
6182 /* Horrible backwards compatibility hack as an old server bug
6183 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6187 size = get_file_size_stat(psbuf);
6192 * Deal with the UNIX specific mode set.
6195 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6196 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6197 (unsigned int)unixmode, fname ));
6198 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6199 return map_nt_error_from_unix(errno);
6204 * Deal with the UNIX specific uid set.
6207 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_ex_uid != set_owner)) {
6210 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6211 (unsigned int)set_owner, fname ));
6213 if (S_ISLNK(psbuf->st_ex_mode)) {
6214 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6216 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6220 status = map_nt_error_from_unix(errno);
6221 if (delete_on_fail) {
6222 SMB_VFS_UNLINK(conn,fname);
6229 * Deal with the UNIX specific gid set.
6232 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_ex_gid != set_grp)) {
6233 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6234 (unsigned int)set_owner, fname ));
6235 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6236 status = map_nt_error_from_unix(errno);
6237 if (delete_on_fail) {
6238 SMB_VFS_UNLINK(conn,fname);
6244 /* Deal with any size changes. */
6246 status = smb_set_file_size(conn, req,
6251 if (!NT_STATUS_IS_OK(status)) {
6255 /* Deal with any time changes. */
6257 return smb_set_file_time(conn,
6265 /****************************************************************************
6266 Deal with SMB_SET_FILE_UNIX_INFO2.
6267 ****************************************************************************/
6269 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6270 struct smb_request *req,
6275 SMB_STRUCT_STAT *psbuf)
6281 if (total_data < 116) {
6282 return NT_STATUS_INVALID_PARAMETER;
6285 /* Start by setting all the fields that are common between UNIX_BASIC
6288 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6290 if (!NT_STATUS_IS_OK(status)) {
6294 smb_fflags = IVAL(pdata, 108);
6295 smb_fmask = IVAL(pdata, 112);
6297 /* NB: We should only attempt to alter the file flags if the client
6298 * sends a non-zero mask.
6300 if (smb_fmask != 0) {
6301 int stat_fflags = 0;
6303 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6305 /* Client asked to alter a flag we don't understand. */
6306 return NT_STATUS_INVALID_PARAMETER;
6309 if (fsp && fsp->fh->fd != -1) {
6310 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6311 return NT_STATUS_NOT_SUPPORTED;
6313 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6314 return map_nt_error_from_unix(errno);
6319 /* XXX: need to add support for changing the create_time here. You
6320 * can do this for paths on Darwin with setattrlist(2). The right way
6321 * to hook this up is probably by extending the VFS utimes interface.
6324 return NT_STATUS_OK;
6327 /****************************************************************************
6328 Create a directory with POSIX semantics.
6329 ****************************************************************************/
6331 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6332 struct smb_request *req,
6336 SMB_STRUCT_STAT *psbuf,
6337 int *pdata_return_size)
6339 struct smb_filename *smb_fname;
6340 NTSTATUS status = NT_STATUS_OK;
6341 uint32 raw_unixmode = 0;
6342 uint32 mod_unixmode = 0;
6343 mode_t unixmode = (mode_t)0;
6344 files_struct *fsp = NULL;
6345 uint16 info_level_return = 0;
6347 char *pdata = *ppdata;
6349 if (total_data < 18) {
6350 return NT_STATUS_INVALID_PARAMETER;
6353 raw_unixmode = IVAL(pdata,8);
6354 /* Next 4 bytes are not yet defined. */
6356 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6357 if (!NT_STATUS_IS_OK(status)) {
6361 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6363 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6364 fname, (unsigned int)unixmode ));
6366 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6368 if (!NT_STATUS_IS_OK(status)) {
6372 status = SMB_VFS_CREATE_FILE(
6375 0, /* root_dir_fid */
6376 smb_fname, /* fname */
6377 FILE_READ_ATTRIBUTES, /* access_mask */
6378 FILE_SHARE_NONE, /* share_access */
6379 FILE_CREATE, /* create_disposition*/
6380 FILE_DIRECTORY_FILE, /* create_options */
6381 mod_unixmode, /* file_attributes */
6382 0, /* oplock_request */
6383 0, /* allocation_size */
6389 *psbuf = smb_fname->st;
6390 TALLOC_FREE(smb_fname);
6392 if (NT_STATUS_IS_OK(status)) {
6393 close_file(req, fsp, NORMAL_CLOSE);
6396 info_level_return = SVAL(pdata,16);
6398 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6399 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6400 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6401 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6403 *pdata_return_size = 12;
6406 /* Realloc the data size */
6407 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6408 if (*ppdata == NULL) {
6409 *pdata_return_size = 0;
6410 return NT_STATUS_NO_MEMORY;
6414 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6415 SSVAL(pdata,2,0); /* No fnum. */
6416 SIVAL(pdata,4,info); /* Was directory created. */
6418 switch (info_level_return) {
6419 case SMB_QUERY_FILE_UNIX_BASIC:
6420 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6421 SSVAL(pdata,10,0); /* Padding. */
6422 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6424 case SMB_QUERY_FILE_UNIX_INFO2:
6425 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6426 SSVAL(pdata,10,0); /* Padding. */
6427 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6430 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6431 SSVAL(pdata,10,0); /* Padding. */
6438 /****************************************************************************
6439 Open/Create a file with POSIX semantics.
6440 ****************************************************************************/
6442 static NTSTATUS smb_posix_open(connection_struct *conn,
6443 struct smb_request *req,
6447 SMB_STRUCT_STAT *psbuf,
6448 int *pdata_return_size)
6450 struct smb_filename *smb_fname = NULL;
6451 bool extended_oplock_granted = False;
6452 char *pdata = *ppdata;
6454 uint32 wire_open_mode = 0;
6455 uint32 raw_unixmode = 0;
6456 uint32 mod_unixmode = 0;
6457 uint32 create_disp = 0;
6458 uint32 access_mask = 0;
6459 uint32 create_options = 0;
6460 NTSTATUS status = NT_STATUS_OK;
6461 mode_t unixmode = (mode_t)0;
6462 files_struct *fsp = NULL;
6463 int oplock_request = 0;
6465 uint16 info_level_return = 0;
6467 if (total_data < 18) {
6468 return NT_STATUS_INVALID_PARAMETER;
6471 flags = IVAL(pdata,0);
6472 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6473 if (oplock_request) {
6474 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6477 wire_open_mode = IVAL(pdata,4);
6479 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6480 return smb_posix_mkdir(conn, req,
6488 switch (wire_open_mode & SMB_ACCMODE) {
6490 access_mask = FILE_READ_DATA;
6493 access_mask = FILE_WRITE_DATA;
6496 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6499 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6500 (unsigned int)wire_open_mode ));
6501 return NT_STATUS_INVALID_PARAMETER;
6504 wire_open_mode &= ~SMB_ACCMODE;
6506 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6507 create_disp = FILE_CREATE;
6508 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6509 create_disp = FILE_OVERWRITE_IF;
6510 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6511 create_disp = FILE_OPEN_IF;
6512 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6513 create_disp = FILE_OPEN;
6515 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6516 (unsigned int)wire_open_mode ));
6517 return NT_STATUS_INVALID_PARAMETER;
6520 raw_unixmode = IVAL(pdata,8);
6521 /* Next 4 bytes are not yet defined. */
6523 status = unix_perms_from_wire(conn,
6526 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6529 if (!NT_STATUS_IS_OK(status)) {
6533 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6535 if (wire_open_mode & SMB_O_SYNC) {
6536 create_options |= FILE_WRITE_THROUGH;
6538 if (wire_open_mode & SMB_O_APPEND) {
6539 access_mask |= FILE_APPEND_DATA;
6541 if (wire_open_mode & SMB_O_DIRECT) {
6542 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6545 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6547 (unsigned int)wire_open_mode,
6548 (unsigned int)unixmode ));
6550 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6552 if (!NT_STATUS_IS_OK(status)) {
6556 status = SMB_VFS_CREATE_FILE(
6559 0, /* root_dir_fid */
6560 smb_fname, /* fname */
6561 access_mask, /* access_mask */
6562 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6564 create_disp, /* create_disposition*/
6565 FILE_NON_DIRECTORY_FILE, /* create_options */
6566 mod_unixmode, /* file_attributes */
6567 oplock_request, /* oplock_request */
6568 0, /* allocation_size */
6574 *psbuf = smb_fname->st;
6575 TALLOC_FREE(smb_fname);
6577 if (!NT_STATUS_IS_OK(status)) {
6581 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6582 extended_oplock_granted = True;
6585 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6586 extended_oplock_granted = True;
6589 info_level_return = SVAL(pdata,16);
6591 /* Allocate the correct return size. */
6593 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6594 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6595 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6596 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6598 *pdata_return_size = 12;
6601 /* Realloc the data size */
6602 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6603 if (*ppdata == NULL) {
6604 close_file(req, fsp, ERROR_CLOSE);
6605 *pdata_return_size = 0;
6606 return NT_STATUS_NO_MEMORY;
6610 if (extended_oplock_granted) {
6611 if (flags & REQUEST_BATCH_OPLOCK) {
6612 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6614 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6616 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6617 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6619 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6622 SSVAL(pdata,2,fsp->fnum);
6623 SIVAL(pdata,4,info); /* Was file created etc. */
6625 switch (info_level_return) {
6626 case SMB_QUERY_FILE_UNIX_BASIC:
6627 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6628 SSVAL(pdata,10,0); /* padding. */
6629 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6631 case SMB_QUERY_FILE_UNIX_INFO2:
6632 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6633 SSVAL(pdata,10,0); /* padding. */
6634 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6637 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6638 SSVAL(pdata,10,0); /* padding. */
6641 return NT_STATUS_OK;
6644 /****************************************************************************
6645 Delete a file with POSIX semantics.
6646 ****************************************************************************/
6648 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6649 struct smb_request *req,
6653 SMB_STRUCT_STAT *psbuf)
6655 struct smb_filename *smb_fname = NULL;
6656 NTSTATUS status = NT_STATUS_OK;
6657 files_struct *fsp = NULL;
6661 int create_options = 0;
6663 struct share_mode_lock *lck = NULL;
6665 if (total_data < 2) {
6666 return NT_STATUS_INVALID_PARAMETER;
6669 flags = SVAL(pdata,0);
6671 if (!VALID_STAT(*psbuf)) {
6672 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6675 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6676 !VALID_STAT_OF_DIR(*psbuf)) {
6677 return NT_STATUS_NOT_A_DIRECTORY;
6680 DEBUG(10,("smb_posix_unlink: %s %s\n",
6681 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6684 if (VALID_STAT_OF_DIR(*psbuf)) {
6685 create_options |= FILE_DIRECTORY_FILE;
6688 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6690 if (!NT_STATUS_IS_OK(status)) {
6694 status = SMB_VFS_CREATE_FILE(
6697 0, /* root_dir_fid */
6698 smb_fname, /* fname */
6699 DELETE_ACCESS, /* access_mask */
6700 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6702 FILE_OPEN, /* create_disposition*/
6703 create_options, /* create_options */
6704 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6705 0, /* oplock_request */
6706 0, /* allocation_size */
6712 *psbuf = smb_fname->st;
6713 TALLOC_FREE(smb_fname);
6715 if (!NT_STATUS_IS_OK(status)) {
6720 * Don't lie to client. If we can't really delete due to
6721 * non-POSIX opens return SHARING_VIOLATION.
6724 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6727 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6728 "lock for file %s\n", fsp->fsp_name));
6729 close_file(req, fsp, NORMAL_CLOSE);
6730 return NT_STATUS_INVALID_PARAMETER;
6734 * See if others still have the file open. If this is the case, then
6735 * don't delete. If all opens are POSIX delete we can set the delete
6736 * on close disposition.
6738 for (i=0; i<lck->num_share_modes; i++) {
6739 struct share_mode_entry *e = &lck->share_modes[i];
6740 if (is_valid_share_mode_entry(e)) {
6741 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6744 /* Fail with sharing violation. */
6745 close_file(req, fsp, NORMAL_CLOSE);
6747 return NT_STATUS_SHARING_VIOLATION;
6752 * Set the delete on close.
6754 status = smb_set_file_disposition_info(conn,
6761 if (!NT_STATUS_IS_OK(status)) {
6762 close_file(req, fsp, NORMAL_CLOSE);
6767 return close_file(req, fsp, NORMAL_CLOSE);
6770 /****************************************************************************
6771 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6772 ****************************************************************************/
6774 static void call_trans2setfilepathinfo(connection_struct *conn,
6775 struct smb_request *req,
6776 unsigned int tran_call,
6777 char **pparams, int total_params,
6778 char **ppdata, int total_data,
6779 unsigned int max_data_bytes)
6781 char *params = *pparams;
6782 char *pdata = *ppdata;
6784 SMB_STRUCT_STAT sbuf;
6786 struct smb_filename *smb_fname = NULL;
6787 files_struct *fsp = NULL;
6788 NTSTATUS status = NT_STATUS_OK;
6789 int data_return_size = 0;
6790 TALLOC_CTX *ctx = talloc_tos();
6793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6799 if (tran_call == TRANSACT2_SETFILEINFO) {
6800 if (total_params < 4) {
6801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6805 fsp = file_fsp(req, SVAL(params,0));
6806 /* Basic check for non-null fsp. */
6807 if (!check_fsp_open(conn, req, fsp)) {
6810 info_level = SVAL(params,2);
6812 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6814 reply_nterror(req, NT_STATUS_NO_MEMORY);
6818 if(fsp->is_directory || fsp->fh->fd == -1) {
6820 * This is actually a SETFILEINFO on a directory
6821 * handle (returned from an NT SMB). NT5.0 seems
6822 * to do this call. JRA.
6824 if (INFO_LEVEL_IS_UNIX(info_level)) {
6825 /* Always do lstat for UNIX calls. */
6826 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6827 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6828 reply_unixerror(req,ERRDOS,ERRbadpath);
6832 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6833 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6834 reply_unixerror(req,ERRDOS,ERRbadpath);
6838 } else if (fsp->print_file) {
6840 * Doing a DELETE_ON_CLOSE should cancel a print job.
6842 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6843 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6845 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6848 send_trans2_replies(conn, req, params, 2,
6853 reply_unixerror(req, ERRDOS, ERRbadpath);
6858 * Original code - this is an open file.
6860 if (!check_fsp(conn, req, fsp)) {
6864 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6865 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6866 reply_unixerror(req, ERRDOS, ERRbadfid);
6872 if (total_params < 7) {
6873 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6877 info_level = SVAL(params,0);
6878 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6879 total_params - 6, STR_TERMINATE,
6881 if (!NT_STATUS_IS_OK(status)) {
6882 reply_nterror(req, status);
6886 status = resolve_dfspath(ctx, conn,
6887 req->flags2 & FLAGS2_DFS_PATHNAMES,
6890 if (!NT_STATUS_IS_OK(status)) {
6891 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6892 reply_botherror(req,
6893 NT_STATUS_PATH_NOT_COVERED,
6894 ERRSRV, ERRbadpath);
6897 reply_nterror(req, status);
6901 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
6902 if (!NT_STATUS_IS_OK(status)) {
6903 reply_nterror(req, status);
6906 sbuf = smb_fname->st;
6908 status = get_full_smb_filename(ctx, smb_fname, &fname);
6909 TALLOC_FREE(smb_fname);
6910 if (!NT_STATUS_IS_OK(status)) {
6911 reply_nterror(req, status);
6915 status = check_name(conn, fname);
6916 if (!NT_STATUS_IS_OK(status)) {
6917 reply_nterror(req, status);
6921 if (INFO_LEVEL_IS_UNIX(info_level)) {
6923 * For CIFS UNIX extensions the target name may not exist.
6926 /* Always do lstat for UNIX calls. */
6927 SMB_VFS_LSTAT(conn,fname,&sbuf);
6929 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6930 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6931 reply_unixerror(req, ERRDOS, ERRbadpath);
6936 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6937 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6941 if (!CAN_WRITE(conn)) {
6942 /* Allow POSIX opens. The open path will deny
6943 * any non-readonly opens. */
6944 if (info_level != SMB_POSIX_PATH_OPEN) {
6945 reply_doserror(req, ERRSRV, ERRaccess);
6950 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6951 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6953 /* Realloc the parameter size */
6954 *pparams = (char *)SMB_REALLOC(*pparams,2);
6955 if (*pparams == NULL) {
6956 reply_nterror(req, NT_STATUS_NO_MEMORY);
6963 switch (info_level) {
6965 case SMB_INFO_STANDARD:
6967 status = smb_set_info_standard(conn,
6976 case SMB_INFO_SET_EA:
6978 status = smb_info_set_ea(conn,
6986 case SMB_SET_FILE_BASIC_INFO:
6987 case SMB_FILE_BASIC_INFORMATION:
6989 status = smb_set_file_basic_info(conn,
6998 case SMB_FILE_ALLOCATION_INFORMATION:
6999 case SMB_SET_FILE_ALLOCATION_INFO:
7001 status = smb_set_file_allocation_info(conn, req,
7010 case SMB_FILE_END_OF_FILE_INFORMATION:
7011 case SMB_SET_FILE_END_OF_FILE_INFO:
7013 status = smb_set_file_end_of_file_info(conn, req,
7022 case SMB_FILE_DISPOSITION_INFORMATION:
7023 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7026 /* JRA - We used to just ignore this on a path ?
7027 * Shouldn't this be invalid level on a pathname
7030 if (tran_call != TRANSACT2_SETFILEINFO) {
7031 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7034 status = smb_set_file_disposition_info(conn,
7043 case SMB_FILE_POSITION_INFORMATION:
7045 status = smb_file_position_information(conn,
7052 /* From tridge Samba4 :
7053 * MODE_INFORMATION in setfileinfo (I have no
7054 * idea what "mode information" on a file is - it takes a value of 0,
7055 * 2, 4 or 6. What could it be?).
7058 case SMB_FILE_MODE_INFORMATION:
7060 status = smb_file_mode_information(conn,
7067 * CIFS UNIX extensions.
7070 case SMB_SET_FILE_UNIX_BASIC:
7072 status = smb_set_file_unix_basic(conn, req,
7081 case SMB_SET_FILE_UNIX_INFO2:
7083 status = smb_set_file_unix_info2(conn, req,
7092 case SMB_SET_FILE_UNIX_LINK:
7094 if (tran_call != TRANSACT2_SETPATHINFO) {
7095 /* We must have a pathname for this. */
7096 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7099 status = smb_set_file_unix_link(conn, req, pdata,
7104 case SMB_SET_FILE_UNIX_HLINK:
7106 if (tran_call != TRANSACT2_SETPATHINFO) {
7107 /* We must have a pathname for this. */
7108 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7111 status = smb_set_file_unix_hlink(conn, req,
7117 case SMB_FILE_RENAME_INFORMATION:
7119 status = smb_file_rename_information(conn, req,
7125 #if defined(HAVE_POSIX_ACLS)
7126 case SMB_SET_POSIX_ACL:
7128 status = smb_set_posix_acl(conn,
7138 case SMB_SET_POSIX_LOCK:
7140 if (tran_call != TRANSACT2_SETFILEINFO) {
7141 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7144 status = smb_set_posix_lock(conn, req,
7145 pdata, total_data, fsp);
7149 case SMB_POSIX_PATH_OPEN:
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_open(conn, req,
7166 case SMB_POSIX_PATH_UNLINK:
7168 if (tran_call != TRANSACT2_SETPATHINFO) {
7169 /* We must have a pathname for this. */
7170 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7174 status = smb_posix_unlink(conn, req,
7183 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7187 if (!NT_STATUS_IS_OK(status)) {
7188 if (open_was_deferred(req->mid)) {
7189 /* We have re-scheduled this call. */
7192 if (blocking_lock_was_deferred(req->mid)) {
7193 /* We have re-scheduled this call. */
7196 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7197 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7198 ERRSRV, ERRbadpath);
7201 if (info_level == SMB_POSIX_PATH_OPEN) {
7202 reply_openerror(req, status);
7206 reply_nterror(req, status);
7211 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7217 /****************************************************************************
7218 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7219 ****************************************************************************/
7221 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7222 char **pparams, int total_params,
7223 char **ppdata, int total_data,
7224 unsigned int max_data_bytes)
7226 struct smb_filename *smb_dname = NULL;
7227 char *params = *pparams;
7228 char *pdata = *ppdata;
7229 char *directory = NULL;
7230 NTSTATUS status = NT_STATUS_OK;
7231 struct ea_list *ea_list = NULL;
7232 TALLOC_CTX *ctx = talloc_tos();
7234 if (!CAN_WRITE(conn)) {
7235 reply_doserror(req, ERRSRV, ERRaccess);
7239 if (total_params < 5) {
7240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7244 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7245 total_params - 4, STR_TERMINATE,
7247 if (!NT_STATUS_IS_OK(status)) {
7248 reply_nterror(req, status);
7252 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7254 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
7255 if (!NT_STATUS_IS_OK(status)) {
7256 reply_nterror(req, status);
7260 status = check_name(conn, smb_dname->base_name);
7261 if (!NT_STATUS_IS_OK(status)) {
7262 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7263 reply_nterror(req, status);
7267 /* Any data in this call is an EA list. */
7268 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7269 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7274 * OS/2 workplace shell seems to send SET_EA requests of "null"
7275 * length (4 bytes containing IVAL 4).
7276 * They seem to have no effect. Bug #3212. JRA.
7279 if (total_data != 4) {
7280 if (total_data < 10) {
7281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7285 if (IVAL(pdata,0) > total_data) {
7286 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7287 IVAL(pdata,0), (unsigned int)total_data));
7288 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7292 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7299 /* If total_data == 4 Windows doesn't care what values
7300 * are placed in that field, it just ignores them.
7301 * The System i QNTC IBM SMB client puts bad values here,
7302 * so ignore them. */
7304 status = create_directory(conn, req, smb_dname);
7306 if (!NT_STATUS_IS_OK(status)) {
7307 reply_nterror(req, status);
7311 /* Try and set any given EA. */
7313 status = set_ea(conn, NULL, smb_dname->base_name, ea_list);
7314 if (!NT_STATUS_IS_OK(status)) {
7315 reply_nterror(req, status);
7320 /* Realloc the parameter and data sizes */
7321 *pparams = (char *)SMB_REALLOC(*pparams,2);
7322 if(*pparams == NULL) {
7323 reply_nterror(req, NT_STATUS_NO_MEMORY);
7330 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7333 TALLOC_FREE(smb_dname);
7337 /****************************************************************************
7338 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7339 We don't actually do this - we just send a null response.
7340 ****************************************************************************/
7342 static void call_trans2findnotifyfirst(connection_struct *conn,
7343 struct smb_request *req,
7344 char **pparams, int total_params,
7345 char **ppdata, int total_data,
7346 unsigned int max_data_bytes)
7348 char *params = *pparams;
7351 if (total_params < 6) {
7352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7356 info_level = SVAL(params,4);
7357 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7359 switch (info_level) {
7364 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7368 /* Realloc the parameter and data sizes */
7369 *pparams = (char *)SMB_REALLOC(*pparams,6);
7370 if (*pparams == NULL) {
7371 reply_nterror(req, NT_STATUS_NO_MEMORY);
7376 SSVAL(params,0,fnf_handle);
7377 SSVAL(params,2,0); /* No changes */
7378 SSVAL(params,4,0); /* No EA errors */
7385 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7390 /****************************************************************************
7391 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7392 changes). Currently this does nothing.
7393 ****************************************************************************/
7395 static void call_trans2findnotifynext(connection_struct *conn,
7396 struct smb_request *req,
7397 char **pparams, int total_params,
7398 char **ppdata, int total_data,
7399 unsigned int max_data_bytes)
7401 char *params = *pparams;
7403 DEBUG(3,("call_trans2findnotifynext\n"));
7405 /* Realloc the parameter and data sizes */
7406 *pparams = (char *)SMB_REALLOC(*pparams,4);
7407 if (*pparams == NULL) {
7408 reply_nterror(req, NT_STATUS_NO_MEMORY);
7413 SSVAL(params,0,0); /* No changes */
7414 SSVAL(params,2,0); /* No EA errors */
7416 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7421 /****************************************************************************
7422 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7423 ****************************************************************************/
7425 static void call_trans2getdfsreferral(connection_struct *conn,
7426 struct smb_request *req,
7427 char **pparams, int total_params,
7428 char **ppdata, int total_data,
7429 unsigned int max_data_bytes)
7431 char *params = *pparams;
7432 char *pathname = NULL;
7434 int max_referral_level;
7435 NTSTATUS status = NT_STATUS_OK;
7436 TALLOC_CTX *ctx = talloc_tos();
7438 DEBUG(10,("call_trans2getdfsreferral\n"));
7440 if (total_params < 3) {
7441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7445 max_referral_level = SVAL(params,0);
7447 if(!lp_host_msdfs()) {
7448 reply_doserror(req, ERRDOS, ERRbadfunc);
7452 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7453 total_params - 2, STR_TERMINATE);
7455 reply_nterror(req, NT_STATUS_NOT_FOUND);
7458 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7459 ppdata,&status)) < 0) {
7460 reply_nterror(req, status);
7464 SSVAL(req->inbuf, smb_flg2,
7465 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7466 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7471 #define LMCAT_SPL 0x53
7472 #define LMFUNC_GETJOBID 0x60
7474 /****************************************************************************
7475 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7476 ****************************************************************************/
7478 static void call_trans2ioctl(connection_struct *conn,
7479 struct smb_request *req,
7480 char **pparams, int total_params,
7481 char **ppdata, int total_data,
7482 unsigned int max_data_bytes)
7484 char *pdata = *ppdata;
7485 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7487 /* check for an invalid fid before proceeding */
7490 reply_doserror(req, ERRDOS, ERRbadfid);
7494 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7495 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7496 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7497 if (*ppdata == NULL) {
7498 reply_nterror(req, NT_STATUS_NO_MEMORY);
7503 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7504 CAN ACCEPT THIS IN UNICODE. JRA. */
7506 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7507 srvstr_push(pdata, req->flags2, pdata + 2,
7508 global_myname(), 15,
7509 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7510 srvstr_push(pdata, req->flags2, pdata+18,
7511 lp_servicename(SNUM(conn)), 13,
7512 STR_ASCII|STR_TERMINATE); /* Service name */
7513 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7518 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7519 reply_doserror(req, ERRSRV, ERRerror);
7522 /****************************************************************************
7523 Reply to a SMBfindclose (stop trans2 directory search).
7524 ****************************************************************************/
7526 void reply_findclose(struct smb_request *req)
7530 START_PROFILE(SMBfindclose);
7533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7534 END_PROFILE(SMBfindclose);
7538 dptr_num = SVALS(req->vwv+0, 0);
7540 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7542 dptr_close(&dptr_num);
7544 reply_outbuf(req, 0, 0);
7546 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7548 END_PROFILE(SMBfindclose);
7552 /****************************************************************************
7553 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7554 ****************************************************************************/
7556 void reply_findnclose(struct smb_request *req)
7560 START_PROFILE(SMBfindnclose);
7563 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7564 END_PROFILE(SMBfindnclose);
7568 dptr_num = SVAL(req->vwv+0, 0);
7570 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7572 /* We never give out valid handles for a
7573 findnotifyfirst - so any dptr_num is ok here.
7576 reply_outbuf(req, 0, 0);
7578 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7580 END_PROFILE(SMBfindnclose);
7584 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7585 struct trans_state *state)
7587 if (Protocol >= PROTOCOL_NT1) {
7588 req->flags2 |= 0x40; /* IS_LONG_NAME */
7589 SSVAL(req->inbuf,smb_flg2,req->flags2);
7592 if (conn->encrypt_level == Required && !req->encrypted) {
7593 if (state->call != TRANSACT2_QFSINFO &&
7594 state->call != TRANSACT2_SETFSINFO) {
7595 DEBUG(0,("handle_trans2: encryption required "
7597 (unsigned int)state->call));
7598 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7603 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7605 /* Now we must call the relevant TRANS2 function */
7606 switch(state->call) {
7607 case TRANSACT2_OPEN:
7609 START_PROFILE(Trans2_open);
7610 call_trans2open(conn, req,
7611 &state->param, state->total_param,
7612 &state->data, state->total_data,
7613 state->max_data_return);
7614 END_PROFILE(Trans2_open);
7618 case TRANSACT2_FINDFIRST:
7620 START_PROFILE(Trans2_findfirst);
7621 call_trans2findfirst(conn, req,
7622 &state->param, state->total_param,
7623 &state->data, state->total_data,
7624 state->max_data_return);
7625 END_PROFILE(Trans2_findfirst);
7629 case TRANSACT2_FINDNEXT:
7631 START_PROFILE(Trans2_findnext);
7632 call_trans2findnext(conn, req,
7633 &state->param, state->total_param,
7634 &state->data, state->total_data,
7635 state->max_data_return);
7636 END_PROFILE(Trans2_findnext);
7640 case TRANSACT2_QFSINFO:
7642 START_PROFILE(Trans2_qfsinfo);
7643 call_trans2qfsinfo(conn, req,
7644 &state->param, state->total_param,
7645 &state->data, state->total_data,
7646 state->max_data_return);
7647 END_PROFILE(Trans2_qfsinfo);
7651 case TRANSACT2_SETFSINFO:
7653 START_PROFILE(Trans2_setfsinfo);
7654 call_trans2setfsinfo(conn, req,
7655 &state->param, state->total_param,
7656 &state->data, state->total_data,
7657 state->max_data_return);
7658 END_PROFILE(Trans2_setfsinfo);
7662 case TRANSACT2_QPATHINFO:
7663 case TRANSACT2_QFILEINFO:
7665 START_PROFILE(Trans2_qpathinfo);
7666 call_trans2qfilepathinfo(conn, req, state->call,
7667 &state->param, state->total_param,
7668 &state->data, state->total_data,
7669 state->max_data_return);
7670 END_PROFILE(Trans2_qpathinfo);
7674 case TRANSACT2_SETPATHINFO:
7675 case TRANSACT2_SETFILEINFO:
7677 START_PROFILE(Trans2_setpathinfo);
7678 call_trans2setfilepathinfo(conn, req, state->call,
7679 &state->param, state->total_param,
7680 &state->data, state->total_data,
7681 state->max_data_return);
7682 END_PROFILE(Trans2_setpathinfo);
7686 case TRANSACT2_FINDNOTIFYFIRST:
7688 START_PROFILE(Trans2_findnotifyfirst);
7689 call_trans2findnotifyfirst(conn, req,
7690 &state->param, state->total_param,
7691 &state->data, state->total_data,
7692 state->max_data_return);
7693 END_PROFILE(Trans2_findnotifyfirst);
7697 case TRANSACT2_FINDNOTIFYNEXT:
7699 START_PROFILE(Trans2_findnotifynext);
7700 call_trans2findnotifynext(conn, req,
7701 &state->param, state->total_param,
7702 &state->data, state->total_data,
7703 state->max_data_return);
7704 END_PROFILE(Trans2_findnotifynext);
7708 case TRANSACT2_MKDIR:
7710 START_PROFILE(Trans2_mkdir);
7711 call_trans2mkdir(conn, req,
7712 &state->param, state->total_param,
7713 &state->data, state->total_data,
7714 state->max_data_return);
7715 END_PROFILE(Trans2_mkdir);
7719 case TRANSACT2_GET_DFS_REFERRAL:
7721 START_PROFILE(Trans2_get_dfs_referral);
7722 call_trans2getdfsreferral(conn, req,
7723 &state->param, state->total_param,
7724 &state->data, state->total_data,
7725 state->max_data_return);
7726 END_PROFILE(Trans2_get_dfs_referral);
7730 case TRANSACT2_IOCTL:
7732 START_PROFILE(Trans2_ioctl);
7733 call_trans2ioctl(conn, req,
7734 &state->param, state->total_param,
7735 &state->data, state->total_data,
7736 state->max_data_return);
7737 END_PROFILE(Trans2_ioctl);
7742 /* Error in request */
7743 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7744 reply_doserror(req, ERRSRV,ERRerror);
7748 /****************************************************************************
7749 Reply to a SMBtrans2.
7750 ****************************************************************************/
7752 void reply_trans2(struct smb_request *req)
7754 connection_struct *conn = req->conn;
7759 unsigned int tran_call;
7760 struct trans_state *state;
7763 START_PROFILE(SMBtrans2);
7765 if (req->wct < 14) {
7766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7767 END_PROFILE(SMBtrans2);
7771 dsoff = SVAL(req->vwv+12, 0);
7772 dscnt = SVAL(req->vwv+11, 0);
7773 psoff = SVAL(req->vwv+10, 0);
7774 pscnt = SVAL(req->vwv+9, 0);
7775 tran_call = SVAL(req->vwv+14, 0);
7777 result = allow_new_trans(conn->pending_trans, req->mid);
7778 if (!NT_STATUS_IS_OK(result)) {
7779 DEBUG(2, ("Got invalid trans2 request: %s\n",
7780 nt_errstr(result)));
7781 reply_nterror(req, result);
7782 END_PROFILE(SMBtrans2);
7787 switch (tran_call) {
7788 /* List the allowed trans2 calls on IPC$ */
7789 case TRANSACT2_OPEN:
7790 case TRANSACT2_GET_DFS_REFERRAL:
7791 case TRANSACT2_QFILEINFO:
7792 case TRANSACT2_QFSINFO:
7793 case TRANSACT2_SETFSINFO:
7796 reply_doserror(req, ERRSRV, ERRaccess);
7797 END_PROFILE(SMBtrans2);
7802 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7803 DEBUG(0, ("talloc failed\n"));
7804 reply_nterror(req, NT_STATUS_NO_MEMORY);
7805 END_PROFILE(SMBtrans2);
7809 state->cmd = SMBtrans2;
7811 state->mid = req->mid;
7812 state->vuid = req->vuid;
7813 state->setup_count = SVAL(req->vwv+13, 0);
7814 state->setup = NULL;
7815 state->total_param = SVAL(req->vwv+0, 0);
7816 state->param = NULL;
7817 state->total_data = SVAL(req->vwv+1, 0);
7819 state->max_param_return = SVAL(req->vwv+2, 0);
7820 state->max_data_return = SVAL(req->vwv+3, 0);
7821 state->max_setup_return = SVAL(req->vwv+4, 0);
7822 state->close_on_completion = BITSETW(req->vwv+5, 0);
7823 state->one_way = BITSETW(req->vwv+5, 1);
7825 state->call = tran_call;
7827 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7828 is so as a sanity check */
7829 if (state->setup_count != 1) {
7831 * Need to have rc=0 for ioctl to get job id for OS/2.
7832 * Network printing will fail if function is not successful.
7833 * Similar function in reply.c will be used if protocol
7834 * is LANMAN1.0 instead of LM1.2X002.
7835 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7836 * outbuf doesn't have to be set(only job id is used).
7838 if ( (state->setup_count == 4)
7839 && (tran_call == TRANSACT2_IOCTL)
7840 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7841 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7842 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7844 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7845 DEBUG(2,("Transaction is %d\n",tran_call));
7847 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7848 END_PROFILE(SMBtrans2);
7853 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7856 if (state->total_data) {
7858 if (trans_oob(state->total_data, 0, dscnt)
7859 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7863 /* Can't use talloc here, the core routines do realloc on the
7864 * params and data. */
7865 state->data = (char *)SMB_MALLOC(state->total_data);
7866 if (state->data == NULL) {
7867 DEBUG(0,("reply_trans2: data malloc fail for %u "
7868 "bytes !\n", (unsigned int)state->total_data));
7870 reply_nterror(req, NT_STATUS_NO_MEMORY);
7871 END_PROFILE(SMBtrans2);
7875 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7878 if (state->total_param) {
7880 if (trans_oob(state->total_param, 0, pscnt)
7881 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7885 /* Can't use talloc here, the core routines do realloc on the
7886 * params and data. */
7887 state->param = (char *)SMB_MALLOC(state->total_param);
7888 if (state->param == NULL) {
7889 DEBUG(0,("reply_trans: param malloc fail for %u "
7890 "bytes !\n", (unsigned int)state->total_param));
7891 SAFE_FREE(state->data);
7893 reply_nterror(req, NT_STATUS_NO_MEMORY);
7894 END_PROFILE(SMBtrans2);
7898 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7901 state->received_data = dscnt;
7902 state->received_param = pscnt;
7904 if ((state->received_param == state->total_param) &&
7905 (state->received_data == state->total_data)) {
7907 handle_trans2(conn, req, state);
7909 SAFE_FREE(state->data);
7910 SAFE_FREE(state->param);
7912 END_PROFILE(SMBtrans2);
7916 DLIST_ADD(conn->pending_trans, state);
7918 /* We need to send an interim response then receive the rest
7919 of the parameter/data bytes */
7920 reply_outbuf(req, 0, 0);
7921 show_msg((char *)req->outbuf);
7922 END_PROFILE(SMBtrans2);
7927 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7928 SAFE_FREE(state->data);
7929 SAFE_FREE(state->param);
7931 END_PROFILE(SMBtrans2);
7932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7936 /****************************************************************************
7937 Reply to a SMBtranss2
7938 ****************************************************************************/
7940 void reply_transs2(struct smb_request *req)
7942 connection_struct *conn = req->conn;
7943 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7944 struct trans_state *state;
7946 START_PROFILE(SMBtranss2);
7948 show_msg((char *)req->inbuf);
7951 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7952 END_PROFILE(SMBtranss2);
7956 for (state = conn->pending_trans; state != NULL;
7957 state = state->next) {
7958 if (state->mid == req->mid) {
7963 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7964 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7965 END_PROFILE(SMBtranss2);
7969 /* Revise state->total_param and state->total_data in case they have
7970 changed downwards */
7972 if (SVAL(req->vwv+0, 0) < state->total_param)
7973 state->total_param = SVAL(req->vwv+0, 0);
7974 if (SVAL(req->vwv+1, 0) < state->total_data)
7975 state->total_data = SVAL(req->vwv+1, 0);
7977 pcnt = SVAL(req->vwv+2, 0);
7978 poff = SVAL(req->vwv+3, 0);
7979 pdisp = SVAL(req->vwv+4, 0);
7981 dcnt = SVAL(req->vwv+5, 0);
7982 doff = SVAL(req->vwv+6, 0);
7983 ddisp = SVAL(req->vwv+7, 0);
7985 state->received_param += pcnt;
7986 state->received_data += dcnt;
7988 if ((state->received_data > state->total_data) ||
7989 (state->received_param > state->total_param))
7993 if (trans_oob(state->total_param, pdisp, pcnt)
7994 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7997 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8001 if (trans_oob(state->total_data, ddisp, dcnt)
8002 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8005 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8008 if ((state->received_param < state->total_param) ||
8009 (state->received_data < state->total_data)) {
8010 END_PROFILE(SMBtranss2);
8014 handle_trans2(conn, req, state);
8016 DLIST_REMOVE(conn->pending_trans, state);
8017 SAFE_FREE(state->data);
8018 SAFE_FREE(state->param);
8021 END_PROFILE(SMBtranss2);
8026 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8027 DLIST_REMOVE(conn->pending_trans, state);
8028 SAFE_FREE(state->data);
8029 SAFE_FREE(state->param);
8031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8032 END_PROFILE(SMBtranss2);