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/>.
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct *conn,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
44 const SMB_STRUCT_STAT *psbuf);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
53 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type = get_remote_arch();
57 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58 val = SMB_ROUNDUP(val,rval);
63 /********************************************************************
64 Given a stat buffer return the allocated size on disk, taking into
66 ********************************************************************/
68 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
72 if(S_ISDIR(sbuf->st_mode)) {
76 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
77 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
79 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
82 if (fsp && fsp->initial_allocation_size)
83 ret = MAX(ret,fsp->initial_allocation_size);
85 return smb_roundup(conn, ret);
88 /****************************************************************************
89 Utility functions for dealing with extended attributes.
90 ****************************************************************************/
92 /****************************************************************************
93 Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
96 static bool samba_private_attr_name(const char *unix_ea_name)
98 static const char *prohibited_ea_names[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME,
100 SAMBA_XATTR_DOS_ATTRIB,
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
110 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
111 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
117 /****************************************************************************
118 Get one EA value. Fill in a struct ea_struct.
119 ****************************************************************************/
121 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
122 files_struct *fsp, const char *fname,
123 const char *ea_name, struct ea_struct *pea)
125 /* Get the value of this xattr. Max size is 64k. */
126 size_t attr_size = 256;
132 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 return NT_STATUS_NO_MEMORY;
137 if (fsp && fsp->fh->fd != -1) {
138 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
140 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
143 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
149 return map_nt_error_from_unix(errno);
152 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
153 dump_data(10, (uint8 *)val, sizeret);
156 if (strnequal(ea_name, "user.", 5)) {
157 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
159 pea->name = talloc_strdup(mem_ctx, ea_name);
161 if (pea->name == NULL) {
163 return NT_STATUS_NO_MEMORY;
165 pea->value.data = (unsigned char *)val;
166 pea->value.length = (size_t)sizeret;
170 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
171 files_struct *fsp, const char *fname,
172 char ***pnames, size_t *pnum_names)
174 /* Get a list of all xattrs. Max namesize is 64k. */
175 size_t ea_namelist_size = 1024;
176 char *ea_namelist = NULL;
183 if (!lp_ea_support(SNUM(conn))) {
190 * TALLOC the result early to get the talloc hierarchy right.
193 names = TALLOC_ARRAY(mem_ctx, char *, 1);
195 DEBUG(0, ("talloc failed\n"));
196 return NT_STATUS_NO_MEMORY;
199 while (ea_namelist_size <= 65536) {
201 ea_namelist = TALLOC_REALLOC_ARRAY(
202 names, ea_namelist, char, ea_namelist_size);
203 if (ea_namelist == NULL) {
204 DEBUG(0, ("talloc failed\n"));
206 return NT_STATUS_NO_MEMORY;
209 if (fsp && fsp->fh->fd != -1) {
210 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
213 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
217 if ((sizeret == -1) && (errno == ERANGE)) {
218 ea_namelist_size *= 2;
227 return map_nt_error_from_unix(errno);
230 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
231 (unsigned int)sizeret));
241 * Ensure the result is 0-terminated
244 if (ea_namelist[sizeret-1] != '\0') {
246 return NT_STATUS_INTERNAL_ERROR;
254 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
258 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
260 DEBUG(0, ("talloc failed\n"));
262 return NT_STATUS_NO_MEMORY;
268 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
269 names[num_names++] = p;
273 *pnum_names = num_names;
277 /****************************************************************************
278 Return a linked list of the total EA's. Plus the total size
279 ****************************************************************************/
281 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
282 const char *fname, size_t *pea_total_len)
284 /* Get a list of all xattrs. Max namesize is 64k. */
287 struct ea_list *ea_list_head = NULL;
292 if (!lp_ea_support(SNUM(conn))) {
296 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
299 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
303 for (i=0; i<num_names; i++) {
304 struct ea_list *listp;
307 if (strnequal(names[i], "system.", 7)
308 || samba_private_attr_name(names[i]))
311 listp = TALLOC_P(mem_ctx, struct ea_list);
316 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
322 push_ascii_fstring(dos_ea_name, listp->ea.name);
325 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
327 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
328 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
329 (unsigned int)listp->ea.value.length));
331 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
335 /* Add on 4 for total length. */
336 if (*pea_total_len) {
340 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
341 (unsigned int)*pea_total_len));
346 /****************************************************************************
347 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
349 ****************************************************************************/
351 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
352 connection_struct *conn, struct ea_list *ea_list)
354 unsigned int ret_data_size = 4;
357 SMB_ASSERT(total_data_size >= 4);
359 if (!lp_ea_support(SNUM(conn))) {
364 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
367 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
368 dos_namelen = strlen(dos_ea_name);
369 if (dos_namelen > 255 || dos_namelen == 0) {
372 if (ea_list->ea.value.length > 65535) {
375 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
379 /* We know we have room. */
380 SCVAL(p,0,ea_list->ea.flags);
381 SCVAL(p,1,dos_namelen);
382 SSVAL(p,2,ea_list->ea.value.length);
383 fstrcpy(p+4, dos_ea_name);
384 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
386 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
387 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
390 ret_data_size = PTR_DIFF(p, pdata);
391 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
392 SIVAL(pdata,0,ret_data_size);
393 return ret_data_size;
396 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
398 size_t total_ea_len = 0;
399 TALLOC_CTX *mem_ctx = NULL;
401 if (!lp_ea_support(SNUM(conn))) {
404 mem_ctx = talloc_tos();
405 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
409 /****************************************************************************
410 Ensure the EA name is case insensitive by matching any existing EA name.
411 ****************************************************************************/
413 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
416 TALLOC_CTX *mem_ctx = talloc_tos();
417 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
419 for (; ea_list; ea_list = ea_list->next) {
420 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
421 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
422 &unix_ea_name[5], ea_list->ea.name));
423 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
429 /****************************************************************************
430 Set or delete an extended attribute.
431 ****************************************************************************/
433 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
435 if (!lp_ea_support(SNUM(conn))) {
436 return NT_STATUS_EAS_NOT_SUPPORTED;
439 for (;ea_list; ea_list = ea_list->next) {
441 fstring unix_ea_name;
443 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
444 fstrcat(unix_ea_name, ea_list->ea.name);
446 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
448 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
450 if (samba_private_attr_name(unix_ea_name)) {
451 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
452 return NT_STATUS_ACCESS_DENIED;
455 if (ea_list->ea.value.length == 0) {
456 /* Remove the attribute. */
457 if (fsp && (fsp->fh->fd != -1)) {
458 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
459 unix_ea_name, fsp->fsp_name));
460 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
462 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
463 unix_ea_name, fname));
464 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
467 /* Removing a non existent attribute always succeeds. */
468 if (ret == -1 && errno == ENOATTR) {
469 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
475 if (fsp && (fsp->fh->fd != -1)) {
476 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
477 unix_ea_name, fsp->fsp_name));
478 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
479 ea_list->ea.value.data, ea_list->ea.value.length, 0);
481 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
482 unix_ea_name, fname));
483 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
484 ea_list->ea.value.data, ea_list->ea.value.length, 0);
490 if (errno == ENOTSUP) {
491 return NT_STATUS_EAS_NOT_SUPPORTED;
494 return map_nt_error_from_unix(errno);
500 /****************************************************************************
501 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
502 ****************************************************************************/
504 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
506 struct ea_list *ea_list_head = NULL;
509 while (offset + 2 < data_size) {
510 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
511 unsigned int namelen = CVAL(pdata,offset);
513 offset++; /* Go past the namelen byte. */
515 /* integer wrap paranioa. */
516 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
517 (offset > data_size) || (namelen > data_size) ||
518 (offset + namelen >= data_size)) {
521 /* Ensure the name is null terminated. */
522 if (pdata[offset + namelen] != '\0') {
525 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
530 offset += (namelen + 1); /* Go past the name + terminating zero. */
531 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
532 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
538 /****************************************************************************
539 Read one EA list entry from the buffer.
540 ****************************************************************************/
542 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
544 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
546 unsigned int namelen;
556 eal->ea.flags = CVAL(pdata,0);
557 namelen = CVAL(pdata,1);
558 val_len = SVAL(pdata,2);
560 if (4 + namelen + 1 + val_len > data_size) {
564 /* Ensure the name is null terminated. */
565 if (pdata[namelen + 4] != '\0') {
568 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
573 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
574 if (!eal->ea.value.data) {
578 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
580 /* Ensure we're null terminated just in case we print the value. */
581 eal->ea.value.data[val_len] = '\0';
582 /* But don't count the null. */
583 eal->ea.value.length--;
586 *pbytes_used = 4 + namelen + 1 + val_len;
589 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
590 dump_data(10, eal->ea.value.data, eal->ea.value.length);
595 /****************************************************************************
596 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
597 ****************************************************************************/
599 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
601 struct ea_list *ea_list_head = NULL;
603 size_t bytes_used = 0;
605 while (offset < data_size) {
606 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
612 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
613 offset += bytes_used;
619 /****************************************************************************
620 Count the total EA size needed.
621 ****************************************************************************/
623 static size_t ea_list_size(struct ea_list *ealist)
626 struct ea_list *listp;
629 for (listp = ealist; listp; listp = listp->next) {
630 push_ascii_fstring(dos_ea_name, listp->ea.name);
631 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
633 /* Add on 4 for total length. */
641 /****************************************************************************
642 Return a union of EA's from a file list and a list of names.
643 The TALLOC context for the two lists *MUST* be identical as we steal
644 memory from one list to add to another. JRA.
645 ****************************************************************************/
647 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
649 struct ea_list *nlistp, *flistp;
651 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
652 for (flistp = file_list; flistp; flistp = flistp->next) {
653 if (strequal(nlistp->ea.name, flistp->ea.name)) {
659 /* Copy the data from this entry. */
660 nlistp->ea.flags = flistp->ea.flags;
661 nlistp->ea.value = flistp->ea.value;
664 nlistp->ea.flags = 0;
665 ZERO_STRUCT(nlistp->ea.value);
669 *total_ea_len = ea_list_size(name_list);
673 /****************************************************************************
674 Send the required number of replies back.
675 We assume all fields other than the data fields are
676 set correctly for the type of call.
677 HACK ! Always assumes smb_setup field is zero.
678 ****************************************************************************/
680 void send_trans2_replies(connection_struct *conn,
681 struct smb_request *req,
688 /* As we are using a protocol > LANMAN1 then the max_send
689 variable must have been set in the sessetupX call.
690 This takes precedence over the max_xmit field in the
691 global struct. These different max_xmit variables should
692 be merged as this is now too confusing */
694 int data_to_send = datasize;
695 int params_to_send = paramsize;
697 const char *pp = params;
698 const char *pd = pdata;
699 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
700 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
701 int data_alignment_offset = 0;
702 bool overflow = False;
704 /* Modify the data_to_send and datasize and set the error if
705 we're trying to send more than max_data_bytes. We still send
706 the part of the packet(s) that fit. Strange, but needed
709 if (max_data_bytes > 0 && datasize > max_data_bytes) {
710 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
711 max_data_bytes, datasize ));
712 datasize = data_to_send = max_data_bytes;
716 /* If there genuinely are no parameters or data to send just send the empty packet */
718 if(params_to_send == 0 && data_to_send == 0) {
719 reply_outbuf(req, 10, 0);
720 show_msg((char *)req->outbuf);
724 /* When sending params and data ensure that both are nicely aligned */
725 /* Only do this alignment when there is also data to send - else
726 can cause NT redirector problems. */
728 if (((params_to_send % 4) != 0) && (data_to_send != 0))
729 data_alignment_offset = 4 - (params_to_send % 4);
731 /* Space is bufsize minus Netbios over TCP header minus SMB header */
732 /* The alignment_offset is to align the param bytes on an even byte
733 boundary. NT 4.0 Beta needs this to work correctly. */
735 useable_space = max_send - (smb_size
738 + data_alignment_offset);
740 if (useable_space < 0) {
741 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
742 "= %d!!!", useable_space));
743 exit_server_cleanly("send_trans2_replies: Not enough space");
746 while (params_to_send || data_to_send) {
747 /* Calculate whether we will totally or partially fill this packet */
749 total_sent_thistime = params_to_send + data_to_send;
751 /* We can never send more than useable_space */
753 * Note that 'useable_space' does not include the alignment offsets,
754 * but we must include the alignment offsets in the calculation of
755 * the length of the data we send over the wire, as the alignment offsets
756 * are sent here. Fix from Marc_Jacobsen@hp.com.
759 total_sent_thistime = MIN(total_sent_thistime, useable_space);
761 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
762 + data_alignment_offset);
764 /* Set total params and data to be sent */
765 SSVAL(req->outbuf,smb_tprcnt,paramsize);
766 SSVAL(req->outbuf,smb_tdrcnt,datasize);
768 /* Calculate how many parameters and data we can fit into
769 * this packet. Parameters get precedence
772 params_sent_thistime = MIN(params_to_send,useable_space);
773 data_sent_thistime = useable_space - params_sent_thistime;
774 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
776 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
778 /* smb_proff is the offset from the start of the SMB header to the
779 parameter bytes, however the first 4 bytes of outbuf are
780 the Netbios over TCP header. Thus use smb_base() to subtract
781 them from the calculation */
783 SSVAL(req->outbuf,smb_proff,
784 ((smb_buf(req->outbuf)+alignment_offset)
785 - smb_base(req->outbuf)));
787 if(params_sent_thistime == 0)
788 SSVAL(req->outbuf,smb_prdisp,0);
790 /* Absolute displacement of param bytes sent in this packet */
791 SSVAL(req->outbuf,smb_prdisp,pp - params);
793 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
794 if(data_sent_thistime == 0) {
795 SSVAL(req->outbuf,smb_droff,0);
796 SSVAL(req->outbuf,smb_drdisp, 0);
798 /* The offset of the data bytes is the offset of the
799 parameter bytes plus the number of parameters being sent this time */
800 SSVAL(req->outbuf, smb_droff,
801 ((smb_buf(req->outbuf)+alignment_offset)
802 - smb_base(req->outbuf))
803 + params_sent_thistime + data_alignment_offset);
804 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
807 /* Initialize the padding for alignment */
809 if (alignment_offset != 0) {
810 memset(smb_buf(req->outbuf), 0, alignment_offset);
813 /* Copy the param bytes into the packet */
815 if(params_sent_thistime) {
816 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
817 params_sent_thistime);
820 /* Copy in the data bytes */
821 if(data_sent_thistime) {
822 if (data_alignment_offset != 0) {
823 memset((smb_buf(req->outbuf)+alignment_offset+
824 params_sent_thistime), 0,
825 data_alignment_offset);
827 memcpy(smb_buf(req->outbuf)+alignment_offset
828 +params_sent_thistime+data_alignment_offset,
829 pd,data_sent_thistime);
832 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
833 params_sent_thistime, data_sent_thistime, useable_space));
834 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
835 params_to_send, data_to_send, paramsize, datasize));
838 error_packet_set((char *)req->outbuf,
839 ERRDOS,ERRbufferoverflow,
840 STATUS_BUFFER_OVERFLOW,
844 /* Send the packet */
845 show_msg((char *)req->outbuf);
846 if (!srv_send_smb(smbd_server_fd(),
848 IS_CONN_ENCRYPTED(conn)))
849 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
851 TALLOC_FREE(req->outbuf);
853 pp += params_sent_thistime;
854 pd += data_sent_thistime;
856 params_to_send -= params_sent_thistime;
857 data_to_send -= data_sent_thistime;
860 if(params_to_send < 0 || data_to_send < 0) {
861 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
862 params_to_send, data_to_send));
870 /****************************************************************************
871 Reply to a TRANSACT2_OPEN.
872 ****************************************************************************/
874 static void call_trans2open(connection_struct *conn,
875 struct smb_request *req,
876 char **pparams, int total_params,
877 char **ppdata, int total_data,
878 unsigned int max_data_bytes)
880 char *params = *pparams;
881 char *pdata = *ppdata;
886 bool return_additional_info;
897 SMB_STRUCT_STAT sbuf;
900 struct ea_list *ea_list = NULL;
905 uint32 create_disposition;
906 uint32 create_options = 0;
907 TALLOC_CTX *ctx = talloc_tos();
910 * Ensure we have enough parameters to perform the operation.
913 if (total_params < 29) {
914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
918 flags = SVAL(params, 0);
919 deny_mode = SVAL(params, 2);
920 open_attr = SVAL(params,6);
921 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
922 if (oplock_request) {
923 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
927 return_additional_info = BITSETW(params,0);
928 open_sattr = SVAL(params, 4);
929 open_time = make_unix_date3(params+8);
931 open_ofun = SVAL(params,12);
932 open_size = IVAL(params,14);
936 reply_doserror(req, ERRSRV, ERRaccess);
940 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
941 total_params - 28, STR_TERMINATE,
943 if (!NT_STATUS_IS_OK(status)) {
944 reply_nterror(req, status);
948 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
949 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
950 (unsigned int)open_ofun, open_size));
952 if (open_ofun == 0) {
953 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
957 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
962 reply_doserror(req, ERRDOS, ERRbadaccess);
966 /* Any data in this call is an EA list. */
967 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
968 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
972 if (total_data != 4) {
973 if (total_data < 10) {
974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
978 if (IVAL(pdata,0) > total_data) {
979 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
980 IVAL(pdata,0), (unsigned int)total_data));
981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
985 ea_list = read_ea_list(talloc_tos(), pdata + 4,
988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
991 } else if (IVAL(pdata,0) != 4) {
992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
996 status = create_file(conn, /* conn */
998 0, /* root_dir_fid */
1000 access_mask, /* access_mask */
1001 share_mode, /* share_access */
1002 create_disposition, /* create_disposition*/
1003 create_options, /* create_options */
1004 open_attr, /* file_attributes */
1005 oplock_request, /* oplock_request */
1006 open_size, /* allocation_size */
1008 ea_list, /* ea_list */
1010 &smb_action, /* pinfo */
1013 if (!NT_STATUS_IS_OK(status)) {
1014 if (open_was_deferred(req->mid)) {
1015 /* We have re-scheduled this call. */
1018 reply_openerror(req, status);
1022 size = get_file_size(sbuf);
1023 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1024 mtime = sbuf.st_mtime;
1025 inode = sbuf.st_ino;
1027 close_file(fsp,ERROR_CLOSE);
1028 reply_doserror(req, ERRDOS,ERRnoaccess);
1032 /* Realloc the size of parameters and data we will return */
1033 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1034 if(*pparams == NULL ) {
1035 reply_nterror(req, NT_STATUS_NO_MEMORY);
1040 SSVAL(params,0,fsp->fnum);
1041 SSVAL(params,2,fattr);
1042 srv_put_dos_date2(params,4, mtime);
1043 SIVAL(params,8, (uint32)size);
1044 SSVAL(params,12,deny_mode);
1045 SSVAL(params,14,0); /* open_type - file or directory. */
1046 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1048 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1049 smb_action |= EXTENDED_OPLOCK_GRANTED;
1052 SSVAL(params,18,smb_action);
1055 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1057 SIVAL(params,20,inode);
1058 SSVAL(params,24,0); /* Padding. */
1060 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1061 SIVAL(params, 26, ea_size);
1063 SIVAL(params, 26, 0);
1066 /* Send the required number of replies */
1067 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1070 /*********************************************************
1071 Routine to check if a given string matches exactly.
1072 as a special case a mask of "." does NOT match. That
1073 is required for correct wildcard semantics
1074 Case can be significant or not.
1075 **********************************************************/
1077 static bool exact_match(connection_struct *conn,
1081 if (mask[0] == '.' && mask[1] == 0)
1083 if (conn->case_sensitive)
1084 return strcmp(str,mask)==0;
1085 if (StrCaseCmp(str,mask) != 0) {
1088 if (dptr_has_wild(conn->dirptr)) {
1094 /****************************************************************************
1095 Return the filetype for UNIX extensions.
1096 ****************************************************************************/
1098 static uint32 unix_filetype(mode_t mode)
1101 return UNIX_TYPE_FILE;
1102 else if(S_ISDIR(mode))
1103 return UNIX_TYPE_DIR;
1105 else if(S_ISLNK(mode))
1106 return UNIX_TYPE_SYMLINK;
1109 else if(S_ISCHR(mode))
1110 return UNIX_TYPE_CHARDEV;
1113 else if(S_ISBLK(mode))
1114 return UNIX_TYPE_BLKDEV;
1117 else if(S_ISFIFO(mode))
1118 return UNIX_TYPE_FIFO;
1121 else if(S_ISSOCK(mode))
1122 return UNIX_TYPE_SOCKET;
1125 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1126 return UNIX_TYPE_UNKNOWN;
1129 /****************************************************************************
1130 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1131 ****************************************************************************/
1133 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1135 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1136 SMB_STRUCT_STAT *psbuf,
1138 enum perm_type ptype,
1143 if (perms == SMB_MODE_NO_CHANGE) {
1144 if (!VALID_STAT(*psbuf)) {
1145 return NT_STATUS_INVALID_PARAMETER;
1147 *ret_perms = psbuf->st_mode;
1148 return NT_STATUS_OK;
1152 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1153 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1154 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1155 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1156 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1157 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1158 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1159 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1160 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1162 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1165 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1168 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1173 /* Apply mode mask */
1174 ret &= lp_create_mask(SNUM(conn));
1175 /* Add in force bits */
1176 ret |= lp_force_create_mode(SNUM(conn));
1179 ret &= lp_dir_mask(SNUM(conn));
1180 /* Add in force bits */
1181 ret |= lp_force_dir_mode(SNUM(conn));
1183 case PERM_EXISTING_FILE:
1184 /* Apply mode mask */
1185 ret &= lp_security_mask(SNUM(conn));
1186 /* Add in force bits */
1187 ret |= lp_force_security_mode(SNUM(conn));
1189 case PERM_EXISTING_DIR:
1190 /* Apply mode mask */
1191 ret &= lp_dir_security_mask(SNUM(conn));
1192 /* Add in force bits */
1193 ret |= lp_force_dir_security_mode(SNUM(conn));
1198 return NT_STATUS_OK;
1201 /****************************************************************************
1202 Needed to show the msdfs symlinks as directories. Modifies psbuf
1203 to be a directory if it's a msdfs link.
1204 ****************************************************************************/
1206 static bool check_msdfs_link(connection_struct *conn,
1207 const char *pathname,
1208 SMB_STRUCT_STAT *psbuf)
1210 int saved_errno = errno;
1211 if(lp_host_msdfs() &&
1212 lp_msdfs_root(SNUM(conn)) &&
1213 is_msdfs_link(conn, pathname, psbuf)) {
1215 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1218 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1219 errno = saved_errno;
1222 errno = saved_errno;
1227 /****************************************************************************
1228 Get a level dependent lanman2 dir entry.
1229 ****************************************************************************/
1231 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1232 connection_struct *conn,
1234 const char *path_mask,
1237 int requires_resume_key,
1243 int space_remaining,
1245 bool *got_exact_match,
1246 int *last_entry_off,
1247 struct ea_list *name_list)
1251 SMB_STRUCT_STAT sbuf;
1252 const char *mask = NULL;
1253 char *pathreal = NULL;
1254 const char *fname = NULL;
1255 char *p, *q, *pdata = *ppdata;
1259 SMB_OFF_T file_size = 0;
1260 SMB_BIG_UINT allocation_size = 0;
1262 struct timespec mdate_ts, adate_ts, create_date_ts;
1263 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1265 char *last_entry_ptr;
1267 uint32 nt_extmode; /* Used for NT connections instead of mode */
1268 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1269 bool check_mangled_names = lp_manglednames(conn->params);
1270 char mangled_name[13]; /* mangled 8.3 name. */
1272 *out_of_space = False;
1273 *got_exact_match = False;
1275 ZERO_STRUCT(mdate_ts);
1276 ZERO_STRUCT(adate_ts);
1277 ZERO_STRUCT(create_date_ts);
1279 if (!conn->dirptr) {
1283 p = strrchr_m(path_mask,'/');
1286 mask = talloc_strdup(ctx,"*.*");
1296 bool ms_dfs_link = False;
1298 /* Needed if we run out of space */
1299 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1300 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1303 * Due to bugs in NT client redirectors we are not using
1304 * resume keys any more - set them to zero.
1305 * Check out the related comments in findfirst/findnext.
1311 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1312 (long)conn->dirptr,curr_dirpos));
1319 * fname may get mangled, dname is never mangled.
1320 * Whenever we're accessing the filesystem we use
1321 * pathreal which is composed from dname.
1327 /* Mangle fname if it's an illegal name. */
1328 if (mangle_must_mangle(dname,conn->params)) {
1329 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1330 continue; /* Error - couldn't mangle. */
1332 fname = mangled_name;
1335 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1336 got_match = mask_match(fname, mask, conn->case_sensitive);
1339 if(!got_match && check_mangled_names &&
1340 !mangle_is_8_3(fname, False, conn->params)) {
1342 * It turns out that NT matches wildcards against
1343 * both long *and* short names. This may explain some
1344 * of the wildcard wierdness from old DOS clients
1345 * that some people have been seeing.... JRA.
1347 /* Force the mangling into 8.3. */
1348 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1349 continue; /* Error - couldn't mangle. */
1352 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1353 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1358 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1360 if (dont_descend && !isdots) {
1366 pathreal = talloc_asprintf(ctx,
1371 pathreal = talloc_asprintf(ctx,
1381 if (INFO_LEVEL_IS_UNIX(info_level)) {
1382 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1383 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1384 pathreal,strerror(errno)));
1385 TALLOC_FREE(pathreal);
1388 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1389 /* Needed to show the msdfs symlinks as
1392 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1394 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1395 pathreal,strerror(errno)));
1396 TALLOC_FREE(pathreal);
1402 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1404 mode = dos_mode(conn,pathreal,&sbuf);
1407 if (!dir_check_ftype(conn,mode,dirtype)) {
1408 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1409 TALLOC_FREE(pathreal);
1413 if (!(mode & aDIR)) {
1414 file_size = get_file_size(sbuf);
1416 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1418 mdate_ts = get_mtimespec(&sbuf);
1419 adate_ts = get_atimespec(&sbuf);
1420 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1422 if (ask_sharemode) {
1423 struct timespec write_time_ts;
1424 struct file_id fileid;
1426 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1427 get_file_infos(fileid, NULL, &write_time_ts);
1428 if (!null_timespec(write_time_ts)) {
1429 mdate_ts = write_time_ts;
1433 if (lp_dos_filetime_resolution(SNUM(conn))) {
1434 dos_filetime_timespec(&create_date_ts);
1435 dos_filetime_timespec(&mdate_ts);
1436 dos_filetime_timespec(&adate_ts);
1439 create_date = convert_timespec_to_time_t(create_date_ts);
1440 mdate = convert_timespec_to_time_t(mdate_ts);
1441 adate = convert_timespec_to_time_t(adate_ts);
1443 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1447 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1454 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1456 switch (info_level) {
1457 case SMB_FIND_INFO_STANDARD:
1458 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1459 if(requires_resume_key) {
1463 srv_put_dos_date2(p,0,create_date);
1464 srv_put_dos_date2(p,4,adate);
1465 srv_put_dos_date2(p,8,mdate);
1466 SIVAL(p,12,(uint32)file_size);
1467 SIVAL(p,16,(uint32)allocation_size);
1471 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1472 p += ucs2_align(base_data, p, 0);
1474 len = srvstr_push(base_data, flags2, p,
1475 fname, PTR_DIFF(end_data, p),
1477 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1479 SCVAL(nameptr, -1, len - 2);
1481 SCVAL(nameptr, -1, 0);
1485 SCVAL(nameptr, -1, len - 1);
1487 SCVAL(nameptr, -1, 0);
1493 case SMB_FIND_EA_SIZE:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1495 if(requires_resume_key) {
1499 srv_put_dos_date2(p,0,create_date);
1500 srv_put_dos_date2(p,4,adate);
1501 srv_put_dos_date2(p,8,mdate);
1502 SIVAL(p,12,(uint32)file_size);
1503 SIVAL(p,16,(uint32)allocation_size);
1506 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1507 SIVAL(p,22,ea_size); /* Extended attributes */
1511 len = srvstr_push(base_data, flags2,
1512 p, fname, PTR_DIFF(end_data, p),
1513 STR_TERMINATE | STR_NOALIGN);
1514 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1527 SCVAL(nameptr,0,len);
1529 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1532 case SMB_FIND_EA_LIST:
1534 struct ea_list *file_list = NULL;
1537 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1541 if(requires_resume_key) {
1545 srv_put_dos_date2(p,0,create_date);
1546 srv_put_dos_date2(p,4,adate);
1547 srv_put_dos_date2(p,8,mdate);
1548 SIVAL(p,12,(uint32)file_size);
1549 SIVAL(p,16,(uint32)allocation_size);
1551 p += 22; /* p now points to the EA area. */
1553 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1554 name_list = ea_list_union(name_list, file_list, &ea_len);
1556 /* We need to determine if this entry will fit in the space available. */
1557 /* Max string size is 255 bytes. */
1558 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1559 /* Move the dirptr back to prev_dirpos */
1560 dptr_SeekDir(conn->dirptr, prev_dirpos);
1561 *out_of_space = True;
1562 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1563 return False; /* Not finished - just out of space */
1566 /* Push the ea_data followed by the name. */
1567 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1569 len = srvstr_push(base_data, flags2,
1570 p + 1, fname, PTR_DIFF(end_data, p+1),
1571 STR_TERMINATE | STR_NOALIGN);
1572 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1585 SCVAL(nameptr,0,len);
1587 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1591 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1592 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1593 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1595 SIVAL(p,0,reskey); p += 4;
1596 put_long_date_timespec(p,create_date_ts); p += 8;
1597 put_long_date_timespec(p,adate_ts); p += 8;
1598 put_long_date_timespec(p,mdate_ts); p += 8;
1599 put_long_date_timespec(p,mdate_ts); p += 8;
1600 SOFF_T(p,0,file_size); p += 8;
1601 SOFF_T(p,0,allocation_size); p += 8;
1602 SIVAL(p,0,nt_extmode); p += 4;
1603 q = p; p += 4; /* q is placeholder for name length. */
1605 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1606 SIVAL(p,0,ea_size); /* Extended attributes */
1609 /* Clear the short name buffer. This is
1610 * IMPORTANT as not doing so will trigger
1611 * a Win2k client bug. JRA.
1613 if (!was_8_3 && check_mangled_names) {
1614 if (!name_to_8_3(fname,mangled_name,True,
1616 /* Error - mangle failed ! */
1617 memset(mangled_name,'\0',12);
1619 mangled_name[12] = 0;
1620 len = srvstr_push(base_data, flags2,
1621 p+2, mangled_name, 24,
1622 STR_UPPER|STR_UNICODE);
1624 memset(p + 2 + len,'\0',24 - len);
1631 len = srvstr_push(base_data, flags2, p,
1632 fname, PTR_DIFF(end_data, p),
1633 STR_TERMINATE_ASCII);
1636 SIVAL(p,0,0); /* Ensure any padding is null. */
1637 len = PTR_DIFF(p, pdata);
1638 len = (len + 3) & ~3;
1643 case SMB_FIND_FILE_DIRECTORY_INFO:
1644 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1646 SIVAL(p,0,reskey); p += 4;
1647 put_long_date_timespec(p,create_date_ts); p += 8;
1648 put_long_date_timespec(p,adate_ts); p += 8;
1649 put_long_date_timespec(p,mdate_ts); p += 8;
1650 put_long_date_timespec(p,mdate_ts); p += 8;
1651 SOFF_T(p,0,file_size); p += 8;
1652 SOFF_T(p,0,allocation_size); p += 8;
1653 SIVAL(p,0,nt_extmode); p += 4;
1654 len = srvstr_push(base_data, flags2,
1655 p + 4, fname, PTR_DIFF(end_data, p+4),
1656 STR_TERMINATE_ASCII);
1659 SIVAL(p,0,0); /* Ensure any padding is null. */
1660 len = PTR_DIFF(p, pdata);
1661 len = (len + 3) & ~3;
1666 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1667 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1669 SIVAL(p,0,reskey); p += 4;
1670 put_long_date_timespec(p,create_date_ts); p += 8;
1671 put_long_date_timespec(p,adate_ts); p += 8;
1672 put_long_date_timespec(p,mdate_ts); p += 8;
1673 put_long_date_timespec(p,mdate_ts); p += 8;
1674 SOFF_T(p,0,file_size); p += 8;
1675 SOFF_T(p,0,allocation_size); p += 8;
1676 SIVAL(p,0,nt_extmode); p += 4;
1677 q = p; p += 4; /* q is placeholder for name length. */
1679 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1680 SIVAL(p,0,ea_size); /* Extended attributes */
1683 len = srvstr_push(base_data, flags2, p,
1684 fname, PTR_DIFF(end_data, p),
1685 STR_TERMINATE_ASCII);
1689 SIVAL(p,0,0); /* Ensure any padding is null. */
1690 len = PTR_DIFF(p, pdata);
1691 len = (len + 3) & ~3;
1696 case SMB_FIND_FILE_NAMES_INFO:
1697 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1699 SIVAL(p,0,reskey); p += 4;
1701 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1702 acl on a dir (tridge) */
1703 len = srvstr_push(base_data, flags2, p,
1704 fname, PTR_DIFF(end_data, p),
1705 STR_TERMINATE_ASCII);
1708 SIVAL(p,0,0); /* Ensure any padding is null. */
1709 len = PTR_DIFF(p, pdata);
1710 len = (len + 3) & ~3;
1715 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1716 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1718 SIVAL(p,0,reskey); p += 4;
1719 put_long_date_timespec(p,create_date_ts); p += 8;
1720 put_long_date_timespec(p,adate_ts); p += 8;
1721 put_long_date_timespec(p,mdate_ts); p += 8;
1722 put_long_date_timespec(p,mdate_ts); p += 8;
1723 SOFF_T(p,0,file_size); p += 8;
1724 SOFF_T(p,0,allocation_size); p += 8;
1725 SIVAL(p,0,nt_extmode); p += 4;
1726 q = p; p += 4; /* q is placeholder for name length. */
1728 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1729 SIVAL(p,0,ea_size); /* Extended attributes */
1732 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1733 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1734 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1735 len = srvstr_push(base_data, flags2, p,
1736 fname, PTR_DIFF(end_data, p),
1737 STR_TERMINATE_ASCII);
1740 SIVAL(p,0,0); /* Ensure any padding is null. */
1741 len = PTR_DIFF(p, pdata);
1742 len = (len + 3) & ~3;
1747 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1748 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1749 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1751 SIVAL(p,0,reskey); p += 4;
1752 put_long_date_timespec(p,create_date_ts); p += 8;
1753 put_long_date_timespec(p,adate_ts); p += 8;
1754 put_long_date_timespec(p,mdate_ts); p += 8;
1755 put_long_date_timespec(p,mdate_ts); p += 8;
1756 SOFF_T(p,0,file_size); p += 8;
1757 SOFF_T(p,0,allocation_size); p += 8;
1758 SIVAL(p,0,nt_extmode); p += 4;
1759 q = p; p += 4; /* q is placeholder for name length */
1761 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1762 SIVAL(p,0,ea_size); /* Extended attributes */
1765 /* Clear the short name buffer. This is
1766 * IMPORTANT as not doing so will trigger
1767 * a Win2k client bug. JRA.
1769 if (!was_8_3 && check_mangled_names) {
1770 if (!name_to_8_3(fname,mangled_name,True,
1772 /* Error - mangle failed ! */
1773 memset(mangled_name,'\0',12);
1775 mangled_name[12] = 0;
1776 len = srvstr_push(base_data, flags2,
1777 p+2, mangled_name, 24,
1778 STR_UPPER|STR_UNICODE);
1781 memset(p + 2 + len,'\0',24 - len);
1788 SSVAL(p,0,0); p += 2; /* Reserved ? */
1789 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1790 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1791 len = srvstr_push(base_data, flags2, p,
1792 fname, PTR_DIFF(end_data, p),
1793 STR_TERMINATE_ASCII);
1796 SIVAL(p,0,0); /* Ensure any padding is null. */
1797 len = PTR_DIFF(p, pdata);
1798 len = (len + 3) & ~3;
1803 /* CIFS UNIX Extension. */
1805 case SMB_FIND_FILE_UNIX:
1806 case SMB_FIND_FILE_UNIX_INFO2:
1808 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1810 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1812 if (info_level == SMB_FIND_FILE_UNIX) {
1813 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1814 p = store_file_unix_basic(conn, p,
1816 len = srvstr_push(base_data, flags2, p,
1817 fname, PTR_DIFF(end_data, p),
1820 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1821 p = store_file_unix_basic_info2(conn, p,
1825 len = srvstr_push(base_data, flags2, p, fname,
1826 PTR_DIFF(end_data, p), 0);
1827 SIVAL(nameptr, 0, len);
1831 SIVAL(p,0,0); /* Ensure any padding is null. */
1833 len = PTR_DIFF(p, pdata);
1834 len = (len + 3) & ~3;
1835 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1837 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1846 if (PTR_DIFF(p,pdata) > space_remaining) {
1847 /* Move the dirptr back to prev_dirpos */
1848 dptr_SeekDir(conn->dirptr, prev_dirpos);
1849 *out_of_space = True;
1850 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1851 return False; /* Not finished - just out of space */
1854 /* Setup the last entry pointer, as an offset from base_data */
1855 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1856 /* Advance the data pointer to the next slot */
1862 /****************************************************************************
1863 Reply to a TRANS2_FINDFIRST.
1864 ****************************************************************************/
1866 static void call_trans2findfirst(connection_struct *conn,
1867 struct smb_request *req,
1868 char **pparams, int total_params,
1869 char **ppdata, int total_data,
1870 unsigned int max_data_bytes)
1872 /* We must be careful here that we don't return more than the
1873 allowed number of data bytes. If this means returning fewer than
1874 maxentries then so be it. We assume that the redirector has
1875 enough room for the fixed number of parameter bytes it has
1877 char *params = *pparams;
1878 char *pdata = *ppdata;
1882 uint16 findfirst_flags;
1883 bool close_after_first;
1885 bool requires_resume_key;
1887 char *directory = NULL;
1890 int last_entry_off=0;
1894 bool finished = False;
1895 bool dont_descend = False;
1896 bool out_of_space = False;
1897 int space_remaining;
1898 bool mask_contains_wcard = False;
1899 SMB_STRUCT_STAT sbuf;
1900 struct ea_list *ea_list = NULL;
1901 NTSTATUS ntstatus = NT_STATUS_OK;
1902 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1903 TALLOC_CTX *ctx = talloc_tos();
1905 if (total_params < 13) {
1906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1910 dirtype = SVAL(params,0);
1911 maxentries = SVAL(params,2);
1912 findfirst_flags = SVAL(params,4);
1913 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1914 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1915 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1916 info_level = SVAL(params,6);
1918 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1919 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1920 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1921 info_level, max_data_bytes));
1924 /* W2K3 seems to treat zero as 1. */
1928 switch (info_level) {
1929 case SMB_FIND_INFO_STANDARD:
1930 case SMB_FIND_EA_SIZE:
1931 case SMB_FIND_EA_LIST:
1932 case SMB_FIND_FILE_DIRECTORY_INFO:
1933 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1934 case SMB_FIND_FILE_NAMES_INFO:
1935 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1936 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1937 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1939 case SMB_FIND_FILE_UNIX:
1940 case SMB_FIND_FILE_UNIX_INFO2:
1941 /* Always use filesystem for UNIX mtime query. */
1942 ask_sharemode = false;
1943 if (!lp_unix_extensions()) {
1944 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1949 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1953 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1954 params+12, total_params - 12,
1955 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1956 if (!NT_STATUS_IS_OK(ntstatus)) {
1957 reply_nterror(req, ntstatus);
1961 ntstatus = resolve_dfspath_wcard(ctx, conn,
1962 req->flags2 & FLAGS2_DFS_PATHNAMES,
1965 &mask_contains_wcard);
1966 if (!NT_STATUS_IS_OK(ntstatus)) {
1967 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1968 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1969 ERRSRV, ERRbadpath);
1972 reply_nterror(req, ntstatus);
1976 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1977 if (!NT_STATUS_IS_OK(ntstatus)) {
1978 reply_nterror(req, ntstatus);
1982 ntstatus = check_name(conn, directory);
1983 if (!NT_STATUS_IS_OK(ntstatus)) {
1984 reply_nterror(req, ntstatus);
1988 p = strrchr_m(directory,'/');
1990 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1991 if((directory[0] == '.') && (directory[1] == '\0')) {
1992 mask = talloc_strdup(ctx,"*");
1994 reply_nterror(req, NT_STATUS_NO_MEMORY);
1997 mask_contains_wcard = True;
1999 directory = talloc_strdup(talloc_tos(), "./");
2001 reply_nterror(req, NT_STATUS_NO_MEMORY);
2008 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2010 if (info_level == SMB_FIND_EA_LIST) {
2013 if (total_data < 4) {
2014 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2018 ea_size = IVAL(pdata,0);
2019 if (ea_size != total_data) {
2020 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2021 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2026 if (!lp_ea_support(SNUM(conn))) {
2027 reply_doserror(req, ERRDOS, ERReasnotsupported);
2031 /* Pull out the list of names. */
2032 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2039 *ppdata = (char *)SMB_REALLOC(
2040 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2041 if(*ppdata == NULL ) {
2042 reply_nterror(req, NT_STATUS_NO_MEMORY);
2046 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2048 /* Realloc the params space */
2049 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2050 if (*pparams == NULL) {
2051 reply_nterror(req, NT_STATUS_NO_MEMORY);
2056 /* Save the wildcard match and attribs we are using on this directory -
2057 needed as lanman2 assumes these are being saved between calls */
2059 ntstatus = dptr_create(conn,
2065 mask_contains_wcard,
2069 if (!NT_STATUS_IS_OK(ntstatus)) {
2070 reply_nterror(req, ntstatus);
2074 dptr_num = dptr_dnum(conn->dirptr);
2075 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2077 /* We don't need to check for VOL here as this is returned by
2078 a different TRANS2 call. */
2080 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2081 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2082 dont_descend = True;
2085 space_remaining = max_data_bytes;
2086 out_of_space = False;
2088 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2089 bool got_exact_match = False;
2091 /* this is a heuristic to avoid seeking the dirptr except when
2092 absolutely necessary. It allows for a filename of about 40 chars */
2093 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2094 out_of_space = True;
2097 finished = !get_lanman2_dir_entry(ctx,
2100 mask,dirtype,info_level,
2101 requires_resume_key,dont_descend,
2104 space_remaining, &out_of_space,
2106 &last_entry_off, ea_list);
2109 if (finished && out_of_space)
2112 if (!finished && !out_of_space)
2116 * As an optimisation if we know we aren't looking
2117 * for a wildcard name (ie. the name matches the wildcard exactly)
2118 * then we can finish on any (first) match.
2119 * This speeds up large directory searches. JRA.
2125 /* Ensure space_remaining never goes -ve. */
2126 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2127 space_remaining = 0;
2128 out_of_space = true;
2130 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2134 /* Check if we can close the dirptr */
2135 if(close_after_first || (finished && close_if_end)) {
2136 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2137 dptr_close(&dptr_num);
2141 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2142 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2143 * the protocol level is less than NT1. Tested with smbclient. JRA.
2144 * This should fix the OS/2 client bug #2335.
2147 if(numentries == 0) {
2148 dptr_close(&dptr_num);
2149 if (Protocol < PROTOCOL_NT1) {
2150 reply_doserror(req, ERRDOS, ERRnofiles);
2153 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2154 ERRDOS, ERRbadfile);
2159 /* At this point pdata points to numentries directory entries. */
2161 /* Set up the return parameter block */
2162 SSVAL(params,0,dptr_num);
2163 SSVAL(params,2,numentries);
2164 SSVAL(params,4,finished);
2165 SSVAL(params,6,0); /* Never an EA error */
2166 SSVAL(params,8,last_entry_off);
2168 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2171 if ((! *directory) && dptr_path(dptr_num)) {
2172 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2174 reply_nterror(req, NT_STATUS_NO_MEMORY);
2178 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2179 smb_fn_name(CVAL(req->inbuf,smb_com)),
2180 mask, directory, dirtype, numentries ) );
2183 * Force a name mangle here to ensure that the
2184 * mask as an 8.3 name is top of the mangled cache.
2185 * The reasons for this are subtle. Don't remove
2186 * this code unless you know what you are doing
2187 * (see PR#13758). JRA.
2190 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2191 char mangled_name[13];
2192 name_to_8_3(mask, mangled_name, True, conn->params);
2198 /****************************************************************************
2199 Reply to a TRANS2_FINDNEXT.
2200 ****************************************************************************/
2202 static void call_trans2findnext(connection_struct *conn,
2203 struct smb_request *req,
2204 char **pparams, int total_params,
2205 char **ppdata, int total_data,
2206 unsigned int max_data_bytes)
2208 /* We must be careful here that we don't return more than the
2209 allowed number of data bytes. If this means returning fewer than
2210 maxentries then so be it. We assume that the redirector has
2211 enough room for the fixed number of parameter bytes it has
2213 char *params = *pparams;
2214 char *pdata = *ppdata;
2220 uint16 findnext_flags;
2221 bool close_after_request;
2223 bool requires_resume_key;
2225 bool mask_contains_wcard = False;
2226 char *resume_name = NULL;
2227 const char *mask = NULL;
2228 const char *directory = NULL;
2232 int i, last_entry_off=0;
2233 bool finished = False;
2234 bool dont_descend = False;
2235 bool out_of_space = False;
2236 int space_remaining;
2237 struct ea_list *ea_list = NULL;
2238 NTSTATUS ntstatus = NT_STATUS_OK;
2239 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2240 TALLOC_CTX *ctx = talloc_tos();
2242 if (total_params < 13) {
2243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2247 dptr_num = SVAL(params,0);
2248 maxentries = SVAL(params,2);
2249 info_level = SVAL(params,4);
2250 resume_key = IVAL(params,6);
2251 findnext_flags = SVAL(params,10);
2252 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2253 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2254 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2255 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2257 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2259 total_params - 12, STR_TERMINATE, &ntstatus,
2260 &mask_contains_wcard);
2261 if (!NT_STATUS_IS_OK(ntstatus)) {
2262 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2263 complain (it thinks we're asking for the directory above the shared
2264 path or an invalid name). Catch this as the resume name is only compared, never used in
2265 a file access. JRA. */
2266 srvstr_pull_talloc(ctx, params, req->flags2,
2267 &resume_name, params+12,
2271 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2272 reply_nterror(req, ntstatus);
2277 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2278 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2279 resume_key = %d resume name = %s continue=%d level = %d\n",
2280 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2281 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2284 /* W2K3 seems to treat zero as 1. */
2288 switch (info_level) {
2289 case SMB_FIND_INFO_STANDARD:
2290 case SMB_FIND_EA_SIZE:
2291 case SMB_FIND_EA_LIST:
2292 case SMB_FIND_FILE_DIRECTORY_INFO:
2293 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2294 case SMB_FIND_FILE_NAMES_INFO:
2295 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2296 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2297 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2299 case SMB_FIND_FILE_UNIX:
2300 case SMB_FIND_FILE_UNIX_INFO2:
2301 /* Always use filesystem for UNIX mtime query. */
2302 ask_sharemode = false;
2303 if (!lp_unix_extensions()) {
2304 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2309 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2313 if (info_level == SMB_FIND_EA_LIST) {
2316 if (total_data < 4) {
2317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2321 ea_size = IVAL(pdata,0);
2322 if (ea_size != total_data) {
2323 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2324 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2325 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2329 if (!lp_ea_support(SNUM(conn))) {
2330 reply_doserror(req, ERRDOS, ERReasnotsupported);
2334 /* Pull out the list of names. */
2335 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2342 *ppdata = (char *)SMB_REALLOC(
2343 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2344 if(*ppdata == NULL) {
2345 reply_nterror(req, NT_STATUS_NO_MEMORY);
2350 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2352 /* Realloc the params space */
2353 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2354 if(*pparams == NULL ) {
2355 reply_nterror(req, NT_STATUS_NO_MEMORY);
2361 /* Check that the dptr is valid */
2362 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2363 reply_doserror(req, ERRDOS, ERRnofiles);
2367 string_set(&conn->dirpath,dptr_path(dptr_num));
2369 /* Get the wildcard mask from the dptr */
2370 if((p = dptr_wcard(dptr_num))== NULL) {
2371 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2372 reply_doserror(req, ERRDOS, ERRnofiles);
2377 directory = conn->dirpath;
2379 /* Get the attr mask from the dptr */
2380 dirtype = dptr_attr(dptr_num);
2382 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2383 dptr_num, mask, dirtype,
2385 dptr_TellDir(conn->dirptr)));
2387 /* We don't need to check for VOL here as this is returned by
2388 a different TRANS2 call. */
2390 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2391 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2392 dont_descend = True;
2395 space_remaining = max_data_bytes;
2396 out_of_space = False;
2399 * Seek to the correct position. We no longer use the resume key but
2400 * depend on the last file name instead.
2403 if(*resume_name && !continue_bit) {
2406 long current_pos = 0;
2408 * Remember, name_to_8_3 is called by
2409 * get_lanman2_dir_entry(), so the resume name
2410 * could be mangled. Ensure we check the unmangled name.
2413 if (mangle_is_mangled(resume_name, conn->params)) {
2414 char *new_resume_name = NULL;
2415 mangle_lookup_name_from_8_3(ctx,
2419 if (new_resume_name) {
2420 resume_name = new_resume_name;
2425 * Fix for NT redirector problem triggered by resume key indexes
2426 * changing between directory scans. We now return a resume key of 0
2427 * and instead look for the filename to continue from (also given
2428 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2429 * findfirst/findnext (as is usual) then the directory pointer
2430 * should already be at the correct place.
2433 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2434 } /* end if resume_name && !continue_bit */
2436 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2437 bool got_exact_match = False;
2439 /* this is a heuristic to avoid seeking the dirptr except when
2440 absolutely necessary. It allows for a filename of about 40 chars */
2441 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2442 out_of_space = True;
2445 finished = !get_lanman2_dir_entry(ctx,
2448 mask,dirtype,info_level,
2449 requires_resume_key,dont_descend,
2452 space_remaining, &out_of_space,
2454 &last_entry_off, ea_list);
2457 if (finished && out_of_space)
2460 if (!finished && !out_of_space)
2464 * As an optimisation if we know we aren't looking
2465 * for a wildcard name (ie. the name matches the wildcard exactly)
2466 * then we can finish on any (first) match.
2467 * This speeds up large directory searches. JRA.
2473 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2476 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2477 smb_fn_name(CVAL(req->inbuf,smb_com)),
2478 mask, directory, dirtype, numentries ) );
2480 /* Check if we can close the dirptr */
2481 if(close_after_request || (finished && close_if_end)) {
2482 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2483 dptr_close(&dptr_num); /* This frees up the saved mask */
2486 /* Set up the return parameter block */
2487 SSVAL(params,0,numentries);
2488 SSVAL(params,2,finished);
2489 SSVAL(params,4,0); /* Never an EA error */
2490 SSVAL(params,6,last_entry_off);
2492 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2498 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2500 E_md4hash(lp_servicename(SNUM(conn)),objid);
2504 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2506 SMB_ASSERT(extended_info != NULL);
2508 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2509 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2510 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2511 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2512 #ifdef SAMBA_VERSION_REVISION
2513 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2515 extended_info->samba_subversion = 0;
2516 #ifdef SAMBA_VERSION_RC_RELEASE
2517 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2519 #ifdef SAMBA_VERSION_PRE_RELEASE
2520 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2523 #ifdef SAMBA_VERSION_VENDOR_PATCH
2524 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2526 extended_info->samba_gitcommitdate = 0;
2527 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2528 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2531 memset(extended_info->samba_version_string, 0,
2532 sizeof(extended_info->samba_version_string));
2534 snprintf (extended_info->samba_version_string,
2535 sizeof(extended_info->samba_version_string),
2536 "%s", samba_version_string());
2539 /****************************************************************************
2540 Reply to a TRANS2_QFSINFO (query filesystem info).
2541 ****************************************************************************/
2543 static void call_trans2qfsinfo(connection_struct *conn,
2544 struct smb_request *req,
2545 char **pparams, int total_params,
2546 char **ppdata, int total_data,
2547 unsigned int max_data_bytes)
2549 char *pdata, *end_data;
2550 char *params = *pparams;
2554 const char *vname = volume_label(SNUM(conn));
2555 int snum = SNUM(conn);
2556 char *fstype = lp_fstype(SNUM(conn));
2557 uint32 additional_flags = 0;
2559 if (total_params < 2) {
2560 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2564 info_level = SVAL(params,0);
2567 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2568 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2569 "info level (0x%x) on IPC$.\n",
2570 (unsigned int)info_level));
2571 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2576 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2577 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2578 DEBUG(0,("call_trans2qfsinfo: encryption required "
2579 "and info level 0x%x sent.\n",
2580 (unsigned int)info_level));
2581 exit_server_cleanly("encryption required "
2587 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2589 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2590 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2591 reply_doserror(req, ERRSRV, ERRinvdevice);
2595 *ppdata = (char *)SMB_REALLOC(
2596 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2597 if (*ppdata == NULL ) {
2598 reply_nterror(req, NT_STATUS_NO_MEMORY);
2603 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2604 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2606 switch (info_level) {
2607 case SMB_INFO_ALLOCATION:
2609 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2611 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2612 reply_unixerror(req, ERRHRD, ERRgeneral);
2616 block_size = lp_block_size(snum);
2617 if (bsize < block_size) {
2618 SMB_BIG_UINT factor = block_size/bsize;
2623 if (bsize > block_size) {
2624 SMB_BIG_UINT factor = bsize/block_size;
2629 bytes_per_sector = 512;
2630 sectors_per_unit = bsize/bytes_per_sector;
2632 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2633 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2634 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2636 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2637 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2638 SIVAL(pdata,l1_cUnit,dsize);
2639 SIVAL(pdata,l1_cUnitAvail,dfree);
2640 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2644 case SMB_INFO_VOLUME:
2645 /* Return volume name */
2647 * Add volume serial number - hash of a combination of
2648 * the called hostname and the service name.
2650 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2652 * Win2k3 and previous mess this up by sending a name length
2653 * one byte short. I believe only older clients (OS/2 Win9x) use
2654 * this call so try fixing this by adding a terminating null to
2655 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2659 pdata+l2_vol_szVolLabel, vname,
2660 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2661 STR_NOALIGN|STR_TERMINATE);
2662 SCVAL(pdata,l2_vol_cch,len);
2663 data_len = l2_vol_szVolLabel + len;
2664 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2665 (unsigned)st.st_ctime, len, vname));
2668 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2669 case SMB_FS_ATTRIBUTE_INFORMATION:
2671 additional_flags = 0;
2672 #if defined(HAVE_SYS_QUOTAS)
2673 additional_flags |= FILE_VOLUME_QUOTAS;
2676 if(lp_nt_acl_support(SNUM(conn))) {
2677 additional_flags |= FILE_PERSISTENT_ACLS;
2680 /* Capabilities are filled in at connection time through STATVFS call */
2681 additional_flags |= conn->fs_capabilities;
2683 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2684 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2685 additional_flags); /* FS ATTRIBUTES */
2687 SIVAL(pdata,4,255); /* Max filename component length */
2688 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2689 and will think we can't do long filenames */
2690 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2691 PTR_DIFF(end_data, pdata+12),
2694 data_len = 12 + len;
2697 case SMB_QUERY_FS_LABEL_INFO:
2698 case SMB_FS_LABEL_INFORMATION:
2699 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2700 PTR_DIFF(end_data, pdata+4), 0);
2705 case SMB_QUERY_FS_VOLUME_INFO:
2706 case SMB_FS_VOLUME_INFORMATION:
2709 * Add volume serial number - hash of a combination of
2710 * the called hostname and the service name.
2712 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2713 (str_checksum(get_local_machine_name())<<16));
2715 /* Max label len is 32 characters. */
2716 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2717 PTR_DIFF(end_data, pdata+18),
2719 SIVAL(pdata,12,len);
2722 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2723 (int)strlen(vname),vname, lp_servicename(snum)));
2726 case SMB_QUERY_FS_SIZE_INFO:
2727 case SMB_FS_SIZE_INFORMATION:
2729 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2731 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2732 reply_unixerror(req, ERRHRD, ERRgeneral);
2735 block_size = lp_block_size(snum);
2736 if (bsize < block_size) {
2737 SMB_BIG_UINT factor = block_size/bsize;
2742 if (bsize > block_size) {
2743 SMB_BIG_UINT factor = bsize/block_size;
2748 bytes_per_sector = 512;
2749 sectors_per_unit = bsize/bytes_per_sector;
2750 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2751 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2752 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2753 SBIG_UINT(pdata,0,dsize);
2754 SBIG_UINT(pdata,8,dfree);
2755 SIVAL(pdata,16,sectors_per_unit);
2756 SIVAL(pdata,20,bytes_per_sector);
2760 case SMB_FS_FULL_SIZE_INFORMATION:
2762 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2764 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2765 reply_unixerror(req, ERRHRD, ERRgeneral);
2768 block_size = lp_block_size(snum);
2769 if (bsize < block_size) {
2770 SMB_BIG_UINT factor = block_size/bsize;
2775 if (bsize > block_size) {
2776 SMB_BIG_UINT factor = bsize/block_size;
2781 bytes_per_sector = 512;
2782 sectors_per_unit = bsize/bytes_per_sector;
2783 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2784 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2785 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2786 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2787 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2788 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2789 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2790 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2794 case SMB_QUERY_FS_DEVICE_INFO:
2795 case SMB_FS_DEVICE_INFORMATION:
2797 SIVAL(pdata,0,0); /* dev type */
2798 SIVAL(pdata,4,0); /* characteristics */
2801 #ifdef HAVE_SYS_QUOTAS
2802 case SMB_FS_QUOTA_INFORMATION:
2804 * what we have to send --metze:
2806 * Unknown1: 24 NULL bytes
2807 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2808 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2809 * Quota Flags: 2 byte :
2810 * Unknown3: 6 NULL bytes
2814 * details for Quota Flags:
2816 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2817 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2818 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2819 * 0x0001 Enable Quotas: enable quota for this fs
2823 /* we need to fake up a fsp here,
2824 * because its not send in this call
2827 SMB_NTQUOTA_STRUCT quotas;
2830 ZERO_STRUCT(quotas);
2836 if (current_user.ut.uid != 0) {
2837 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2838 lp_servicename(SNUM(conn)),conn->user));
2839 reply_doserror(req, ERRDOS, ERRnoaccess);
2843 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2844 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2845 reply_doserror(req, ERRSRV, ERRerror);
2851 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2853 /* Unknown1 24 NULL bytes*/
2854 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2855 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2856 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2858 /* Default Soft Quota 8 bytes */
2859 SBIG_UINT(pdata,24,quotas.softlim);
2861 /* Default Hard Quota 8 bytes */
2862 SBIG_UINT(pdata,32,quotas.hardlim);
2864 /* Quota flag 2 bytes */
2865 SSVAL(pdata,40,quotas.qflags);
2867 /* Unknown3 6 NULL bytes */
2873 #endif /* HAVE_SYS_QUOTAS */
2874 case SMB_FS_OBJECTID_INFORMATION:
2876 unsigned char objid[16];
2877 struct smb_extended_info extended_info;
2878 memcpy(pdata,create_volume_objectid(conn, objid),16);
2879 samba_extended_info_version (&extended_info);
2880 SIVAL(pdata,16,extended_info.samba_magic);
2881 SIVAL(pdata,20,extended_info.samba_version);
2882 SIVAL(pdata,24,extended_info.samba_subversion);
2883 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2884 memcpy(pdata+36,extended_info.samba_version_string,28);
2890 * Query the version and capabilities of the CIFS UNIX extensions
2894 case SMB_QUERY_CIFS_UNIX_INFO:
2896 bool large_write = lp_min_receive_file_size() &&
2897 !srv_is_signing_active();
2898 bool large_read = !srv_is_signing_active();
2899 int encrypt_caps = 0;
2901 if (!lp_unix_extensions()) {
2902 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2906 switch (conn->encrypt_level) {
2912 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2915 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2916 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2917 large_write = false;
2923 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2924 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2926 /* We have POSIX ACLs, pathname, encryption,
2927 * large read/write, and locking capability. */
2929 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2930 CIFS_UNIX_POSIX_ACLS_CAP|
2931 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2932 CIFS_UNIX_FCNTL_LOCKS_CAP|
2933 CIFS_UNIX_EXTATTR_CAP|
2934 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2936 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2938 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2942 case SMB_QUERY_POSIX_FS_INFO:
2945 vfs_statvfs_struct svfs;
2947 if (!lp_unix_extensions()) {
2948 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2952 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2956 SIVAL(pdata,0,svfs.OptimalTransferSize);
2957 SIVAL(pdata,4,svfs.BlockSize);
2958 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2959 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2960 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2961 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2962 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2963 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2964 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2966 } else if (rc == EOPNOTSUPP) {
2967 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2969 #endif /* EOPNOTSUPP */
2971 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2972 reply_doserror(req, ERRSRV, ERRerror);
2978 case SMB_QUERY_POSIX_WHOAMI:
2984 if (!lp_unix_extensions()) {
2985 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2989 if (max_data_bytes < 40) {
2990 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2994 /* We ARE guest if global_sid_Builtin_Guests is
2995 * in our list of SIDs.
2997 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2998 current_user.nt_user_token)) {
2999 flags |= SMB_WHOAMI_GUEST;
3002 /* We are NOT guest if global_sid_Authenticated_Users
3003 * is in our list of SIDs.
3005 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3006 current_user.nt_user_token)) {
3007 flags &= ~SMB_WHOAMI_GUEST;
3010 /* NOTE: 8 bytes for UID/GID, irrespective of native
3011 * platform size. This matches
3012 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3014 data_len = 4 /* flags */
3021 + 4 /* pad/reserved */
3022 + (current_user.ut.ngroups * 8)
3024 + (current_user.nt_user_token->num_sids *
3028 SIVAL(pdata, 0, flags);
3029 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3030 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
3031 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
3034 if (data_len >= max_data_bytes) {
3035 /* Potential overflow, skip the GIDs and SIDs. */
3037 SIVAL(pdata, 24, 0); /* num_groups */
3038 SIVAL(pdata, 28, 0); /* num_sids */
3039 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3040 SIVAL(pdata, 36, 0); /* reserved */
3046 SIVAL(pdata, 24, current_user.ut.ngroups);
3048 current_user.nt_user_token->num_sids);
3050 /* We walk the SID list twice, but this call is fairly
3051 * infrequent, and I don't expect that it's performance
3052 * sensitive -- jpeach
3054 for (i = 0, sid_bytes = 0;
3055 i < current_user.nt_user_token->num_sids; ++i) {
3056 sid_bytes += ndr_size_dom_sid(
3057 ¤t_user.nt_user_token->user_sids[i], 0);
3060 /* SID list byte count */
3061 SIVAL(pdata, 32, sid_bytes);
3063 /* 4 bytes pad/reserved - must be zero */
3064 SIVAL(pdata, 36, 0);
3068 for (i = 0; i < current_user.ut.ngroups; ++i) {
3069 SBIG_UINT(pdata, data_len,
3070 (SMB_BIG_UINT)current_user.ut.groups[i]);
3076 i < current_user.nt_user_token->num_sids; ++i) {
3077 int sid_len = ndr_size_dom_sid(
3078 ¤t_user.nt_user_token->user_sids[i], 0);
3080 sid_linearize(pdata + data_len, sid_len,
3081 ¤t_user.nt_user_token->user_sids[i]);
3082 data_len += sid_len;
3088 case SMB_MAC_QUERY_FS_INFO:
3090 * Thursby MAC extension... ONLY on NTFS filesystems
3091 * once we do streams then we don't need this
3093 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3095 SIVAL(pdata,84,0x100); /* Don't support mac... */
3100 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3105 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3108 DEBUG( 4, ( "%s info_level = %d\n",
3109 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3114 /****************************************************************************
3115 Reply to a TRANS2_SETFSINFO (set filesystem info).
3116 ****************************************************************************/
3118 static void call_trans2setfsinfo(connection_struct *conn,
3119 struct smb_request *req,
3120 char **pparams, int total_params,
3121 char **ppdata, int total_data,
3122 unsigned int max_data_bytes)
3124 char *pdata = *ppdata;
3125 char *params = *pparams;
3128 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3131 if (total_params < 4) {
3132 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3138 info_level = SVAL(params,2);
3141 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3142 info_level != SMB_SET_CIFS_UNIX_INFO) {
3143 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3144 "info level (0x%x) on IPC$.\n",
3145 (unsigned int)info_level));
3146 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3151 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3152 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3153 DEBUG(0,("call_trans2setfsinfo: encryption required "
3154 "and info level 0x%x sent.\n",
3155 (unsigned int)info_level));
3156 exit_server_cleanly("encryption required "
3162 switch(info_level) {
3163 case SMB_SET_CIFS_UNIX_INFO:
3165 uint16 client_unix_major;
3166 uint16 client_unix_minor;
3167 uint32 client_unix_cap_low;
3168 uint32 client_unix_cap_high;
3170 if (!lp_unix_extensions()) {
3172 NT_STATUS_INVALID_LEVEL);
3176 /* There should be 12 bytes of capabilities set. */
3177 if (total_data < 8) {
3180 NT_STATUS_INVALID_PARAMETER);
3183 client_unix_major = SVAL(pdata,0);
3184 client_unix_minor = SVAL(pdata,2);
3185 client_unix_cap_low = IVAL(pdata,4);
3186 client_unix_cap_high = IVAL(pdata,8);
3187 /* Just print these values for now. */
3188 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3189 cap_low = 0x%x, cap_high = 0x%x\n",
3190 (unsigned int)client_unix_major,
3191 (unsigned int)client_unix_minor,
3192 (unsigned int)client_unix_cap_low,
3193 (unsigned int)client_unix_cap_high ));
3195 /* Here is where we must switch to posix pathname processing... */
3196 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3197 lp_set_posix_pathnames();
3198 mangle_change_to_posix();
3201 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3202 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3203 /* Client that knows how to do posix locks,
3204 * but not posix open/mkdir operations. Set a
3205 * default type for read/write checks. */
3207 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3213 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3216 size_t param_len = 0;
3217 size_t data_len = total_data;
3219 if (!lp_unix_extensions()) {
3222 NT_STATUS_INVALID_LEVEL);
3226 if (lp_smb_encrypt(SNUM(conn)) == false) {
3229 NT_STATUS_NOT_SUPPORTED);
3233 DEBUG( 4,("call_trans2setfsinfo: "
3234 "request transport encryption.\n"));
3236 status = srv_request_encryption_setup(conn,
3237 (unsigned char **)ppdata,
3239 (unsigned char **)pparams,
3242 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3243 !NT_STATUS_IS_OK(status)) {
3244 reply_nterror(req, status);
3248 send_trans2_replies(conn, req,
3255 if (NT_STATUS_IS_OK(status)) {
3256 /* Server-side transport
3257 * encryption is now *on*. */
3258 status = srv_encryption_start(conn);
3259 if (!NT_STATUS_IS_OK(status)) {
3260 exit_server_cleanly(
3261 "Failure in setting "
3262 "up encrypted transport");
3268 case SMB_FS_QUOTA_INFORMATION:
3270 files_struct *fsp = NULL;
3271 SMB_NTQUOTA_STRUCT quotas;
3273 ZERO_STRUCT(quotas);
3276 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3277 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3278 lp_servicename(SNUM(conn)),conn->user));
3279 reply_doserror(req, ERRSRV, ERRaccess);
3283 /* note: normaly there're 48 bytes,
3284 * but we didn't use the last 6 bytes for now
3287 fsp = file_fsp(SVAL(params,0));
3288 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3289 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3291 req, NT_STATUS_INVALID_HANDLE);
3295 if (total_data < 42) {
3296 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3300 NT_STATUS_INVALID_PARAMETER);
3304 /* unknown_1 24 NULL bytes in pdata*/
3306 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3307 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3308 #ifdef LARGE_SMB_OFF_T
3309 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3310 #else /* LARGE_SMB_OFF_T */
3311 if ((IVAL(pdata,28) != 0)&&
3312 ((quotas.softlim != 0xFFFFFFFF)||
3313 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3314 /* more than 32 bits? */
3317 NT_STATUS_INVALID_PARAMETER);
3320 #endif /* LARGE_SMB_OFF_T */
3322 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3323 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3324 #ifdef LARGE_SMB_OFF_T
3325 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3326 #else /* LARGE_SMB_OFF_T */
3327 if ((IVAL(pdata,36) != 0)&&
3328 ((quotas.hardlim != 0xFFFFFFFF)||
3329 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3330 /* more than 32 bits? */
3333 NT_STATUS_INVALID_PARAMETER);
3336 #endif /* LARGE_SMB_OFF_T */
3338 /* quota_flags 2 bytes **/
3339 quotas.qflags = SVAL(pdata,40);
3341 /* unknown_2 6 NULL bytes follow*/
3343 /* now set the quotas */
3344 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3345 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3346 reply_doserror(req, ERRSRV, ERRerror);
3353 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3355 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3361 * sending this reply works fine,
3362 * but I'm not sure it's the same
3363 * like windows do...
3366 reply_outbuf(req, 10, 0);
3369 #if defined(HAVE_POSIX_ACLS)
3370 /****************************************************************************
3371 Utility function to count the number of entries in a POSIX acl.
3372 ****************************************************************************/
3374 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3376 unsigned int ace_count = 0;
3377 int entry_id = SMB_ACL_FIRST_ENTRY;
3378 SMB_ACL_ENTRY_T entry;
3380 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3382 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3383 entry_id = SMB_ACL_NEXT_ENTRY;
3390 /****************************************************************************
3391 Utility function to marshall a POSIX acl into wire format.
3392 ****************************************************************************/
3394 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3396 int entry_id = SMB_ACL_FIRST_ENTRY;
3397 SMB_ACL_ENTRY_T entry;
3399 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3400 SMB_ACL_TAG_T tagtype;
3401 SMB_ACL_PERMSET_T permset;
3402 unsigned char perms = 0;
3403 unsigned int own_grp;
3406 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3407 entry_id = SMB_ACL_NEXT_ENTRY;
3410 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3411 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3415 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3416 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3420 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3421 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3422 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3424 SCVAL(pdata,1,perms);
3427 case SMB_ACL_USER_OBJ:
3428 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3429 own_grp = (unsigned int)pst->st_uid;
3430 SIVAL(pdata,2,own_grp);
3435 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3437 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3440 own_grp = (unsigned int)*puid;
3441 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3442 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3443 SIVAL(pdata,2,own_grp);
3447 case SMB_ACL_GROUP_OBJ:
3448 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3449 own_grp = (unsigned int)pst->st_gid;
3450 SIVAL(pdata,2,own_grp);
3455 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3457 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3460 own_grp = (unsigned int)*pgid;
3461 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3462 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3463 SIVAL(pdata,2,own_grp);
3468 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3469 SIVAL(pdata,2,0xFFFFFFFF);
3470 SIVAL(pdata,6,0xFFFFFFFF);
3473 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3474 SIVAL(pdata,2,0xFFFFFFFF);
3475 SIVAL(pdata,6,0xFFFFFFFF);
3478 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3481 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3488 /****************************************************************************
3489 Store the FILE_UNIX_BASIC info.
3490 ****************************************************************************/
3492 static char *store_file_unix_basic(connection_struct *conn,
3495 const SMB_STRUCT_STAT *psbuf)
3497 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3498 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3500 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3503 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3506 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3507 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3508 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3511 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3515 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3519 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3522 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3526 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3530 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3533 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3537 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3544 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3545 * the chflags(2) (or equivalent) flags.
3547 * XXX: this really should be behind the VFS interface. To do this, we would
3548 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3549 * Each VFS module could then implement its own mapping as appropriate for the
3550 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3552 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3556 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3560 { UF_IMMUTABLE, EXT_IMMUTABLE },
3564 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3568 { UF_HIDDEN, EXT_HIDDEN },
3571 /* Do not remove. We need to guarantee that this array has at least one
3572 * entry to build on HP-UX.
3578 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3579 uint32 *smb_fflags, uint32 *smb_fmask)
3581 #ifdef HAVE_STAT_ST_FLAGS
3584 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3585 *smb_fmask |= info2_flags_map[i].smb_fflag;
3586 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3587 *smb_fflags |= info2_flags_map[i].smb_fflag;
3590 #endif /* HAVE_STAT_ST_FLAGS */
3593 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3594 const uint32 smb_fflags,
3595 const uint32 smb_fmask,
3598 #ifdef HAVE_STAT_ST_FLAGS
3599 uint32 max_fmask = 0;
3602 *stat_fflags = psbuf->st_flags;
3604 /* For each flags requested in smb_fmask, check the state of the
3605 * corresponding flag in smb_fflags and set or clear the matching
3609 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3610 max_fmask |= info2_flags_map[i].smb_fflag;
3611 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3612 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3613 *stat_fflags |= info2_flags_map[i].stat_fflag;
3615 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3620 /* If smb_fmask is asking to set any bits that are not supported by
3621 * our flag mappings, we should fail.
3623 if ((smb_fmask & max_fmask) != smb_fmask) {
3630 #endif /* HAVE_STAT_ST_FLAGS */
3634 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3635 * of file flags and birth (create) time.
3637 static char *store_file_unix_basic_info2(connection_struct *conn,
3640 const SMB_STRUCT_STAT *psbuf)
3642 uint32 file_flags = 0;
3643 uint32 flags_mask = 0;
3645 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3647 /* Create (birth) time 64 bit */
3648 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3651 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3652 SIVAL(pdata, 0, file_flags); /* flags */
3653 SIVAL(pdata, 4, flags_mask); /* mask */
3659 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3660 const struct stream_struct *streams,
3662 unsigned int max_data_bytes,
3663 unsigned int *data_size)
3666 unsigned int ofs = 0;
3668 for (i=0; i<num_streams; i++) {
3669 unsigned int next_offset;
3671 smb_ucs2_t *namebuf;
3673 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3676 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3677 return NT_STATUS_INVALID_PARAMETER;
3681 * name_buf is now null-terminated, we need to marshall as not
3687 if (ofs + 24 + namelen > max_data_bytes) {
3688 TALLOC_FREE(namebuf);
3689 return NT_STATUS_BUFFER_TOO_SMALL;
3692 SIVAL(data, ofs+4, namelen);
3693 SOFF_T(data, ofs+8, streams[i].size);
3694 SOFF_T(data, ofs+16, streams[i].alloc_size);
3695 memcpy(data+ofs+24, namebuf, namelen);
3696 TALLOC_FREE(namebuf);
3698 next_offset = ofs + 24 + namelen;
3700 if (i == num_streams-1) {
3701 SIVAL(data, ofs, 0);
3704 unsigned int align = ndr_align_size(next_offset, 8);
3706 if (next_offset + align > max_data_bytes) {
3707 return NT_STATUS_BUFFER_TOO_SMALL;
3710 memset(data+next_offset, 0, align);
3711 next_offset += align;
3713 SIVAL(data, ofs, next_offset - ofs);
3722 return NT_STATUS_OK;
3725 /****************************************************************************
3726 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3727 ****************************************************************************/
3729 static void call_trans2qpipeinfo(connection_struct *conn,
3730 struct smb_request *req,
3731 unsigned int tran_call,
3732 char **pparams, int total_params,
3733 char **ppdata, int total_data,
3734 unsigned int max_data_bytes)
3736 char *params = *pparams;
3737 char *pdata = *ppdata;
3738 unsigned int data_size = 0;
3739 unsigned int param_size = 2;
3741 smb_np_struct *p_pipe = NULL;
3744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3748 if (total_params < 4) {
3749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3753 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3754 if (p_pipe == NULL) {
3755 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3759 info_level = SVAL(params,2);
3761 *pparams = (char *)SMB_REALLOC(*pparams,2);
3762 if (*pparams == NULL) {
3763 reply_nterror(req, NT_STATUS_NO_MEMORY);
3768 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3769 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3770 if (*ppdata == NULL ) {
3771 reply_nterror(req, NT_STATUS_NO_MEMORY);
3776 switch (info_level) {
3777 case SMB_FILE_STANDARD_INFORMATION:
3779 SOFF_T(pdata,0,4096LL);
3786 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3790 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3796 /****************************************************************************
3797 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3798 file name or file id).
3799 ****************************************************************************/
3801 static void call_trans2qfilepathinfo(connection_struct *conn,
3802 struct smb_request *req,
3803 unsigned int tran_call,
3804 char **pparams, int total_params,
3805 char **ppdata, int total_data,
3806 unsigned int max_data_bytes)
3808 char *params = *pparams;
3809 char *pdata = *ppdata;
3810 char *dstart, *dend;
3814 SMB_OFF_T file_size=0;
3815 SMB_BIG_UINT allocation_size=0;
3816 unsigned int data_size = 0;
3817 unsigned int param_size = 2;
3818 SMB_STRUCT_STAT sbuf;
3819 char *dos_fname = NULL;
3825 bool delete_pending = False;
3827 time_t create_time, mtime, atime;
3828 struct timespec create_time_ts, mtime_ts, atime_ts;
3829 struct timespec write_time_ts;
3830 files_struct *fsp = NULL;
3831 struct file_id fileid;
3832 struct ea_list *ea_list = NULL;
3833 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3834 char *lock_data = NULL;
3835 bool ms_dfs_link = false;
3836 TALLOC_CTX *ctx = talloc_tos();
3839 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3844 ZERO_STRUCT(write_time_ts);
3846 if (tran_call == TRANSACT2_QFILEINFO) {
3847 if (total_params < 4) {
3848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3853 call_trans2qpipeinfo(conn, req, tran_call,
3854 pparams, total_params,
3860 fsp = file_fsp(SVAL(params,0));
3861 info_level = SVAL(params,2);
3863 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3865 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3866 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3870 /* Initial check for valid fsp ptr. */
3871 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3875 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3877 reply_nterror(req, NT_STATUS_NO_MEMORY);
3881 if(fsp->fake_file_handle) {
3883 * This is actually for the QUOTA_FAKE_FILE --metze
3886 /* We know this name is ok, it's already passed the checks. */
3888 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3890 * This is actually a QFILEINFO on a directory
3891 * handle (returned from an NT SMB). NT5.0 seems
3892 * to do this call. JRA.
3895 if (INFO_LEVEL_IS_UNIX(info_level)) {
3896 /* Always do lstat for UNIX calls. */
3897 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3898 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3899 reply_unixerror(req,ERRDOS,ERRbadpath);
3902 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3903 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3904 reply_unixerror(req, ERRDOS, ERRbadpath);
3908 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3909 get_file_infos(fileid, &delete_pending, &write_time_ts);
3912 * Original code - this is an open file.
3914 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3918 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3919 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3920 reply_unixerror(req, ERRDOS, ERRbadfid);
3923 pos = fsp->fh->position_information;
3924 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3925 get_file_infos(fileid, &delete_pending, &write_time_ts);
3926 access_mask = fsp->access_mask;
3930 NTSTATUS status = NT_STATUS_OK;
3933 if (total_params < 7) {
3934 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3938 info_level = SVAL(params,0);
3940 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3942 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3943 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3947 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3949 STR_TERMINATE, &status);
3950 if (!NT_STATUS_IS_OK(status)) {
3951 reply_nterror(req, status);
3955 status = resolve_dfspath(ctx,
3957 req->flags2 & FLAGS2_DFS_PATHNAMES,
3960 if (!NT_STATUS_IS_OK(status)) {
3961 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3962 reply_botherror(req,
3963 NT_STATUS_PATH_NOT_COVERED,
3964 ERRSRV, ERRbadpath);
3966 reply_nterror(req, status);
3970 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 reply_nterror(req, status);
3975 status = check_name(conn, fname);
3976 if (!NT_STATUS_IS_OK(status)) {
3977 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3978 reply_nterror(req, status);
3982 if (INFO_LEVEL_IS_UNIX(info_level)) {
3983 /* Always do lstat for UNIX calls. */
3984 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3985 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3986 reply_unixerror(req, ERRDOS, ERRbadpath);
3990 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3991 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
3994 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3995 reply_unixerror(req, ERRDOS, ERRbadpath);
4000 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4001 get_file_infos(fileid, &delete_pending, &write_time_ts);
4002 if (delete_pending) {
4003 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4008 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4009 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4013 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4014 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4016 p = strrchr_m(fname,'/');
4023 mode = dos_mode_msdfs(conn,fname,&sbuf);
4025 mode = dos_mode(conn,fname,&sbuf);
4028 mode = FILE_ATTRIBUTE_NORMAL;
4030 nlink = sbuf.st_nlink;
4032 if (nlink && (mode&aDIR)) {
4036 if ((nlink > 0) && delete_pending) {
4040 fullpathname = fname;
4042 file_size = get_file_size(sbuf);
4044 /* Pull out any data sent here before we realloc. */
4045 switch (info_level) {
4046 case SMB_INFO_QUERY_EAS_FROM_LIST:
4048 /* Pull any EA list from the data portion. */
4051 if (total_data < 4) {
4053 req, NT_STATUS_INVALID_PARAMETER);
4056 ea_size = IVAL(pdata,0);
4058 if (total_data > 0 && ea_size != total_data) {
4059 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4060 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4062 req, NT_STATUS_INVALID_PARAMETER);
4066 if (!lp_ea_support(SNUM(conn))) {
4067 reply_doserror(req, ERRDOS,
4068 ERReasnotsupported);
4072 /* Pull out the list of names. */
4073 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4076 req, NT_STATUS_INVALID_PARAMETER);
4082 case SMB_QUERY_POSIX_LOCK:
4084 if (fsp == NULL || fsp->fh->fd == -1) {
4085 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4089 if (total_data != POSIX_LOCK_DATA_SIZE) {
4091 req, NT_STATUS_INVALID_PARAMETER);
4095 /* Copy the lock range data. */
4096 lock_data = (char *)TALLOC_MEMDUP(
4097 ctx, pdata, total_data);
4099 reply_nterror(req, NT_STATUS_NO_MEMORY);
4107 *pparams = (char *)SMB_REALLOC(*pparams,2);
4108 if (*pparams == NULL) {
4109 reply_nterror(req, NT_STATUS_NO_MEMORY);
4114 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4115 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4116 if (*ppdata == NULL ) {
4117 reply_nterror(req, NT_STATUS_NO_MEMORY);
4122 dend = dstart + data_size - 1;
4124 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4125 mtime_ts = get_mtimespec(&sbuf);
4126 atime_ts = get_atimespec(&sbuf);
4128 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4131 /* Do we have this path open ? */
4133 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4134 fsp1 = file_find_di_first(fileid);
4135 if (fsp1 && fsp1->initial_allocation_size) {
4136 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4140 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4141 mtime_ts = write_time_ts;
4144 if (lp_dos_filetime_resolution(SNUM(conn))) {
4145 dos_filetime_timespec(&create_time_ts);
4146 dos_filetime_timespec(&mtime_ts);
4147 dos_filetime_timespec(&atime_ts);
4150 create_time = convert_timespec_to_time_t(create_time_ts);
4151 mtime = convert_timespec_to_time_t(mtime_ts);
4152 atime = convert_timespec_to_time_t(atime_ts);
4154 /* NT expects the name to be in an exact form of the *full*
4155 filename. See the trans2 torture test */
4156 if (ISDOT(base_name)) {
4157 dos_fname = talloc_strdup(ctx, "\\");
4159 reply_nterror(req, NT_STATUS_NO_MEMORY);
4163 dos_fname = talloc_asprintf(ctx,
4167 reply_nterror(req, NT_STATUS_NO_MEMORY);
4170 string_replace(dos_fname, '/', '\\');
4173 switch (info_level) {
4174 case SMB_INFO_STANDARD:
4175 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4177 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4178 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4179 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4180 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4181 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4182 SSVAL(pdata,l1_attrFile,mode);
4185 case SMB_INFO_QUERY_EA_SIZE:
4187 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4188 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4190 srv_put_dos_date2(pdata,0,create_time);
4191 srv_put_dos_date2(pdata,4,atime);
4192 srv_put_dos_date2(pdata,8,mtime); /* write time */
4193 SIVAL(pdata,12,(uint32)file_size);
4194 SIVAL(pdata,16,(uint32)allocation_size);
4195 SSVAL(pdata,20,mode);
4196 SIVAL(pdata,22,ea_size);
4200 case SMB_INFO_IS_NAME_VALID:
4201 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4202 if (tran_call == TRANSACT2_QFILEINFO) {
4203 /* os/2 needs this ? really ?*/
4204 reply_doserror(req, ERRDOS, ERRbadfunc);
4211 case SMB_INFO_QUERY_EAS_FROM_LIST:
4213 size_t total_ea_len = 0;
4214 struct ea_list *ea_file_list = NULL;
4216 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4218 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4219 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4221 if (!ea_list || (total_ea_len > data_size)) {
4223 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4227 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4231 case SMB_INFO_QUERY_ALL_EAS:
4233 /* We have data_size bytes to put EA's into. */
4234 size_t total_ea_len = 0;
4236 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4238 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4239 if (!ea_list || (total_ea_len > data_size)) {
4241 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4245 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4249 case SMB_FILE_BASIC_INFORMATION:
4250 case SMB_QUERY_FILE_BASIC_INFO:
4252 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4253 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4254 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4256 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4260 put_long_date_timespec(pdata,create_time_ts);
4261 put_long_date_timespec(pdata+8,atime_ts);
4262 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4263 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4264 SIVAL(pdata,32,mode);
4266 DEBUG(5,("SMB_QFBI - "));
4267 DEBUG(5,("create: %s ", ctime(&create_time)));
4268 DEBUG(5,("access: %s ", ctime(&atime)));
4269 DEBUG(5,("write: %s ", ctime(&mtime)));
4270 DEBUG(5,("change: %s ", ctime(&mtime)));
4271 DEBUG(5,("mode: %x\n", mode));
4274 case SMB_FILE_STANDARD_INFORMATION:
4275 case SMB_QUERY_FILE_STANDARD_INFO:
4277 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4279 SOFF_T(pdata,0,allocation_size);
4280 SOFF_T(pdata,8,file_size);
4281 SIVAL(pdata,16,nlink);
4282 SCVAL(pdata,20,delete_pending?1:0);
4283 SCVAL(pdata,21,(mode&aDIR)?1:0);
4284 SSVAL(pdata,22,0); /* Padding. */
4287 case SMB_FILE_EA_INFORMATION:
4288 case SMB_QUERY_FILE_EA_INFO:
4290 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4291 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4293 SIVAL(pdata,0,ea_size);
4297 /* Get the 8.3 name - used if NT SMB was negotiated. */
4298 case SMB_QUERY_FILE_ALT_NAME_INFO:
4299 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4301 char mangled_name[13];
4302 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4303 if (!name_to_8_3(base_name,mangled_name,
4304 True,conn->params)) {
4307 NT_STATUS_NO_MEMORY);
4309 len = srvstr_push(dstart, req->flags2,
4310 pdata+4, mangled_name,
4311 PTR_DIFF(dend, pdata+4),
4313 data_size = 4 + len;
4318 case SMB_QUERY_FILE_NAME_INFO:
4320 this must be *exactly* right for ACLs on mapped drives to work
4322 len = srvstr_push(dstart, req->flags2,
4324 PTR_DIFF(dend, pdata+4),
4326 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4327 data_size = 4 + len;
4331 case SMB_FILE_ALLOCATION_INFORMATION:
4332 case SMB_QUERY_FILE_ALLOCATION_INFO:
4333 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4335 SOFF_T(pdata,0,allocation_size);
4338 case SMB_FILE_END_OF_FILE_INFORMATION:
4339 case SMB_QUERY_FILE_END_OF_FILEINFO:
4340 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4342 SOFF_T(pdata,0,file_size);
4345 case SMB_QUERY_FILE_ALL_INFO:
4346 case SMB_FILE_ALL_INFORMATION:
4348 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4349 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4350 put_long_date_timespec(pdata,create_time_ts);
4351 put_long_date_timespec(pdata+8,atime_ts);
4352 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4353 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4354 SIVAL(pdata,32,mode);
4355 SIVAL(pdata,36,0); /* padding. */
4357 SOFF_T(pdata,0,allocation_size);
4358 SOFF_T(pdata,8,file_size);
4359 SIVAL(pdata,16,nlink);
4360 SCVAL(pdata,20,delete_pending);
4361 SCVAL(pdata,21,(mode&aDIR)?1:0);
4364 SIVAL(pdata,0,ea_size);
4365 pdata += 4; /* EA info */
4366 len = srvstr_push(dstart, req->flags2,
4368 PTR_DIFF(dend, pdata+4),
4372 data_size = PTR_DIFF(pdata,(*ppdata));
4375 case SMB_FILE_INTERNAL_INFORMATION:
4376 /* This should be an index number - looks like
4379 I think this causes us to fail the IFSKIT
4380 BasicFileInformationTest. -tpot */
4382 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4383 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4384 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4388 case SMB_FILE_ACCESS_INFORMATION:
4389 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4390 SIVAL(pdata,0,access_mask);
4394 case SMB_FILE_NAME_INFORMATION:
4395 /* Pathname with leading '\'. */
4398 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4399 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4400 SIVAL(pdata,0,byte_len);
4401 data_size = 4 + byte_len;
4405 case SMB_FILE_DISPOSITION_INFORMATION:
4406 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4408 SCVAL(pdata,0,delete_pending);
4411 case SMB_FILE_POSITION_INFORMATION:
4412 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4414 SOFF_T(pdata,0,pos);
4417 case SMB_FILE_MODE_INFORMATION:
4418 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4419 SIVAL(pdata,0,mode);
4423 case SMB_FILE_ALIGNMENT_INFORMATION:
4424 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4425 SIVAL(pdata,0,0); /* No alignment needed. */
4430 * NT4 server just returns "invalid query" to this - if we try
4431 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4434 /* The first statement above is false - verified using Thursby
4435 * client against NT4 -- gcolley.
4437 case SMB_QUERY_FILE_STREAM_INFO:
4438 case SMB_FILE_STREAM_INFORMATION: {
4439 unsigned int num_streams;
4440 struct stream_struct *streams;
4443 DEBUG(10,("call_trans2qfilepathinfo: "
4444 "SMB_FILE_STREAM_INFORMATION\n"));
4446 status = SMB_VFS_STREAMINFO(
4447 conn, fsp, fname, talloc_tos(),
4448 &num_streams, &streams);
4450 if (!NT_STATUS_IS_OK(status)) {
4451 DEBUG(10, ("could not get stream info: %s\n",
4452 nt_errstr(status)));
4453 reply_nterror(req, status);
4457 status = marshall_stream_info(num_streams, streams,
4458 pdata, max_data_bytes,
4461 if (!NT_STATUS_IS_OK(status)) {
4462 DEBUG(10, ("marshall_stream_info failed: %s\n",
4463 nt_errstr(status)));
4464 reply_nterror(req, status);
4468 TALLOC_FREE(streams);
4472 case SMB_QUERY_COMPRESSION_INFO:
4473 case SMB_FILE_COMPRESSION_INFORMATION:
4474 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4475 SOFF_T(pdata,0,file_size);
4476 SIVAL(pdata,8,0); /* ??? */
4477 SIVAL(pdata,12,0); /* ??? */
4481 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4482 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4483 put_long_date_timespec(pdata,create_time_ts);
4484 put_long_date_timespec(pdata+8,atime_ts);
4485 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4486 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4487 SOFF_T(pdata,32,allocation_size);
4488 SOFF_T(pdata,40,file_size);
4489 SIVAL(pdata,48,mode);
4490 SIVAL(pdata,52,0); /* ??? */
4494 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4495 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4496 SIVAL(pdata,0,mode);
4502 * CIFS UNIX Extensions.
4505 case SMB_QUERY_FILE_UNIX_BASIC:
4507 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4508 data_size = PTR_DIFF(pdata,(*ppdata));
4512 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4514 for (i=0; i<100; i++)
4515 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4521 case SMB_QUERY_FILE_UNIX_INFO2:
4523 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4524 data_size = PTR_DIFF(pdata,(*ppdata));
4528 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4530 for (i=0; i<100; i++)
4531 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4537 case SMB_QUERY_FILE_UNIX_LINK:
4539 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4542 reply_nterror(req, NT_STATUS_NO_MEMORY);
4546 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4548 if(!S_ISLNK(sbuf.st_mode)) {
4549 reply_unixerror(req, ERRSRV,
4554 reply_unixerror(req, ERRDOS, ERRbadlink);
4557 len = SMB_VFS_READLINK(conn,fullpathname,
4560 reply_unixerror(req, ERRDOS,
4565 len = srvstr_push(dstart, req->flags2,
4567 PTR_DIFF(dend, pdata),
4570 data_size = PTR_DIFF(pdata,(*ppdata));
4575 #if defined(HAVE_POSIX_ACLS)
4576 case SMB_QUERY_POSIX_ACL:
4578 SMB_ACL_T file_acl = NULL;
4579 SMB_ACL_T def_acl = NULL;
4580 uint16 num_file_acls = 0;
4581 uint16 num_def_acls = 0;
4583 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4584 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4586 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4589 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4590 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4594 NT_STATUS_NOT_IMPLEMENTED);
4598 if (S_ISDIR(sbuf.st_mode)) {
4599 if (fsp && fsp->is_directory) {
4600 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4602 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4604 def_acl = free_empty_sys_acl(conn, def_acl);
4607 num_file_acls = count_acl_entries(conn, file_acl);
4608 num_def_acls = count_acl_entries(conn, def_acl);
4610 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4611 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4613 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4614 SMB_POSIX_ACL_HEADER_SIZE) ));
4616 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4619 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4623 NT_STATUS_BUFFER_TOO_SMALL);
4627 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4628 SSVAL(pdata,2,num_file_acls);
4629 SSVAL(pdata,4,num_def_acls);
4630 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4632 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4635 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4638 req, NT_STATUS_INTERNAL_ERROR);
4641 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4643 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4646 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4650 NT_STATUS_INTERNAL_ERROR);
4655 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4658 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4660 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4666 case SMB_QUERY_POSIX_LOCK:
4668 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4670 SMB_BIG_UINT offset;
4672 enum brl_type lock_type;
4674 if (total_data != POSIX_LOCK_DATA_SIZE) {
4676 req, NT_STATUS_INVALID_PARAMETER);
4680 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4681 case POSIX_LOCK_TYPE_READ:
4682 lock_type = READ_LOCK;
4684 case POSIX_LOCK_TYPE_WRITE:
4685 lock_type = WRITE_LOCK;
4687 case POSIX_LOCK_TYPE_UNLOCK:
4689 /* There's no point in asking for an unlock... */
4692 NT_STATUS_INVALID_PARAMETER);
4696 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4697 #if defined(HAVE_LONGLONG)
4698 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4699 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4700 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4701 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4702 #else /* HAVE_LONGLONG */
4703 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4704 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4705 #endif /* HAVE_LONGLONG */
4707 status = query_lock(fsp,
4714 if (ERROR_WAS_LOCK_DENIED(status)) {
4715 /* Here we need to report who has it locked... */
4716 data_size = POSIX_LOCK_DATA_SIZE;
4718 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4719 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4720 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4721 #if defined(HAVE_LONGLONG)
4722 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4723 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4724 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4725 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4726 #else /* HAVE_LONGLONG */
4727 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4728 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4729 #endif /* HAVE_LONGLONG */
4731 } else if (NT_STATUS_IS_OK(status)) {
4732 /* For success we just return a copy of what we sent
4733 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4734 data_size = POSIX_LOCK_DATA_SIZE;
4735 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4736 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4738 reply_nterror(req, status);
4745 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4749 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4755 /****************************************************************************
4756 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4758 ****************************************************************************/
4760 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4761 connection_struct *conn,
4762 const char *oldname_in,
4763 const char *newname_in)
4765 SMB_STRUCT_STAT sbuf1, sbuf2;
4766 char *last_component_oldname = NULL;
4767 char *last_component_newname = NULL;
4768 char *oldname = NULL;
4769 char *newname = NULL;
4770 NTSTATUS status = NT_STATUS_OK;
4775 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4776 &last_component_oldname, &sbuf1);
4777 if (!NT_STATUS_IS_OK(status)) {
4781 status = check_name(conn, oldname);
4782 if (!NT_STATUS_IS_OK(status)) {
4786 /* source must already exist. */
4787 if (!VALID_STAT(sbuf1)) {
4788 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4791 status = unix_convert(ctx, conn, newname_in, False, &newname,
4792 &last_component_newname, &sbuf2);
4793 if (!NT_STATUS_IS_OK(status)) {
4797 status = check_name(conn, newname);
4798 if (!NT_STATUS_IS_OK(status)) {
4802 /* Disallow if newname already exists. */
4803 if (VALID_STAT(sbuf2)) {
4804 return NT_STATUS_OBJECT_NAME_COLLISION;
4807 /* No links from a directory. */
4808 if (S_ISDIR(sbuf1.st_mode)) {
4809 return NT_STATUS_FILE_IS_A_DIRECTORY;
4812 /* Ensure this is within the share. */
4813 status = check_reduced_name(conn, oldname);
4814 if (!NT_STATUS_IS_OK(status)) {
4818 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4820 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4821 status = map_nt_error_from_unix(errno);
4822 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4823 nt_errstr(status), newname, oldname));
4829 /****************************************************************************
4830 Deal with setting the time from any of the setfilepathinfo functions.
4831 ****************************************************************************/
4833 NTSTATUS smb_set_file_time(connection_struct *conn,
4836 const SMB_STRUCT_STAT *psbuf,
4837 struct timespec ts[2],
4838 bool setting_write_time)
4841 FILE_NOTIFY_CHANGE_LAST_ACCESS
4842 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4844 if (!VALID_STAT(*psbuf)) {
4845 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4848 /* get some defaults (no modifications) if any info is zero or -1. */
4849 if (null_timespec(ts[0])) {
4850 ts[0] = get_atimespec(psbuf);
4851 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4854 if (null_timespec(ts[1])) {
4855 ts[1] = get_mtimespec(psbuf);
4856 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4859 if (!setting_write_time) {
4860 /* ts[1] comes from change time, not write time. */
4861 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4864 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4865 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4868 * Try and set the times of this file if
4869 * they are different from the current values.
4873 struct timespec mts = get_mtimespec(psbuf);
4874 struct timespec ats = get_atimespec(psbuf);
4875 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4876 return NT_STATUS_OK;
4880 if (setting_write_time) {
4882 * This was a setfileinfo on an open file.
4883 * NT does this a lot. We also need to
4884 * set the time here, as it can be read by
4885 * FindFirst/FindNext and with the patch for bug #2045
4886 * in smbd/fileio.c it ensures that this timestamp is
4887 * kept sticky even after a write. We save the request
4888 * away and will set it on file close and after a write. JRA.
4891 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4892 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4895 set_sticky_write_time_fsp(fsp, ts[1]);
4897 set_sticky_write_time_path(conn, fname,
4898 vfs_file_id_from_sbuf(conn, psbuf),
4903 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4905 if(file_ntimes(conn, fname, ts)!=0) {
4906 return map_nt_error_from_unix(errno);
4908 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4910 return NT_STATUS_OK;
4913 /****************************************************************************
4914 Deal with setting the dosmode from any of the setfilepathinfo functions.
4915 ****************************************************************************/
4917 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4919 SMB_STRUCT_STAT *psbuf,
4922 if (!VALID_STAT(*psbuf)) {
4923 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4927 if (S_ISDIR(psbuf->st_mode)) {
4934 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4936 /* check the mode isn't different, before changing it */
4937 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4939 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4940 fname, (unsigned int)dosmode ));
4942 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4943 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4944 fname, strerror(errno)));
4945 return map_nt_error_from_unix(errno);
4948 return NT_STATUS_OK;
4951 /****************************************************************************
4952 Deal with setting the size from any of the setfilepathinfo functions.
4953 ****************************************************************************/
4955 static NTSTATUS smb_set_file_size(connection_struct *conn,
4956 struct smb_request *req,
4959 SMB_STRUCT_STAT *psbuf,
4962 NTSTATUS status = NT_STATUS_OK;
4963 files_struct *new_fsp = NULL;
4965 if (!VALID_STAT(*psbuf)) {
4966 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4969 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4971 if (size == get_file_size(*psbuf)) {
4972 return NT_STATUS_OK;
4975 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4976 fname, (double)size ));
4978 if (fsp && fsp->fh->fd != -1) {
4979 /* Handle based call. */
4980 if (vfs_set_filelen(fsp, size) == -1) {
4981 return map_nt_error_from_unix(errno);
4983 trigger_write_time_update_immediate(fsp);
4984 return NT_STATUS_OK;
4987 status = open_file_ntcreate(conn, req, fname, psbuf,
4988 FILE_WRITE_ATTRIBUTES,
4989 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4992 FILE_ATTRIBUTE_NORMAL,
4993 FORCE_OPLOCK_BREAK_TO_NONE,
4996 if (!NT_STATUS_IS_OK(status)) {
4997 /* NB. We check for open_was_deferred in the caller. */
5001 if (vfs_set_filelen(new_fsp, size) == -1) {
5002 status = map_nt_error_from_unix(errno);
5003 close_file(new_fsp,NORMAL_CLOSE);
5007 trigger_write_time_update_immediate(new_fsp);
5008 close_file(new_fsp,NORMAL_CLOSE);
5009 return NT_STATUS_OK;
5012 /****************************************************************************
5013 Deal with SMB_INFO_SET_EA.
5014 ****************************************************************************/
5016 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5022 struct ea_list *ea_list = NULL;
5023 TALLOC_CTX *ctx = NULL;
5024 NTSTATUS status = NT_STATUS_OK;
5026 if (total_data < 10) {
5028 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5029 length. They seem to have no effect. Bug #3212. JRA */
5031 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5032 /* We're done. We only get EA info in this call. */
5033 return NT_STATUS_OK;
5036 return NT_STATUS_INVALID_PARAMETER;
5039 if (IVAL(pdata,0) > total_data) {
5040 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5041 IVAL(pdata,0), (unsigned int)total_data));
5042 return NT_STATUS_INVALID_PARAMETER;
5046 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5048 return NT_STATUS_INVALID_PARAMETER;
5050 status = set_ea(conn, fsp, fname, ea_list);
5055 /****************************************************************************
5056 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5057 ****************************************************************************/
5059 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5064 SMB_STRUCT_STAT *psbuf)
5066 NTSTATUS status = NT_STATUS_OK;
5067 bool delete_on_close;
5070 if (total_data < 1) {
5071 return NT_STATUS_INVALID_PARAMETER;
5075 return NT_STATUS_INVALID_HANDLE;
5078 delete_on_close = (CVAL(pdata,0) ? True : False);
5079 dosmode = dos_mode(conn, fname, psbuf);
5081 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5082 "delete_on_close = %u\n",
5084 (unsigned int)dosmode,
5085 (unsigned int)delete_on_close ));
5087 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5089 if (!NT_STATUS_IS_OK(status)) {
5093 /* The set is across all open files on this dev/inode pair. */
5094 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
5095 return NT_STATUS_ACCESS_DENIED;
5097 return NT_STATUS_OK;
5100 /****************************************************************************
5101 Deal with SMB_FILE_POSITION_INFORMATION.
5102 ****************************************************************************/
5104 static NTSTATUS smb_file_position_information(connection_struct *conn,
5109 SMB_BIG_UINT position_information;
5111 if (total_data < 8) {
5112 return NT_STATUS_INVALID_PARAMETER;
5116 /* Ignore on pathname based set. */
5117 return NT_STATUS_OK;
5120 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5121 #ifdef LARGE_SMB_OFF_T
5122 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5123 #else /* LARGE_SMB_OFF_T */
5124 if (IVAL(pdata,4) != 0) {
5125 /* more than 32 bits? */
5126 return NT_STATUS_INVALID_PARAMETER;
5128 #endif /* LARGE_SMB_OFF_T */
5130 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5131 fsp->fsp_name, (double)position_information ));
5132 fsp->fh->position_information = position_information;
5133 return NT_STATUS_OK;
5136 /****************************************************************************
5137 Deal with SMB_FILE_MODE_INFORMATION.
5138 ****************************************************************************/
5140 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5146 if (total_data < 4) {
5147 return NT_STATUS_INVALID_PARAMETER;
5149 mode = IVAL(pdata,0);
5150 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5151 return NT_STATUS_INVALID_PARAMETER;
5153 return NT_STATUS_OK;
5156 /****************************************************************************
5157 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5158 ****************************************************************************/
5160 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5161 struct smb_request *req,
5166 char *link_target = NULL;
5167 const char *newname = fname;
5168 NTSTATUS status = NT_STATUS_OK;
5169 TALLOC_CTX *ctx = talloc_tos();
5171 /* Set a symbolic link. */
5172 /* Don't allow this if follow links is false. */
5174 if (total_data == 0) {
5175 return NT_STATUS_INVALID_PARAMETER;
5178 if (!lp_symlinks(SNUM(conn))) {
5179 return NT_STATUS_ACCESS_DENIED;
5182 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5183 total_data, STR_TERMINATE);
5186 return NT_STATUS_INVALID_PARAMETER;
5189 /* !widelinks forces the target path to be within the share. */
5190 /* This means we can interpret the target as a pathname. */
5191 if (!lp_widelinks(SNUM(conn))) {
5192 char *rel_name = NULL;
5193 char *last_dirp = NULL;
5195 if (*link_target == '/') {
5196 /* No absolute paths allowed. */
5197 return NT_STATUS_ACCESS_DENIED;
5199 rel_name = talloc_strdup(ctx,newname);
5201 return NT_STATUS_NO_MEMORY;
5203 last_dirp = strrchr_m(rel_name, '/');
5205 last_dirp[1] = '\0';
5207 rel_name = talloc_strdup(ctx,"./");
5209 return NT_STATUS_NO_MEMORY;
5212 rel_name = talloc_asprintf_append(rel_name,
5216 return NT_STATUS_NO_MEMORY;
5219 status = check_name(conn, rel_name);
5220 if (!NT_STATUS_IS_OK(status)) {
5225 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5226 newname, link_target ));
5228 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5229 return map_nt_error_from_unix(errno);
5232 return NT_STATUS_OK;
5235 /****************************************************************************
5236 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5237 ****************************************************************************/
5239 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5240 struct smb_request *req,
5241 const char *pdata, int total_data,
5244 char *oldname = NULL;
5245 TALLOC_CTX *ctx = talloc_tos();
5246 NTSTATUS status = NT_STATUS_OK;
5248 /* Set a hard link. */
5249 if (total_data == 0) {
5250 return NT_STATUS_INVALID_PARAMETER;
5253 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5254 total_data, STR_TERMINATE, &status);
5255 if (!NT_STATUS_IS_OK(status)) {
5259 status = resolve_dfspath(ctx, conn,
5260 req->flags2 & FLAGS2_DFS_PATHNAMES,
5263 if (!NT_STATUS_IS_OK(status)) {
5267 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5270 return hardlink_internals(ctx, conn, oldname, fname);
5273 /****************************************************************************
5274 Deal with SMB_FILE_RENAME_INFORMATION.
5275 ****************************************************************************/
5277 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5278 struct smb_request *req,
5287 char *newname = NULL;
5288 char *base_name = NULL;
5289 bool dest_has_wcard = False;
5290 NTSTATUS status = NT_STATUS_OK;
5292 TALLOC_CTX *ctx = talloc_tos();
5294 if (total_data < 13) {
5295 return NT_STATUS_INVALID_PARAMETER;
5298 overwrite = (CVAL(pdata,0) ? True : False);
5299 root_fid = IVAL(pdata,4);
5300 len = IVAL(pdata,8);
5302 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5303 return NT_STATUS_INVALID_PARAMETER;
5306 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5309 if (!NT_STATUS_IS_OK(status)) {
5313 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5316 status = resolve_dfspath_wcard(ctx, conn,
5317 req->flags2 & FLAGS2_DFS_PATHNAMES,
5321 if (!NT_STATUS_IS_OK(status)) {
5325 /* Check the new name has no '/' characters. */
5326 if (strchr_m(newname, '/')) {
5327 return NT_STATUS_NOT_SUPPORTED;
5330 /* Create the base directory. */
5331 base_name = talloc_strdup(ctx, fname);
5333 return NT_STATUS_NO_MEMORY;
5335 p = strrchr_m(base_name, '/');
5339 base_name = talloc_strdup(ctx, "./");
5341 return NT_STATUS_NO_MEMORY;
5344 /* Append the new name. */
5345 base_name = talloc_asprintf_append(base_name,
5349 return NT_STATUS_NO_MEMORY;
5353 SMB_STRUCT_STAT sbuf;
5354 char *newname_last_component = NULL;
5358 status = unix_convert(ctx, conn, newname, False,
5360 &newname_last_component,
5363 /* If an error we expect this to be
5364 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5366 if (!NT_STATUS_IS_OK(status)
5367 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5372 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5373 fsp->fnum, fsp->fsp_name, base_name ));
5374 status = rename_internals_fsp(conn, fsp, base_name,
5375 newname_last_component, 0,
5378 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5379 fname, base_name ));
5380 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5381 overwrite, False, dest_has_wcard,
5382 FILE_WRITE_ATTRIBUTES);
5388 /****************************************************************************
5389 Deal with SMB_SET_POSIX_ACL.
5390 ****************************************************************************/
5392 #if defined(HAVE_POSIX_ACLS)
5393 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5398 SMB_STRUCT_STAT *psbuf)
5400 uint16 posix_acl_version;
5401 uint16 num_file_acls;
5402 uint16 num_def_acls;
5403 bool valid_file_acls = True;
5404 bool valid_def_acls = True;
5406 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5407 return NT_STATUS_INVALID_PARAMETER;
5409 posix_acl_version = SVAL(pdata,0);
5410 num_file_acls = SVAL(pdata,2);
5411 num_def_acls = SVAL(pdata,4);
5413 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5414 valid_file_acls = False;
5418 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5419 valid_def_acls = False;
5423 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5424 return NT_STATUS_INVALID_PARAMETER;
5427 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5428 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5429 return NT_STATUS_INVALID_PARAMETER;
5432 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5433 fname ? fname : fsp->fsp_name,
5434 (unsigned int)num_file_acls,
5435 (unsigned int)num_def_acls));
5437 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5438 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5439 return map_nt_error_from_unix(errno);
5442 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5443 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5444 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5445 return map_nt_error_from_unix(errno);
5447 return NT_STATUS_OK;
5451 /****************************************************************************
5452 Deal with SMB_SET_POSIX_LOCK.
5453 ****************************************************************************/
5455 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5456 const struct smb_request *req,
5462 SMB_BIG_UINT offset;
5464 bool blocking_lock = False;
5465 enum brl_type lock_type;
5467 NTSTATUS status = NT_STATUS_OK;
5469 if (fsp == NULL || fsp->fh->fd == -1) {
5470 return NT_STATUS_INVALID_HANDLE;
5473 if (total_data != POSIX_LOCK_DATA_SIZE) {
5474 return NT_STATUS_INVALID_PARAMETER;
5477 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5478 case POSIX_LOCK_TYPE_READ:
5479 lock_type = READ_LOCK;
5481 case POSIX_LOCK_TYPE_WRITE:
5482 /* Return the right POSIX-mappable error code for files opened read-only. */
5483 if (!fsp->can_write) {
5484 return NT_STATUS_INVALID_HANDLE;
5486 lock_type = WRITE_LOCK;
5488 case POSIX_LOCK_TYPE_UNLOCK:
5489 lock_type = UNLOCK_LOCK;
5492 return NT_STATUS_INVALID_PARAMETER;
5495 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5496 blocking_lock = False;
5497 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5498 blocking_lock = True;
5500 return NT_STATUS_INVALID_PARAMETER;
5503 if (!lp_blocking_locks(SNUM(conn))) {
5504 blocking_lock = False;
5507 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5508 #if defined(HAVE_LONGLONG)
5509 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5510 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5511 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5512 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5513 #else /* HAVE_LONGLONG */
5514 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5515 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5516 #endif /* HAVE_LONGLONG */
5518 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5519 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5521 (unsigned int)lock_type,
5522 (unsigned int)lock_pid,
5526 if (lock_type == UNLOCK_LOCK) {
5527 status = do_unlock(smbd_messaging_context(),
5534 uint32 block_smbpid;
5536 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5547 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5549 * A blocking lock was requested. Package up
5550 * this smb into a queued request and push it
5551 * onto the blocking lock queue.
5553 if(push_blocking_lock_request(br_lck,
5556 -1, /* infinite timeout. */
5564 TALLOC_FREE(br_lck);
5568 TALLOC_FREE(br_lck);
5574 /****************************************************************************
5575 Deal with SMB_INFO_STANDARD.
5576 ****************************************************************************/
5578 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5583 const SMB_STRUCT_STAT *psbuf)
5585 struct timespec ts[2];
5587 if (total_data < 12) {
5588 return NT_STATUS_INVALID_PARAMETER;
5592 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5594 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5596 DEBUG(10,("smb_set_info_standard: file %s\n",
5597 fname ? fname : fsp->fsp_name ));
5599 return smb_set_file_time(conn,
5607 /****************************************************************************
5608 Deal with SMB_SET_FILE_BASIC_INFO.
5609 ****************************************************************************/
5611 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5616 SMB_STRUCT_STAT *psbuf)
5618 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5619 struct timespec write_time;
5620 struct timespec changed_time;
5622 struct timespec ts[2];
5623 NTSTATUS status = NT_STATUS_OK;
5624 bool setting_write_time = true;
5626 if (total_data < 36) {
5627 return NT_STATUS_INVALID_PARAMETER;
5630 /* Set the attributes */
5631 dosmode = IVAL(pdata,32);
5632 status = smb_set_file_dosmode(conn,
5636 if (!NT_STATUS_IS_OK(status)) {
5640 /* Ignore create time at offset pdata. */
5643 ts[0] = interpret_long_date(pdata+8);
5645 write_time = interpret_long_date(pdata+16);
5646 changed_time = interpret_long_date(pdata+24);
5649 ts[1] = timespec_min(&write_time, &changed_time);
5651 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5655 /* Prefer a defined time to an undefined one. */
5656 if (null_timespec(ts[1])) {
5657 if (null_timespec(write_time)) {
5658 ts[1] = changed_time;
5659 setting_write_time = false;
5665 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5666 fname ? fname : fsp->fsp_name ));
5668 return smb_set_file_time(conn,
5673 setting_write_time);
5676 /****************************************************************************
5677 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5678 ****************************************************************************/
5680 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5681 struct smb_request *req,
5686 SMB_STRUCT_STAT *psbuf)
5688 SMB_BIG_UINT allocation_size = 0;
5689 NTSTATUS status = NT_STATUS_OK;
5690 files_struct *new_fsp = NULL;
5692 if (!VALID_STAT(*psbuf)) {
5693 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5696 if (total_data < 8) {
5697 return NT_STATUS_INVALID_PARAMETER;
5700 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5701 #ifdef LARGE_SMB_OFF_T
5702 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5703 #else /* LARGE_SMB_OFF_T */
5704 if (IVAL(pdata,4) != 0) {
5705 /* more than 32 bits? */
5706 return NT_STATUS_INVALID_PARAMETER;
5708 #endif /* LARGE_SMB_OFF_T */
5710 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5711 fname, (double)allocation_size ));
5713 if (allocation_size) {
5714 allocation_size = smb_roundup(conn, allocation_size);
5717 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5718 fname, (double)allocation_size ));
5720 if (fsp && fsp->fh->fd != -1) {
5721 /* Open file handle. */
5722 /* Only change if needed. */
5723 if (allocation_size != get_file_size(*psbuf)) {
5724 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5725 return map_nt_error_from_unix(errno);
5728 /* But always update the time. */
5730 * This is equivalent to a write. Ensure it's seen immediately
5731 * if there are no pending writes.
5733 trigger_write_time_update_immediate(fsp);
5734 return NT_STATUS_OK;
5737 /* Pathname or stat or directory file. */
5739 status = open_file_ntcreate(conn, req, fname, psbuf,
5741 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5744 FILE_ATTRIBUTE_NORMAL,
5745 FORCE_OPLOCK_BREAK_TO_NONE,
5748 if (!NT_STATUS_IS_OK(status)) {
5749 /* NB. We check for open_was_deferred in the caller. */
5753 /* Only change if needed. */
5754 if (allocation_size != get_file_size(*psbuf)) {
5755 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5756 status = map_nt_error_from_unix(errno);
5757 close_file(new_fsp,NORMAL_CLOSE);
5762 /* Changing the allocation size should set the last mod time. */
5764 * This is equivalent to a write. Ensure it's seen immediately
5765 * if there are no pending writes.
5767 trigger_write_time_update_immediate(new_fsp);
5769 close_file(new_fsp,NORMAL_CLOSE);
5770 return NT_STATUS_OK;
5773 /****************************************************************************
5774 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5775 ****************************************************************************/
5777 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5778 struct smb_request *req,
5783 SMB_STRUCT_STAT *psbuf)
5787 if (total_data < 8) {
5788 return NT_STATUS_INVALID_PARAMETER;
5791 size = IVAL(pdata,0);
5792 #ifdef LARGE_SMB_OFF_T
5793 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5794 #else /* LARGE_SMB_OFF_T */
5795 if (IVAL(pdata,4) != 0) {
5796 /* more than 32 bits? */
5797 return NT_STATUS_INVALID_PARAMETER;
5799 #endif /* LARGE_SMB_OFF_T */
5800 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5801 "file %s to %.0f\n", fname, (double)size ));
5803 return smb_set_file_size(conn, req,
5810 /****************************************************************************
5811 Allow a UNIX info mknod.
5812 ****************************************************************************/
5814 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5818 SMB_STRUCT_STAT *psbuf)
5820 uint32 file_type = IVAL(pdata,56);
5821 #if defined(HAVE_MAKEDEV)
5822 uint32 dev_major = IVAL(pdata,60);
5823 uint32 dev_minor = IVAL(pdata,68);
5825 SMB_DEV_T dev = (SMB_DEV_T)0;
5826 uint32 raw_unixmode = IVAL(pdata,84);
5830 if (total_data < 100) {
5831 return NT_STATUS_INVALID_PARAMETER;
5834 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5835 if (!NT_STATUS_IS_OK(status)) {
5839 #if defined(HAVE_MAKEDEV)
5840 dev = makedev(dev_major, dev_minor);
5843 switch (file_type) {
5844 #if defined(S_IFIFO)
5845 case UNIX_TYPE_FIFO:
5846 unixmode |= S_IFIFO;
5849 #if defined(S_IFSOCK)
5850 case UNIX_TYPE_SOCKET:
5851 unixmode |= S_IFSOCK;
5854 #if defined(S_IFCHR)
5855 case UNIX_TYPE_CHARDEV:
5856 unixmode |= S_IFCHR;
5859 #if defined(S_IFBLK)
5860 case UNIX_TYPE_BLKDEV:
5861 unixmode |= S_IFBLK;
5865 return NT_STATUS_INVALID_PARAMETER;
5868 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5869 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5871 /* Ok - do the mknod. */
5872 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5873 return map_nt_error_from_unix(errno);
5876 /* If any of the other "set" calls fail we
5877 * don't want to end up with a half-constructed mknod.
5880 if (lp_inherit_perms(SNUM(conn))) {
5882 conn, parent_dirname(fname),
5886 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5887 status = map_nt_error_from_unix(errno);
5888 SMB_VFS_UNLINK(conn,fname);
5891 return NT_STATUS_OK;
5894 /****************************************************************************
5895 Deal with SMB_SET_FILE_UNIX_BASIC.
5896 ****************************************************************************/
5898 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5899 struct smb_request *req,
5904 SMB_STRUCT_STAT *psbuf)
5906 struct timespec ts[2];
5907 uint32 raw_unixmode;
5910 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5911 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5912 NTSTATUS status = NT_STATUS_OK;
5913 bool delete_on_fail = False;
5914 enum perm_type ptype;
5916 if (total_data < 100) {
5917 return NT_STATUS_INVALID_PARAMETER;
5920 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5921 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5922 size=IVAL(pdata,0); /* first 8 Bytes are size */
5923 #ifdef LARGE_SMB_OFF_T
5924 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5925 #else /* LARGE_SMB_OFF_T */
5926 if (IVAL(pdata,4) != 0) {
5927 /* more than 32 bits? */
5928 return NT_STATUS_INVALID_PARAMETER;
5930 #endif /* LARGE_SMB_OFF_T */
5933 ts[0] = interpret_long_date(pdata+24); /* access_time */
5934 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5935 set_owner = (uid_t)IVAL(pdata,40);
5936 set_grp = (gid_t)IVAL(pdata,48);
5937 raw_unixmode = IVAL(pdata,84);
5939 if (VALID_STAT(*psbuf)) {
5940 if (S_ISDIR(psbuf->st_mode)) {
5941 ptype = PERM_EXISTING_DIR;
5943 ptype = PERM_EXISTING_FILE;
5946 ptype = PERM_NEW_FILE;
5949 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5950 if (!NT_STATUS_IS_OK(status)) {
5954 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5955 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5956 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5958 if (!VALID_STAT(*psbuf)) {
5960 * The only valid use of this is to create character and block
5961 * devices, and named pipes. This is deprecated (IMHO) and
5962 * a new info level should be used for mknod. JRA.
5965 status = smb_unix_mknod(conn,
5970 if (!NT_STATUS_IS_OK(status)) {
5974 /* Ensure we don't try and change anything else. */
5975 raw_unixmode = SMB_MODE_NO_CHANGE;
5976 size = get_file_size(*psbuf);
5977 ts[0] = get_atimespec(psbuf);
5978 ts[1] = get_mtimespec(psbuf);
5980 * We continue here as we might want to change the
5983 delete_on_fail = True;
5987 /* Horrible backwards compatibility hack as an old server bug
5988 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5992 size = get_file_size(*psbuf);
5997 * Deal with the UNIX specific mode set.
6000 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6001 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6002 (unsigned int)unixmode, fname ));
6003 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6004 return map_nt_error_from_unix(errno);
6009 * Deal with the UNIX specific uid set.
6012 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6015 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6016 (unsigned int)set_owner, fname ));
6018 if (S_ISLNK(psbuf->st_mode)) {
6019 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6021 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6025 status = map_nt_error_from_unix(errno);
6026 if (delete_on_fail) {
6027 SMB_VFS_UNLINK(conn,fname);
6034 * Deal with the UNIX specific gid set.
6037 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6038 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6039 (unsigned int)set_owner, fname ));
6040 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6041 status = map_nt_error_from_unix(errno);
6042 if (delete_on_fail) {
6043 SMB_VFS_UNLINK(conn,fname);
6049 /* Deal with any size changes. */
6051 status = smb_set_file_size(conn, req,
6056 if (!NT_STATUS_IS_OK(status)) {
6060 /* Deal with any time changes. */
6062 return smb_set_file_time(conn,
6070 /****************************************************************************
6071 Deal with SMB_SET_FILE_UNIX_INFO2.
6072 ****************************************************************************/
6074 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6075 struct smb_request *req,
6080 SMB_STRUCT_STAT *psbuf)
6086 if (total_data < 116) {
6087 return NT_STATUS_INVALID_PARAMETER;
6090 /* Start by setting all the fields that are common between UNIX_BASIC
6093 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6095 if (!NT_STATUS_IS_OK(status)) {
6099 smb_fflags = IVAL(pdata, 108);
6100 smb_fmask = IVAL(pdata, 112);
6102 /* NB: We should only attempt to alter the file flags if the client
6103 * sends a non-zero mask.
6105 if (smb_fmask != 0) {
6106 int stat_fflags = 0;
6108 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6110 /* Client asked to alter a flag we don't understand. */
6111 return NT_STATUS_INVALID_PARAMETER;
6114 if (fsp && fsp->fh->fd != -1) {
6115 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6116 return NT_STATUS_NOT_SUPPORTED;
6118 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6119 return map_nt_error_from_unix(errno);
6124 /* XXX: need to add support for changing the create_time here. You
6125 * can do this for paths on Darwin with setattrlist(2). The right way
6126 * to hook this up is probably by extending the VFS utimes interface.
6129 return NT_STATUS_OK;
6132 /****************************************************************************
6133 Create a directory with POSIX semantics.
6134 ****************************************************************************/
6136 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6137 struct smb_request *req,
6141 SMB_STRUCT_STAT *psbuf,
6142 int *pdata_return_size)
6144 NTSTATUS status = NT_STATUS_OK;
6145 uint32 raw_unixmode = 0;
6146 uint32 mod_unixmode = 0;
6147 mode_t unixmode = (mode_t)0;
6148 files_struct *fsp = NULL;
6149 uint16 info_level_return = 0;
6151 char *pdata = *ppdata;
6153 if (total_data < 18) {
6154 return NT_STATUS_INVALID_PARAMETER;
6157 raw_unixmode = IVAL(pdata,8);
6158 /* Next 4 bytes are not yet defined. */
6160 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6161 if (!NT_STATUS_IS_OK(status)) {
6165 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6167 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6168 fname, (unsigned int)unixmode ));
6170 status = open_directory(conn, req,
6173 FILE_READ_ATTRIBUTES, /* Just a stat open */
6174 FILE_SHARE_NONE, /* Ignored for stat opens */
6181 if (NT_STATUS_IS_OK(status)) {
6182 close_file(fsp, NORMAL_CLOSE);
6185 info_level_return = SVAL(pdata,16);
6187 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6188 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6189 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6190 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6192 *pdata_return_size = 12;
6195 /* Realloc the data size */
6196 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6197 if (*ppdata == NULL) {
6198 *pdata_return_size = 0;
6199 return NT_STATUS_NO_MEMORY;
6203 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6204 SSVAL(pdata,2,0); /* No fnum. */
6205 SIVAL(pdata,4,info); /* Was directory created. */
6207 switch (info_level_return) {
6208 case SMB_QUERY_FILE_UNIX_BASIC:
6209 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6210 SSVAL(pdata,10,0); /* Padding. */
6211 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6213 case SMB_QUERY_FILE_UNIX_INFO2:
6214 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6215 SSVAL(pdata,10,0); /* Padding. */
6216 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6219 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6220 SSVAL(pdata,10,0); /* Padding. */
6227 /****************************************************************************
6228 Open/Create a file with POSIX semantics.
6229 ****************************************************************************/
6231 static NTSTATUS smb_posix_open(connection_struct *conn,
6232 struct smb_request *req,
6236 SMB_STRUCT_STAT *psbuf,
6237 int *pdata_return_size)
6239 bool extended_oplock_granted = False;
6240 char *pdata = *ppdata;
6242 uint32 wire_open_mode = 0;
6243 uint32 raw_unixmode = 0;
6244 uint32 mod_unixmode = 0;
6245 uint32 create_disp = 0;
6246 uint32 access_mask = 0;
6247 uint32 create_options = 0;
6248 NTSTATUS status = NT_STATUS_OK;
6249 mode_t unixmode = (mode_t)0;
6250 files_struct *fsp = NULL;
6251 int oplock_request = 0;
6253 uint16 info_level_return = 0;
6255 if (total_data < 18) {
6256 return NT_STATUS_INVALID_PARAMETER;
6259 flags = IVAL(pdata,0);
6260 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6261 if (oplock_request) {
6262 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6265 wire_open_mode = IVAL(pdata,4);
6267 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6268 return smb_posix_mkdir(conn, req,
6276 switch (wire_open_mode & SMB_ACCMODE) {
6278 access_mask = FILE_READ_DATA;
6281 access_mask = FILE_WRITE_DATA;
6284 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6287 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6288 (unsigned int)wire_open_mode ));
6289 return NT_STATUS_INVALID_PARAMETER;
6292 wire_open_mode &= ~SMB_ACCMODE;
6294 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6295 create_disp = FILE_CREATE;
6296 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6297 create_disp = FILE_OVERWRITE_IF;
6298 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6299 create_disp = FILE_OPEN_IF;
6301 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6302 (unsigned int)wire_open_mode ));
6303 return NT_STATUS_INVALID_PARAMETER;
6306 raw_unixmode = IVAL(pdata,8);
6307 /* Next 4 bytes are not yet defined. */
6309 status = unix_perms_from_wire(conn,
6312 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6315 if (!NT_STATUS_IS_OK(status)) {
6319 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6321 if (wire_open_mode & SMB_O_SYNC) {
6322 create_options |= FILE_WRITE_THROUGH;
6324 if (wire_open_mode & SMB_O_APPEND) {
6325 access_mask |= FILE_APPEND_DATA;
6327 if (wire_open_mode & SMB_O_DIRECT) {
6328 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6331 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6333 (unsigned int)wire_open_mode,
6334 (unsigned int)unixmode ));
6336 status = open_file_ntcreate(conn, req,
6340 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6342 0, /* no create options yet. */
6348 if (!NT_STATUS_IS_OK(status)) {
6352 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6353 extended_oplock_granted = True;
6356 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6357 extended_oplock_granted = True;
6360 info_level_return = SVAL(pdata,16);
6362 /* Allocate the correct return size. */
6364 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6365 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6366 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6367 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6369 *pdata_return_size = 12;
6372 /* Realloc the data size */
6373 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6374 if (*ppdata == NULL) {
6375 close_file(fsp,ERROR_CLOSE);
6376 *pdata_return_size = 0;
6377 return NT_STATUS_NO_MEMORY;
6381 if (extended_oplock_granted) {
6382 if (flags & REQUEST_BATCH_OPLOCK) {
6383 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6385 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6387 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6388 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6390 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6393 SSVAL(pdata,2,fsp->fnum);
6394 SIVAL(pdata,4,info); /* Was file created etc. */
6396 switch (info_level_return) {
6397 case SMB_QUERY_FILE_UNIX_BASIC:
6398 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6399 SSVAL(pdata,10,0); /* padding. */
6400 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6402 case SMB_QUERY_FILE_UNIX_INFO2:
6403 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6404 SSVAL(pdata,10,0); /* padding. */
6405 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6408 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6409 SSVAL(pdata,10,0); /* padding. */
6412 return NT_STATUS_OK;
6415 /****************************************************************************
6416 Delete a file with POSIX semantics.
6417 ****************************************************************************/
6419 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6420 struct smb_request *req,
6424 SMB_STRUCT_STAT *psbuf)
6426 NTSTATUS status = NT_STATUS_OK;
6427 files_struct *fsp = NULL;
6432 struct share_mode_lock *lck = NULL;
6434 if (total_data < 2) {
6435 return NT_STATUS_INVALID_PARAMETER;
6438 flags = SVAL(pdata,0);
6440 if (!VALID_STAT(*psbuf)) {
6441 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6444 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6445 !VALID_STAT_OF_DIR(*psbuf)) {
6446 return NT_STATUS_NOT_A_DIRECTORY;
6449 DEBUG(10,("smb_posix_unlink: %s %s\n",
6450 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6453 if (VALID_STAT_OF_DIR(*psbuf)) {
6454 status = open_directory(conn, req,
6458 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6461 FILE_FLAG_POSIX_SEMANTICS|0777,
6466 status = open_file_ntcreate(conn, req,
6470 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6473 FILE_FLAG_POSIX_SEMANTICS|0777,
6474 0, /* No oplock, but break existing ones. */
6479 if (!NT_STATUS_IS_OK(status)) {
6484 * Don't lie to client. If we can't really delete due to
6485 * non-POSIX opens return SHARING_VIOLATION.
6488 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6491 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6492 "lock for file %s\n", fsp->fsp_name));
6493 close_file(fsp, NORMAL_CLOSE);
6494 return NT_STATUS_INVALID_PARAMETER;
6498 * See if others still have the file open. If this is the case, then
6499 * don't delete. If all opens are POSIX delete we can set the delete
6500 * on close disposition.
6502 for (i=0; i<lck->num_share_modes; i++) {
6503 struct share_mode_entry *e = &lck->share_modes[i];
6504 if (is_valid_share_mode_entry(e)) {
6505 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6508 /* Fail with sharing violation. */
6509 close_file(fsp, NORMAL_CLOSE);
6511 return NT_STATUS_SHARING_VIOLATION;
6516 * Set the delete on close.
6518 status = smb_set_file_disposition_info(conn,
6525 if (!NT_STATUS_IS_OK(status)) {
6526 close_file(fsp, NORMAL_CLOSE);
6531 return close_file(fsp, NORMAL_CLOSE);
6534 /****************************************************************************
6535 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6536 ****************************************************************************/
6538 static void call_trans2setfilepathinfo(connection_struct *conn,
6539 struct smb_request *req,
6540 unsigned int tran_call,
6541 char **pparams, int total_params,
6542 char **ppdata, int total_data,
6543 unsigned int max_data_bytes)
6545 char *params = *pparams;
6546 char *pdata = *ppdata;
6548 SMB_STRUCT_STAT sbuf;
6550 files_struct *fsp = NULL;
6551 NTSTATUS status = NT_STATUS_OK;
6552 int data_return_size = 0;
6553 TALLOC_CTX *ctx = talloc_tos();
6556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6562 if (tran_call == TRANSACT2_SETFILEINFO) {
6563 if (total_params < 4) {
6564 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6568 fsp = file_fsp(SVAL(params,0));
6569 /* Basic check for non-null fsp. */
6570 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6573 info_level = SVAL(params,2);
6575 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6577 reply_nterror(req, NT_STATUS_NO_MEMORY);
6581 if(fsp->is_directory || fsp->fh->fd == -1) {
6583 * This is actually a SETFILEINFO on a directory
6584 * handle (returned from an NT SMB). NT5.0 seems
6585 * to do this call. JRA.
6587 if (INFO_LEVEL_IS_UNIX(info_level)) {
6588 /* Always do lstat for UNIX calls. */
6589 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6590 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6591 reply_unixerror(req,ERRDOS,ERRbadpath);
6595 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6596 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6597 reply_unixerror(req,ERRDOS,ERRbadpath);
6601 } else if (fsp->print_file) {
6603 * Doing a DELETE_ON_CLOSE should cancel a print job.
6605 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6606 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6608 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6611 send_trans2_replies(conn, req, params, 2,
6616 reply_unixerror(req, ERRDOS, ERRbadpath);
6621 * Original code - this is an open file.
6623 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6627 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6628 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6629 reply_unixerror(req, ERRDOS, ERRbadfid);
6635 if (total_params < 7) {
6636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6640 info_level = SVAL(params,0);
6641 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6642 total_params - 6, STR_TERMINATE,
6644 if (!NT_STATUS_IS_OK(status)) {
6645 reply_nterror(req, status);
6649 status = resolve_dfspath(ctx, conn,
6650 req->flags2 & FLAGS2_DFS_PATHNAMES,
6653 if (!NT_STATUS_IS_OK(status)) {
6654 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6655 reply_botherror(req,
6656 NT_STATUS_PATH_NOT_COVERED,
6657 ERRSRV, ERRbadpath);
6660 reply_nterror(req, status);
6664 status = unix_convert(ctx, conn, fname, False,
6665 &fname, NULL, &sbuf);
6666 if (!NT_STATUS_IS_OK(status)) {
6667 reply_nterror(req, status);
6671 status = check_name(conn, fname);
6672 if (!NT_STATUS_IS_OK(status)) {
6673 reply_nterror(req, status);
6677 if (INFO_LEVEL_IS_UNIX(info_level)) {
6679 * For CIFS UNIX extensions the target name may not exist.
6682 /* Always do lstat for UNIX calls. */
6683 SMB_VFS_LSTAT(conn,fname,&sbuf);
6685 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6686 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6687 reply_unixerror(req, ERRDOS, ERRbadpath);
6692 if (!CAN_WRITE(conn)) {
6693 reply_doserror(req, ERRSRV, ERRaccess);
6697 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6698 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6702 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6703 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6705 /* Realloc the parameter size */
6706 *pparams = (char *)SMB_REALLOC(*pparams,2);
6707 if (*pparams == NULL) {
6708 reply_nterror(req, NT_STATUS_NO_MEMORY);
6715 switch (info_level) {
6717 case SMB_INFO_STANDARD:
6719 status = smb_set_info_standard(conn,
6728 case SMB_INFO_SET_EA:
6730 status = smb_info_set_ea(conn,
6738 case SMB_SET_FILE_BASIC_INFO:
6739 case SMB_FILE_BASIC_INFORMATION:
6741 status = smb_set_file_basic_info(conn,
6750 case SMB_FILE_ALLOCATION_INFORMATION:
6751 case SMB_SET_FILE_ALLOCATION_INFO:
6753 status = smb_set_file_allocation_info(conn, req,
6762 case SMB_FILE_END_OF_FILE_INFORMATION:
6763 case SMB_SET_FILE_END_OF_FILE_INFO:
6765 status = smb_set_file_end_of_file_info(conn, req,
6774 case SMB_FILE_DISPOSITION_INFORMATION:
6775 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6778 /* JRA - We used to just ignore this on a path ?
6779 * Shouldn't this be invalid level on a pathname
6782 if (tran_call != TRANSACT2_SETFILEINFO) {
6783 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6786 status = smb_set_file_disposition_info(conn,
6795 case SMB_FILE_POSITION_INFORMATION:
6797 status = smb_file_position_information(conn,
6804 /* From tridge Samba4 :
6805 * MODE_INFORMATION in setfileinfo (I have no
6806 * idea what "mode information" on a file is - it takes a value of 0,
6807 * 2, 4 or 6. What could it be?).
6810 case SMB_FILE_MODE_INFORMATION:
6812 status = smb_file_mode_information(conn,
6819 * CIFS UNIX extensions.
6822 case SMB_SET_FILE_UNIX_BASIC:
6824 status = smb_set_file_unix_basic(conn, req,
6833 case SMB_SET_FILE_UNIX_INFO2:
6835 status = smb_set_file_unix_info2(conn, req,
6844 case SMB_SET_FILE_UNIX_LINK:
6846 if (tran_call != TRANSACT2_SETPATHINFO) {
6847 /* We must have a pathname for this. */
6848 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6851 status = smb_set_file_unix_link(conn, req, pdata,
6856 case SMB_SET_FILE_UNIX_HLINK:
6858 if (tran_call != TRANSACT2_SETPATHINFO) {
6859 /* We must have a pathname for this. */
6860 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6863 status = smb_set_file_unix_hlink(conn, req,
6869 case SMB_FILE_RENAME_INFORMATION:
6871 status = smb_file_rename_information(conn, req,
6877 #if defined(HAVE_POSIX_ACLS)
6878 case SMB_SET_POSIX_ACL:
6880 status = smb_set_posix_acl(conn,
6890 case SMB_SET_POSIX_LOCK:
6892 if (tran_call != TRANSACT2_SETFILEINFO) {
6893 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6896 status = smb_set_posix_lock(conn, req,
6897 pdata, total_data, fsp);
6901 case SMB_POSIX_PATH_OPEN:
6903 if (tran_call != TRANSACT2_SETPATHINFO) {
6904 /* We must have a pathname for this. */
6905 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6909 status = smb_posix_open(conn, req,
6918 case SMB_POSIX_PATH_UNLINK:
6920 if (tran_call != TRANSACT2_SETPATHINFO) {
6921 /* We must have a pathname for this. */
6922 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6926 status = smb_posix_unlink(conn, req,
6935 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6940 if (!NT_STATUS_IS_OK(status)) {
6941 if (open_was_deferred(req->mid)) {
6942 /* We have re-scheduled this call. */
6945 if (blocking_lock_was_deferred(req->mid)) {
6946 /* We have re-scheduled this call. */
6949 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6950 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6951 ERRSRV, ERRbadpath);
6954 if (info_level == SMB_POSIX_PATH_OPEN) {
6955 reply_openerror(req, status);
6959 reply_nterror(req, status);
6964 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6970 /****************************************************************************
6971 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6972 ****************************************************************************/
6974 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6975 char **pparams, int total_params,
6976 char **ppdata, int total_data,
6977 unsigned int max_data_bytes)
6979 char *params = *pparams;
6980 char *pdata = *ppdata;
6981 char *directory = NULL;
6982 SMB_STRUCT_STAT sbuf;
6983 NTSTATUS status = NT_STATUS_OK;
6984 struct ea_list *ea_list = NULL;
6985 TALLOC_CTX *ctx = talloc_tos();
6987 if (!CAN_WRITE(conn)) {
6988 reply_doserror(req, ERRSRV, ERRaccess);
6992 if (total_params < 5) {
6993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6997 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6998 total_params - 4, STR_TERMINATE,
7000 if (!NT_STATUS_IS_OK(status)) {
7001 reply_nterror(req, status);
7005 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7007 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7008 if (!NT_STATUS_IS_OK(status)) {
7009 reply_nterror(req, status);
7013 status = check_name(conn, directory);
7014 if (!NT_STATUS_IS_OK(status)) {
7015 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7016 reply_nterror(req, status);
7020 /* Any data in this call is an EA list. */
7021 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7022 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7027 * OS/2 workplace shell seems to send SET_EA requests of "null"
7028 * length (4 bytes containing IVAL 4).
7029 * They seem to have no effect. Bug #3212. JRA.
7032 if (total_data != 4) {
7033 if (total_data < 10) {
7034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7038 if (IVAL(pdata,0) > total_data) {
7039 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7040 IVAL(pdata,0), (unsigned int)total_data));
7041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7045 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7051 } else if (IVAL(pdata,0) != 4) {
7052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7056 status = create_directory(conn, req, directory);
7058 if (!NT_STATUS_IS_OK(status)) {
7059 reply_nterror(req, status);
7063 /* Try and set any given EA. */
7065 status = set_ea(conn, NULL, directory, ea_list);
7066 if (!NT_STATUS_IS_OK(status)) {
7067 reply_nterror(req, status);
7072 /* Realloc the parameter and data sizes */
7073 *pparams = (char *)SMB_REALLOC(*pparams,2);
7074 if(*pparams == NULL) {
7075 reply_nterror(req, NT_STATUS_NO_MEMORY);
7082 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7087 /****************************************************************************
7088 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7089 We don't actually do this - we just send a null response.
7090 ****************************************************************************/
7092 static void call_trans2findnotifyfirst(connection_struct *conn,
7093 struct smb_request *req,
7094 char **pparams, int total_params,
7095 char **ppdata, int total_data,
7096 unsigned int max_data_bytes)
7098 static uint16 fnf_handle = 257;
7099 char *params = *pparams;
7102 if (total_params < 6) {
7103 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7107 info_level = SVAL(params,4);
7108 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7110 switch (info_level) {
7115 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7119 /* Realloc the parameter and data sizes */
7120 *pparams = (char *)SMB_REALLOC(*pparams,6);
7121 if (*pparams == NULL) {
7122 reply_nterror(req, NT_STATUS_NO_MEMORY);
7127 SSVAL(params,0,fnf_handle);
7128 SSVAL(params,2,0); /* No changes */
7129 SSVAL(params,4,0); /* No EA errors */
7136 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7141 /****************************************************************************
7142 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7143 changes). Currently this does nothing.
7144 ****************************************************************************/
7146 static void call_trans2findnotifynext(connection_struct *conn,
7147 struct smb_request *req,
7148 char **pparams, int total_params,
7149 char **ppdata, int total_data,
7150 unsigned int max_data_bytes)
7152 char *params = *pparams;
7154 DEBUG(3,("call_trans2findnotifynext\n"));
7156 /* Realloc the parameter and data sizes */
7157 *pparams = (char *)SMB_REALLOC(*pparams,4);
7158 if (*pparams == NULL) {
7159 reply_nterror(req, NT_STATUS_NO_MEMORY);
7164 SSVAL(params,0,0); /* No changes */
7165 SSVAL(params,2,0); /* No EA errors */
7167 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7172 /****************************************************************************
7173 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7174 ****************************************************************************/
7176 static void call_trans2getdfsreferral(connection_struct *conn,
7177 struct smb_request *req,
7178 char **pparams, int total_params,
7179 char **ppdata, int total_data,
7180 unsigned int max_data_bytes)
7182 char *params = *pparams;
7183 char *pathname = NULL;
7185 int max_referral_level;
7186 NTSTATUS status = NT_STATUS_OK;
7187 TALLOC_CTX *ctx = talloc_tos();
7189 DEBUG(10,("call_trans2getdfsreferral\n"));
7191 if (total_params < 3) {
7192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7196 max_referral_level = SVAL(params,0);
7198 if(!lp_host_msdfs()) {
7199 reply_doserror(req, ERRDOS, ERRbadfunc);
7203 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7204 total_params - 2, STR_TERMINATE);
7206 reply_nterror(req, NT_STATUS_NOT_FOUND);
7209 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7210 ppdata,&status)) < 0) {
7211 reply_nterror(req, status);
7215 SSVAL(req->inbuf, smb_flg2,
7216 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7217 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7222 #define LMCAT_SPL 0x53
7223 #define LMFUNC_GETJOBID 0x60
7225 /****************************************************************************
7226 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7227 ****************************************************************************/
7229 static void call_trans2ioctl(connection_struct *conn,
7230 struct smb_request *req,
7231 char **pparams, int total_params,
7232 char **ppdata, int total_data,
7233 unsigned int max_data_bytes)
7235 char *pdata = *ppdata;
7236 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7238 /* check for an invalid fid before proceeding */
7241 reply_doserror(req, ERRDOS, ERRbadfid);
7245 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7246 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7247 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7248 if (*ppdata == NULL) {
7249 reply_nterror(req, NT_STATUS_NO_MEMORY);
7254 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7255 CAN ACCEPT THIS IN UNICODE. JRA. */
7257 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7258 srvstr_push(pdata, req->flags2, pdata + 2,
7259 global_myname(), 15,
7260 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7261 srvstr_push(pdata, req->flags2, pdata+18,
7262 lp_servicename(SNUM(conn)), 13,
7263 STR_ASCII|STR_TERMINATE); /* Service name */
7264 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7269 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7270 reply_doserror(req, ERRSRV, ERRerror);
7273 /****************************************************************************
7274 Reply to a SMBfindclose (stop trans2 directory search).
7275 ****************************************************************************/
7277 void reply_findclose(struct smb_request *req)
7281 START_PROFILE(SMBfindclose);
7284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7285 END_PROFILE(SMBfindclose);
7289 dptr_num = SVALS(req->inbuf,smb_vwv0);
7291 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7293 dptr_close(&dptr_num);
7295 reply_outbuf(req, 0, 0);
7297 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7299 END_PROFILE(SMBfindclose);
7303 /****************************************************************************
7304 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7305 ****************************************************************************/
7307 void reply_findnclose(struct smb_request *req)
7311 START_PROFILE(SMBfindnclose);
7314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7315 END_PROFILE(SMBfindnclose);
7319 dptr_num = SVAL(req->inbuf,smb_vwv0);
7321 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7323 /* We never give out valid handles for a
7324 findnotifyfirst - so any dptr_num is ok here.
7327 reply_outbuf(req, 0, 0);
7329 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7331 END_PROFILE(SMBfindnclose);
7335 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7336 struct trans_state *state)
7338 if (Protocol >= PROTOCOL_NT1) {
7339 req->flags2 |= 0x40; /* IS_LONG_NAME */
7340 SSVAL(req->inbuf,smb_flg2,req->flags2);
7343 if (conn->encrypt_level == Required && !req->encrypted) {
7344 if (state->call != TRANSACT2_QFSINFO &&
7345 state->call != TRANSACT2_SETFSINFO) {
7346 DEBUG(0,("handle_trans2: encryption required "
7348 (unsigned int)state->call));
7349 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7354 /* Now we must call the relevant TRANS2 function */
7355 switch(state->call) {
7356 case TRANSACT2_OPEN:
7358 START_PROFILE(Trans2_open);
7359 call_trans2open(conn, req,
7360 &state->param, state->total_param,
7361 &state->data, state->total_data,
7362 state->max_data_return);
7363 END_PROFILE(Trans2_open);
7367 case TRANSACT2_FINDFIRST:
7369 START_PROFILE(Trans2_findfirst);
7370 call_trans2findfirst(conn, req,
7371 &state->param, state->total_param,
7372 &state->data, state->total_data,
7373 state->max_data_return);
7374 END_PROFILE(Trans2_findfirst);
7378 case TRANSACT2_FINDNEXT:
7380 START_PROFILE(Trans2_findnext);
7381 call_trans2findnext(conn, req,
7382 &state->param, state->total_param,
7383 &state->data, state->total_data,
7384 state->max_data_return);
7385 END_PROFILE(Trans2_findnext);
7389 case TRANSACT2_QFSINFO:
7391 START_PROFILE(Trans2_qfsinfo);
7392 call_trans2qfsinfo(conn, req,
7393 &state->param, state->total_param,
7394 &state->data, state->total_data,
7395 state->max_data_return);
7396 END_PROFILE(Trans2_qfsinfo);
7400 case TRANSACT2_SETFSINFO:
7402 START_PROFILE(Trans2_setfsinfo);
7403 call_trans2setfsinfo(conn, req,
7404 &state->param, state->total_param,
7405 &state->data, state->total_data,
7406 state->max_data_return);
7407 END_PROFILE(Trans2_setfsinfo);
7411 case TRANSACT2_QPATHINFO:
7412 case TRANSACT2_QFILEINFO:
7414 START_PROFILE(Trans2_qpathinfo);
7415 call_trans2qfilepathinfo(conn, req, state->call,
7416 &state->param, state->total_param,
7417 &state->data, state->total_data,
7418 state->max_data_return);
7419 END_PROFILE(Trans2_qpathinfo);
7423 case TRANSACT2_SETPATHINFO:
7424 case TRANSACT2_SETFILEINFO:
7426 START_PROFILE(Trans2_setpathinfo);
7427 call_trans2setfilepathinfo(conn, req, state->call,
7428 &state->param, state->total_param,
7429 &state->data, state->total_data,
7430 state->max_data_return);
7431 END_PROFILE(Trans2_setpathinfo);
7435 case TRANSACT2_FINDNOTIFYFIRST:
7437 START_PROFILE(Trans2_findnotifyfirst);
7438 call_trans2findnotifyfirst(conn, req,
7439 &state->param, state->total_param,
7440 &state->data, state->total_data,
7441 state->max_data_return);
7442 END_PROFILE(Trans2_findnotifyfirst);
7446 case TRANSACT2_FINDNOTIFYNEXT:
7448 START_PROFILE(Trans2_findnotifynext);
7449 call_trans2findnotifynext(conn, req,
7450 &state->param, state->total_param,
7451 &state->data, state->total_data,
7452 state->max_data_return);
7453 END_PROFILE(Trans2_findnotifynext);
7457 case TRANSACT2_MKDIR:
7459 START_PROFILE(Trans2_mkdir);
7460 call_trans2mkdir(conn, req,
7461 &state->param, state->total_param,
7462 &state->data, state->total_data,
7463 state->max_data_return);
7464 END_PROFILE(Trans2_mkdir);
7468 case TRANSACT2_GET_DFS_REFERRAL:
7470 START_PROFILE(Trans2_get_dfs_referral);
7471 call_trans2getdfsreferral(conn, req,
7472 &state->param, state->total_param,
7473 &state->data, state->total_data,
7474 state->max_data_return);
7475 END_PROFILE(Trans2_get_dfs_referral);
7479 case TRANSACT2_IOCTL:
7481 START_PROFILE(Trans2_ioctl);
7482 call_trans2ioctl(conn, req,
7483 &state->param, state->total_param,
7484 &state->data, state->total_data,
7485 state->max_data_return);
7486 END_PROFILE(Trans2_ioctl);
7491 /* Error in request */
7492 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7493 reply_doserror(req, ERRSRV,ERRerror);
7497 /****************************************************************************
7498 Reply to a SMBtrans2.
7499 ****************************************************************************/
7501 void reply_trans2(struct smb_request *req)
7503 connection_struct *conn = req->conn;
7508 unsigned int tran_call;
7510 unsigned int av_size;
7511 struct trans_state *state;
7514 START_PROFILE(SMBtrans2);
7516 if (req->wct < 14) {
7517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7518 END_PROFILE(SMBtrans2);
7522 dsoff = SVAL(req->inbuf, smb_dsoff);
7523 dscnt = SVAL(req->inbuf, smb_dscnt);
7524 psoff = SVAL(req->inbuf, smb_psoff);
7525 pscnt = SVAL(req->inbuf, smb_pscnt);
7526 tran_call = SVAL(req->inbuf, smb_setup0);
7527 size = smb_len(req->inbuf) + 4;
7528 av_size = smb_len(req->inbuf);
7530 result = allow_new_trans(conn->pending_trans, req->mid);
7531 if (!NT_STATUS_IS_OK(result)) {
7532 DEBUG(2, ("Got invalid trans2 request: %s\n",
7533 nt_errstr(result)));
7534 reply_nterror(req, result);
7535 END_PROFILE(SMBtrans2);
7540 switch (tran_call) {
7541 /* List the allowed trans2 calls on IPC$ */
7542 case TRANSACT2_OPEN:
7543 case TRANSACT2_GET_DFS_REFERRAL:
7544 case TRANSACT2_QFILEINFO:
7545 case TRANSACT2_QFSINFO:
7546 case TRANSACT2_SETFSINFO:
7549 reply_doserror(req, ERRSRV, ERRaccess);
7550 END_PROFILE(SMBtrans2);
7555 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7556 DEBUG(0, ("talloc failed\n"));
7557 reply_nterror(req, NT_STATUS_NO_MEMORY);
7558 END_PROFILE(SMBtrans2);
7562 state->cmd = SMBtrans2;
7564 state->mid = req->mid;
7565 state->vuid = req->vuid;
7566 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7567 state->setup = NULL;
7568 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7569 state->param = NULL;
7570 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7572 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7573 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7574 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7575 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7576 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7578 state->call = tran_call;
7580 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7581 is so as a sanity check */
7582 if (state->setup_count != 1) {
7584 * Need to have rc=0 for ioctl to get job id for OS/2.
7585 * Network printing will fail if function is not successful.
7586 * Similar function in reply.c will be used if protocol
7587 * is LANMAN1.0 instead of LM1.2X002.
7588 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7589 * outbuf doesn't have to be set(only job id is used).
7591 if ( (state->setup_count == 4)
7592 && (tran_call == TRANSACT2_IOCTL)
7593 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7594 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7595 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7597 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7598 DEBUG(2,("Transaction is %d\n",tran_call));
7600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7601 END_PROFILE(SMBtrans2);
7606 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7609 if (state->total_data) {
7610 /* Can't use talloc here, the core routines do realloc on the
7611 * params and data. */
7612 state->data = (char *)SMB_MALLOC(state->total_data);
7613 if (state->data == NULL) {
7614 DEBUG(0,("reply_trans2: data malloc fail for %u "
7615 "bytes !\n", (unsigned int)state->total_data));
7617 reply_nterror(req, NT_STATUS_NO_MEMORY);
7618 END_PROFILE(SMBtrans2);
7622 if (dscnt > state->total_data ||
7623 dsoff+dscnt < dsoff) {
7627 if (dsoff > av_size ||
7629 dsoff+dscnt > av_size) {
7633 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7636 if (state->total_param) {
7637 /* Can't use talloc here, the core routines do realloc on the
7638 * params and data. */
7639 state->param = (char *)SMB_MALLOC(state->total_param);
7640 if (state->param == NULL) {
7641 DEBUG(0,("reply_trans: param malloc fail for %u "
7642 "bytes !\n", (unsigned int)state->total_param));
7643 SAFE_FREE(state->data);
7645 reply_nterror(req, NT_STATUS_NO_MEMORY);
7646 END_PROFILE(SMBtrans2);
7650 if (pscnt > state->total_param ||
7651 psoff+pscnt < psoff) {
7655 if (psoff > av_size ||
7657 psoff+pscnt > av_size) {
7661 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7664 state->received_data = dscnt;
7665 state->received_param = pscnt;
7667 if ((state->received_param == state->total_param) &&
7668 (state->received_data == state->total_data)) {
7670 handle_trans2(conn, req, state);
7672 SAFE_FREE(state->data);
7673 SAFE_FREE(state->param);
7675 END_PROFILE(SMBtrans2);
7679 DLIST_ADD(conn->pending_trans, state);
7681 /* We need to send an interim response then receive the rest
7682 of the parameter/data bytes */
7683 reply_outbuf(req, 0, 0);
7684 show_msg((char *)req->outbuf);
7685 END_PROFILE(SMBtrans2);
7690 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7691 SAFE_FREE(state->data);
7692 SAFE_FREE(state->param);
7694 END_PROFILE(SMBtrans2);
7695 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7699 /****************************************************************************
7700 Reply to a SMBtranss2
7701 ****************************************************************************/
7703 void reply_transs2(struct smb_request *req)
7705 connection_struct *conn = req->conn;
7706 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7707 struct trans_state *state;
7709 unsigned int av_size;
7711 START_PROFILE(SMBtranss2);
7713 show_msg((char *)req->inbuf);
7716 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7717 END_PROFILE(SMBtranss2);
7721 size = smb_len(req->inbuf)+4;
7722 av_size = smb_len(req->inbuf);
7724 for (state = conn->pending_trans; state != NULL;
7725 state = state->next) {
7726 if (state->mid == req->mid) {
7731 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7733 END_PROFILE(SMBtranss2);
7737 /* Revise state->total_param and state->total_data in case they have
7738 changed downwards */
7740 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7741 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7742 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7743 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7745 pcnt = SVAL(req->inbuf, smb_spscnt);
7746 poff = SVAL(req->inbuf, smb_spsoff);
7747 pdisp = SVAL(req->inbuf, smb_spsdisp);
7749 dcnt = SVAL(req->inbuf, smb_sdscnt);
7750 doff = SVAL(req->inbuf, smb_sdsoff);
7751 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7753 state->received_param += pcnt;
7754 state->received_data += dcnt;
7756 if ((state->received_data > state->total_data) ||
7757 (state->received_param > state->total_param))
7761 if (pdisp > state->total_param ||
7762 pcnt > state->total_param ||
7763 pdisp+pcnt > state->total_param ||
7764 pdisp+pcnt < pdisp) {
7768 if (poff > av_size ||
7770 poff+pcnt > av_size ||
7775 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7780 if (ddisp > state->total_data ||
7781 dcnt > state->total_data ||
7782 ddisp+dcnt > state->total_data ||
7783 ddisp+dcnt < ddisp) {
7787 if (ddisp > av_size ||
7789 ddisp+dcnt > av_size ||
7790 ddisp+dcnt < ddisp) {
7794 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7798 if ((state->received_param < state->total_param) ||
7799 (state->received_data < state->total_data)) {
7800 END_PROFILE(SMBtranss2);
7805 * construct_reply_common will copy smb_com from inbuf to
7806 * outbuf. SMBtranss2 is wrong here.
7808 SCVAL(req->inbuf,smb_com,SMBtrans2);
7810 handle_trans2(conn, req, state);
7812 DLIST_REMOVE(conn->pending_trans, state);
7813 SAFE_FREE(state->data);
7814 SAFE_FREE(state->param);
7817 END_PROFILE(SMBtranss2);
7822 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7823 DLIST_REMOVE(conn->pending_trans, state);
7824 SAFE_FREE(state->data);
7825 SAFE_FREE(state->param);
7827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7828 END_PROFILE(SMBtranss2);