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;
1888 const char *mask = 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 if (!lp_unix_extensions()) {
1942 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1947 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1951 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1952 params+12, total_params - 12,
1953 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1954 if (!NT_STATUS_IS_OK(ntstatus)) {
1955 reply_nterror(req, ntstatus);
1959 ntstatus = resolve_dfspath_wcard(ctx, conn,
1960 req->flags2 & FLAGS2_DFS_PATHNAMES,
1963 &mask_contains_wcard);
1964 if (!NT_STATUS_IS_OK(ntstatus)) {
1965 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1966 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1967 ERRSRV, ERRbadpath);
1970 reply_nterror(req, ntstatus);
1974 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1975 if (!NT_STATUS_IS_OK(ntstatus)) {
1976 reply_nterror(req, ntstatus);
1980 ntstatus = check_name(conn, directory);
1981 if (!NT_STATUS_IS_OK(ntstatus)) {
1982 reply_nterror(req, ntstatus);
1986 p = strrchr_m(directory,'/');
1988 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1989 if((directory[0] == '.') && (directory[1] == '\0')) {
1991 mask_contains_wcard = True;
1995 directory = talloc_strdup(talloc_tos(), "./");
1997 reply_nterror(req, NT_STATUS_NO_MEMORY);
2005 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2007 if (info_level == SMB_FIND_EA_LIST) {
2010 if (total_data < 4) {
2011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2015 ea_size = IVAL(pdata,0);
2016 if (ea_size != total_data) {
2017 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2018 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2023 if (!lp_ea_support(SNUM(conn))) {
2024 reply_doserror(req, ERRDOS, ERReasnotsupported);
2028 /* Pull out the list of names. */
2029 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2036 *ppdata = (char *)SMB_REALLOC(
2037 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2038 if(*ppdata == NULL ) {
2039 reply_nterror(req, NT_STATUS_NO_MEMORY);
2043 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2045 /* Realloc the params space */
2046 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2047 if (*pparams == NULL) {
2048 reply_nterror(req, NT_STATUS_NO_MEMORY);
2053 /* Save the wildcard match and attribs we are using on this directory -
2054 needed as lanman2 assumes these are being saved between calls */
2056 ntstatus = dptr_create(conn,
2062 mask_contains_wcard,
2066 if (!NT_STATUS_IS_OK(ntstatus)) {
2067 reply_nterror(req, ntstatus);
2071 dptr_num = dptr_dnum(conn->dirptr);
2072 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2074 /* We don't need to check for VOL here as this is returned by
2075 a different TRANS2 call. */
2077 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2078 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2079 dont_descend = True;
2082 space_remaining = max_data_bytes;
2083 out_of_space = False;
2085 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2086 bool got_exact_match = False;
2088 /* this is a heuristic to avoid seeking the dirptr except when
2089 absolutely necessary. It allows for a filename of about 40 chars */
2090 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2091 out_of_space = True;
2094 finished = !get_lanman2_dir_entry(ctx,
2097 mask,dirtype,info_level,
2098 requires_resume_key,dont_descend,
2101 space_remaining, &out_of_space,
2103 &last_entry_off, ea_list);
2106 if (finished && out_of_space)
2109 if (!finished && !out_of_space)
2113 * As an optimisation if we know we aren't looking
2114 * for a wildcard name (ie. the name matches the wildcard exactly)
2115 * then we can finish on any (first) match.
2116 * This speeds up large directory searches. JRA.
2122 /* Ensure space_remaining never goes -ve. */
2123 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2124 space_remaining = 0;
2125 out_of_space = true;
2127 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2131 /* Check if we can close the dirptr */
2132 if(close_after_first || (finished && close_if_end)) {
2133 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2134 dptr_close(&dptr_num);
2138 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2139 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2140 * the protocol level is less than NT1. Tested with smbclient. JRA.
2141 * This should fix the OS/2 client bug #2335.
2144 if(numentries == 0) {
2145 dptr_close(&dptr_num);
2146 if (Protocol < PROTOCOL_NT1) {
2147 reply_doserror(req, ERRDOS, ERRnofiles);
2150 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2151 ERRDOS, ERRbadfile);
2156 /* At this point pdata points to numentries directory entries. */
2158 /* Set up the return parameter block */
2159 SSVAL(params,0,dptr_num);
2160 SSVAL(params,2,numentries);
2161 SSVAL(params,4,finished);
2162 SSVAL(params,6,0); /* Never an EA error */
2163 SSVAL(params,8,last_entry_off);
2165 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2168 if ((! *directory) && dptr_path(dptr_num)) {
2169 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2171 reply_nterror(req, NT_STATUS_NO_MEMORY);
2175 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2176 smb_fn_name(CVAL(req->inbuf,smb_com)),
2177 mask, directory, dirtype, numentries ) );
2180 * Force a name mangle here to ensure that the
2181 * mask as an 8.3 name is top of the mangled cache.
2182 * The reasons for this are subtle. Don't remove
2183 * this code unless you know what you are doing
2184 * (see PR#13758). JRA.
2187 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2188 char mangled_name[13];
2189 name_to_8_3(mask, mangled_name, True, conn->params);
2195 /****************************************************************************
2196 Reply to a TRANS2_FINDNEXT.
2197 ****************************************************************************/
2199 static void call_trans2findnext(connection_struct *conn,
2200 struct smb_request *req,
2201 char **pparams, int total_params,
2202 char **ppdata, int total_data,
2203 unsigned int max_data_bytes)
2205 /* We must be careful here that we don't return more than the
2206 allowed number of data bytes. If this means returning fewer than
2207 maxentries then so be it. We assume that the redirector has
2208 enough room for the fixed number of parameter bytes it has
2210 char *params = *pparams;
2211 char *pdata = *ppdata;
2217 uint16 findnext_flags;
2218 bool close_after_request;
2220 bool requires_resume_key;
2222 bool mask_contains_wcard = False;
2223 char *resume_name = NULL;
2224 const char *mask = NULL;
2225 const char *directory = NULL;
2229 int i, last_entry_off=0;
2230 bool finished = False;
2231 bool dont_descend = False;
2232 bool out_of_space = False;
2233 int space_remaining;
2234 struct ea_list *ea_list = NULL;
2235 NTSTATUS ntstatus = NT_STATUS_OK;
2236 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2237 TALLOC_CTX *ctx = talloc_tos();
2239 if (total_params < 13) {
2240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2244 dptr_num = SVAL(params,0);
2245 maxentries = SVAL(params,2);
2246 info_level = SVAL(params,4);
2247 resume_key = IVAL(params,6);
2248 findnext_flags = SVAL(params,10);
2249 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2250 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2251 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2252 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2254 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2256 total_params - 12, STR_TERMINATE, &ntstatus,
2257 &mask_contains_wcard);
2258 if (!NT_STATUS_IS_OK(ntstatus)) {
2259 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2260 complain (it thinks we're asking for the directory above the shared
2261 path or an invalid name). Catch this as the resume name is only compared, never used in
2262 a file access. JRA. */
2263 srvstr_pull_talloc(ctx, params, req->flags2,
2264 &resume_name, params+12,
2268 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2269 reply_nterror(req, ntstatus);
2274 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2275 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2276 resume_key = %d resume name = %s continue=%d level = %d\n",
2277 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2278 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2281 /* W2K3 seems to treat zero as 1. */
2285 switch (info_level) {
2286 case SMB_FIND_INFO_STANDARD:
2287 case SMB_FIND_EA_SIZE:
2288 case SMB_FIND_EA_LIST:
2289 case SMB_FIND_FILE_DIRECTORY_INFO:
2290 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2291 case SMB_FIND_FILE_NAMES_INFO:
2292 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2293 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2294 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2296 case SMB_FIND_FILE_UNIX:
2297 case SMB_FIND_FILE_UNIX_INFO2:
2298 if (!lp_unix_extensions()) {
2299 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2304 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2308 if (info_level == SMB_FIND_EA_LIST) {
2311 if (total_data < 4) {
2312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2316 ea_size = IVAL(pdata,0);
2317 if (ea_size != total_data) {
2318 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2319 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2324 if (!lp_ea_support(SNUM(conn))) {
2325 reply_doserror(req, ERRDOS, ERReasnotsupported);
2329 /* Pull out the list of names. */
2330 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2337 *ppdata = (char *)SMB_REALLOC(
2338 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2339 if(*ppdata == NULL) {
2340 reply_nterror(req, NT_STATUS_NO_MEMORY);
2345 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2347 /* Realloc the params space */
2348 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2349 if(*pparams == NULL ) {
2350 reply_nterror(req, NT_STATUS_NO_MEMORY);
2356 /* Check that the dptr is valid */
2357 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2358 reply_doserror(req, ERRDOS, ERRnofiles);
2362 string_set(&conn->dirpath,dptr_path(dptr_num));
2364 /* Get the wildcard mask from the dptr */
2365 if((p = dptr_wcard(dptr_num))== NULL) {
2366 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2367 reply_doserror(req, ERRDOS, ERRnofiles);
2372 directory = conn->dirpath;
2374 /* Get the attr mask from the dptr */
2375 dirtype = dptr_attr(dptr_num);
2377 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2378 dptr_num, mask, dirtype,
2380 dptr_TellDir(conn->dirptr)));
2382 /* We don't need to check for VOL here as this is returned by
2383 a different TRANS2 call. */
2385 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2386 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2387 dont_descend = True;
2390 space_remaining = max_data_bytes;
2391 out_of_space = False;
2394 * Seek to the correct position. We no longer use the resume key but
2395 * depend on the last file name instead.
2398 if(*resume_name && !continue_bit) {
2401 long current_pos = 0;
2403 * Remember, name_to_8_3 is called by
2404 * get_lanman2_dir_entry(), so the resume name
2405 * could be mangled. Ensure we check the unmangled name.
2408 if (mangle_is_mangled(resume_name, conn->params)) {
2409 char *new_resume_name = NULL;
2410 mangle_lookup_name_from_8_3(ctx,
2414 if (new_resume_name) {
2415 resume_name = new_resume_name;
2420 * Fix for NT redirector problem triggered by resume key indexes
2421 * changing between directory scans. We now return a resume key of 0
2422 * and instead look for the filename to continue from (also given
2423 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2424 * findfirst/findnext (as is usual) then the directory pointer
2425 * should already be at the correct place.
2428 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2429 } /* end if resume_name && !continue_bit */
2431 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2432 bool got_exact_match = False;
2434 /* this is a heuristic to avoid seeking the dirptr except when
2435 absolutely necessary. It allows for a filename of about 40 chars */
2436 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2437 out_of_space = True;
2440 finished = !get_lanman2_dir_entry(ctx,
2443 mask,dirtype,info_level,
2444 requires_resume_key,dont_descend,
2447 space_remaining, &out_of_space,
2449 &last_entry_off, ea_list);
2452 if (finished && out_of_space)
2455 if (!finished && !out_of_space)
2459 * As an optimisation if we know we aren't looking
2460 * for a wildcard name (ie. the name matches the wildcard exactly)
2461 * then we can finish on any (first) match.
2462 * This speeds up large directory searches. JRA.
2468 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2471 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2472 smb_fn_name(CVAL(req->inbuf,smb_com)),
2473 mask, directory, dirtype, numentries ) );
2475 /* Check if we can close the dirptr */
2476 if(close_after_request || (finished && close_if_end)) {
2477 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2478 dptr_close(&dptr_num); /* This frees up the saved mask */
2481 /* Set up the return parameter block */
2482 SSVAL(params,0,numentries);
2483 SSVAL(params,2,finished);
2484 SSVAL(params,4,0); /* Never an EA error */
2485 SSVAL(params,6,last_entry_off);
2487 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2493 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2495 E_md4hash(lp_servicename(SNUM(conn)),objid);
2499 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2501 SMB_ASSERT(extended_info != NULL);
2503 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2504 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2505 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2506 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2507 #ifdef SAMBA_VERSION_REVISION
2508 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2510 extended_info->samba_subversion = 0;
2511 #ifdef SAMBA_VERSION_RC_RELEASE
2512 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2514 #ifdef SAMBA_VERSION_PRE_RELEASE
2515 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2518 #ifdef SAMBA_VERSION_VENDOR_PATCH
2519 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2521 extended_info->samba_gitcommitdate = 0;
2522 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2523 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2526 memset(extended_info->samba_version_string, 0,
2527 sizeof(extended_info->samba_version_string));
2529 snprintf (extended_info->samba_version_string,
2530 sizeof(extended_info->samba_version_string),
2531 "%s", samba_version_string());
2534 /****************************************************************************
2535 Reply to a TRANS2_QFSINFO (query filesystem info).
2536 ****************************************************************************/
2538 static void call_trans2qfsinfo(connection_struct *conn,
2539 struct smb_request *req,
2540 char **pparams, int total_params,
2541 char **ppdata, int total_data,
2542 unsigned int max_data_bytes)
2544 char *pdata, *end_data;
2545 char *params = *pparams;
2549 const char *vname = volume_label(SNUM(conn));
2550 int snum = SNUM(conn);
2551 char *fstype = lp_fstype(SNUM(conn));
2552 uint32 additional_flags = 0;
2554 if (total_params < 2) {
2555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2559 info_level = SVAL(params,0);
2562 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2563 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2564 "info level (0x%x) on IPC$.\n",
2565 (unsigned int)info_level));
2566 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2571 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2572 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2573 DEBUG(0,("call_trans2qfsinfo: encryption required "
2574 "and info level 0x%x sent.\n",
2575 (unsigned int)info_level));
2576 exit_server_cleanly("encryption required "
2582 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2584 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2585 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2586 reply_doserror(req, ERRSRV, ERRinvdevice);
2590 *ppdata = (char *)SMB_REALLOC(
2591 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2592 if (*ppdata == NULL ) {
2593 reply_nterror(req, NT_STATUS_NO_MEMORY);
2598 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2599 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2601 switch (info_level) {
2602 case SMB_INFO_ALLOCATION:
2604 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2606 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2607 reply_unixerror(req, ERRHRD, ERRgeneral);
2611 block_size = lp_block_size(snum);
2612 if (bsize < block_size) {
2613 SMB_BIG_UINT factor = block_size/bsize;
2618 if (bsize > block_size) {
2619 SMB_BIG_UINT factor = bsize/block_size;
2624 bytes_per_sector = 512;
2625 sectors_per_unit = bsize/bytes_per_sector;
2627 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2628 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2629 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2631 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2632 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2633 SIVAL(pdata,l1_cUnit,dsize);
2634 SIVAL(pdata,l1_cUnitAvail,dfree);
2635 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2639 case SMB_INFO_VOLUME:
2640 /* Return volume name */
2642 * Add volume serial number - hash of a combination of
2643 * the called hostname and the service name.
2645 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2647 * Win2k3 and previous mess this up by sending a name length
2648 * one byte short. I believe only older clients (OS/2 Win9x) use
2649 * this call so try fixing this by adding a terminating null to
2650 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2654 pdata+l2_vol_szVolLabel, vname,
2655 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2656 STR_NOALIGN|STR_TERMINATE);
2657 SCVAL(pdata,l2_vol_cch,len);
2658 data_len = l2_vol_szVolLabel + len;
2659 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2660 (unsigned)st.st_ctime, len, vname));
2663 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2664 case SMB_FS_ATTRIBUTE_INFORMATION:
2666 additional_flags = 0;
2667 #if defined(HAVE_SYS_QUOTAS)
2668 additional_flags |= FILE_VOLUME_QUOTAS;
2671 if(lp_nt_acl_support(SNUM(conn))) {
2672 additional_flags |= FILE_PERSISTENT_ACLS;
2675 /* Capabilities are filled in at connection time through STATVFS call */
2676 additional_flags |= conn->fs_capabilities;
2678 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2679 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2680 additional_flags); /* FS ATTRIBUTES */
2682 SIVAL(pdata,4,255); /* Max filename component length */
2683 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2684 and will think we can't do long filenames */
2685 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2686 PTR_DIFF(end_data, pdata+12),
2689 data_len = 12 + len;
2692 case SMB_QUERY_FS_LABEL_INFO:
2693 case SMB_FS_LABEL_INFORMATION:
2694 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2695 PTR_DIFF(end_data, pdata+4), 0);
2700 case SMB_QUERY_FS_VOLUME_INFO:
2701 case SMB_FS_VOLUME_INFORMATION:
2704 * Add volume serial number - hash of a combination of
2705 * the called hostname and the service name.
2707 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2708 (str_checksum(get_local_machine_name())<<16));
2710 /* Max label len is 32 characters. */
2711 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2712 PTR_DIFF(end_data, pdata+18),
2714 SIVAL(pdata,12,len);
2717 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2718 (int)strlen(vname),vname, lp_servicename(snum)));
2721 case SMB_QUERY_FS_SIZE_INFO:
2722 case SMB_FS_SIZE_INFORMATION:
2724 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2726 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2727 reply_unixerror(req, ERRHRD, ERRgeneral);
2730 block_size = lp_block_size(snum);
2731 if (bsize < block_size) {
2732 SMB_BIG_UINT factor = block_size/bsize;
2737 if (bsize > block_size) {
2738 SMB_BIG_UINT factor = bsize/block_size;
2743 bytes_per_sector = 512;
2744 sectors_per_unit = bsize/bytes_per_sector;
2745 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2746 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2747 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2748 SBIG_UINT(pdata,0,dsize);
2749 SBIG_UINT(pdata,8,dfree);
2750 SIVAL(pdata,16,sectors_per_unit);
2751 SIVAL(pdata,20,bytes_per_sector);
2755 case SMB_FS_FULL_SIZE_INFORMATION:
2757 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2759 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2760 reply_unixerror(req, ERRHRD, ERRgeneral);
2763 block_size = lp_block_size(snum);
2764 if (bsize < block_size) {
2765 SMB_BIG_UINT factor = block_size/bsize;
2770 if (bsize > block_size) {
2771 SMB_BIG_UINT factor = bsize/block_size;
2776 bytes_per_sector = 512;
2777 sectors_per_unit = bsize/bytes_per_sector;
2778 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2779 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2780 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2781 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2782 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2783 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2784 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2785 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2789 case SMB_QUERY_FS_DEVICE_INFO:
2790 case SMB_FS_DEVICE_INFORMATION:
2792 SIVAL(pdata,0,0); /* dev type */
2793 SIVAL(pdata,4,0); /* characteristics */
2796 #ifdef HAVE_SYS_QUOTAS
2797 case SMB_FS_QUOTA_INFORMATION:
2799 * what we have to send --metze:
2801 * Unknown1: 24 NULL bytes
2802 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2803 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2804 * Quota Flags: 2 byte :
2805 * Unknown3: 6 NULL bytes
2809 * details for Quota Flags:
2811 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2812 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2813 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2814 * 0x0001 Enable Quotas: enable quota for this fs
2818 /* we need to fake up a fsp here,
2819 * because its not send in this call
2822 SMB_NTQUOTA_STRUCT quotas;
2825 ZERO_STRUCT(quotas);
2831 if (current_user.ut.uid != 0) {
2832 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2833 lp_servicename(SNUM(conn)),conn->user));
2834 reply_doserror(req, ERRDOS, ERRnoaccess);
2838 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2839 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2840 reply_doserror(req, ERRSRV, ERRerror);
2846 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2848 /* Unknown1 24 NULL bytes*/
2849 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2850 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2851 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2853 /* Default Soft Quota 8 bytes */
2854 SBIG_UINT(pdata,24,quotas.softlim);
2856 /* Default Hard Quota 8 bytes */
2857 SBIG_UINT(pdata,32,quotas.hardlim);
2859 /* Quota flag 2 bytes */
2860 SSVAL(pdata,40,quotas.qflags);
2862 /* Unknown3 6 NULL bytes */
2868 #endif /* HAVE_SYS_QUOTAS */
2869 case SMB_FS_OBJECTID_INFORMATION:
2871 unsigned char objid[16];
2872 struct smb_extended_info extended_info;
2873 memcpy(pdata,create_volume_objectid(conn, objid),16);
2874 samba_extended_info_version (&extended_info);
2875 SIVAL(pdata,16,extended_info.samba_magic);
2876 SIVAL(pdata,20,extended_info.samba_version);
2877 SIVAL(pdata,24,extended_info.samba_subversion);
2878 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2879 memcpy(pdata+36,extended_info.samba_version_string,28);
2885 * Query the version and capabilities of the CIFS UNIX extensions
2889 case SMB_QUERY_CIFS_UNIX_INFO:
2891 bool large_write = lp_min_receive_file_size() &&
2892 !srv_is_signing_active();
2893 bool large_read = !srv_is_signing_active();
2894 int encrypt_caps = 0;
2896 if (!lp_unix_extensions()) {
2897 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2901 switch (conn->encrypt_level) {
2907 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2910 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2911 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2912 large_write = false;
2918 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2919 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2921 /* We have POSIX ACLs, pathname, encryption,
2922 * large read/write, and locking capability. */
2924 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2925 CIFS_UNIX_POSIX_ACLS_CAP|
2926 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2927 CIFS_UNIX_FCNTL_LOCKS_CAP|
2928 CIFS_UNIX_EXTATTR_CAP|
2929 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2931 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2933 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2937 case SMB_QUERY_POSIX_FS_INFO:
2940 vfs_statvfs_struct svfs;
2942 if (!lp_unix_extensions()) {
2943 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2947 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2951 SIVAL(pdata,0,svfs.OptimalTransferSize);
2952 SIVAL(pdata,4,svfs.BlockSize);
2953 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2954 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2955 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2956 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2957 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2958 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2959 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2961 } else if (rc == EOPNOTSUPP) {
2962 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2964 #endif /* EOPNOTSUPP */
2966 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2967 reply_doserror(req, ERRSRV, ERRerror);
2973 case SMB_QUERY_POSIX_WHOAMI:
2979 if (!lp_unix_extensions()) {
2980 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2984 if (max_data_bytes < 40) {
2985 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2989 /* We ARE guest if global_sid_Builtin_Guests is
2990 * in our list of SIDs.
2992 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2993 current_user.nt_user_token)) {
2994 flags |= SMB_WHOAMI_GUEST;
2997 /* We are NOT guest if global_sid_Authenticated_Users
2998 * is in our list of SIDs.
3000 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3001 current_user.nt_user_token)) {
3002 flags &= ~SMB_WHOAMI_GUEST;
3005 /* NOTE: 8 bytes for UID/GID, irrespective of native
3006 * platform size. This matches
3007 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3009 data_len = 4 /* flags */
3016 + 4 /* pad/reserved */
3017 + (current_user.ut.ngroups * 8)
3019 + (current_user.nt_user_token->num_sids *
3023 SIVAL(pdata, 0, flags);
3024 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3025 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
3026 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
3029 if (data_len >= max_data_bytes) {
3030 /* Potential overflow, skip the GIDs and SIDs. */
3032 SIVAL(pdata, 24, 0); /* num_groups */
3033 SIVAL(pdata, 28, 0); /* num_sids */
3034 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3035 SIVAL(pdata, 36, 0); /* reserved */
3041 SIVAL(pdata, 24, current_user.ut.ngroups);
3043 current_user.nt_user_token->num_sids);
3045 /* We walk the SID list twice, but this call is fairly
3046 * infrequent, and I don't expect that it's performance
3047 * sensitive -- jpeach
3049 for (i = 0, sid_bytes = 0;
3050 i < current_user.nt_user_token->num_sids; ++i) {
3051 sid_bytes += ndr_size_dom_sid(
3052 ¤t_user.nt_user_token->user_sids[i], 0);
3055 /* SID list byte count */
3056 SIVAL(pdata, 32, sid_bytes);
3058 /* 4 bytes pad/reserved - must be zero */
3059 SIVAL(pdata, 36, 0);
3063 for (i = 0; i < current_user.ut.ngroups; ++i) {
3064 SBIG_UINT(pdata, data_len,
3065 (SMB_BIG_UINT)current_user.ut.groups[i]);
3071 i < current_user.nt_user_token->num_sids; ++i) {
3072 int sid_len = ndr_size_dom_sid(
3073 ¤t_user.nt_user_token->user_sids[i], 0);
3075 sid_linearize(pdata + data_len, sid_len,
3076 ¤t_user.nt_user_token->user_sids[i]);
3077 data_len += sid_len;
3083 case SMB_MAC_QUERY_FS_INFO:
3085 * Thursby MAC extension... ONLY on NTFS filesystems
3086 * once we do streams then we don't need this
3088 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3090 SIVAL(pdata,84,0x100); /* Don't support mac... */
3095 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3100 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3103 DEBUG( 4, ( "%s info_level = %d\n",
3104 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3109 /****************************************************************************
3110 Reply to a TRANS2_SETFSINFO (set filesystem info).
3111 ****************************************************************************/
3113 static void call_trans2setfsinfo(connection_struct *conn,
3114 struct smb_request *req,
3115 char **pparams, int total_params,
3116 char **ppdata, int total_data,
3117 unsigned int max_data_bytes)
3119 char *pdata = *ppdata;
3120 char *params = *pparams;
3123 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3126 if (total_params < 4) {
3127 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3133 info_level = SVAL(params,2);
3136 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3137 info_level != SMB_SET_CIFS_UNIX_INFO) {
3138 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3139 "info level (0x%x) on IPC$.\n",
3140 (unsigned int)info_level));
3141 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3146 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3147 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3148 DEBUG(0,("call_trans2setfsinfo: encryption required "
3149 "and info level 0x%x sent.\n",
3150 (unsigned int)info_level));
3151 exit_server_cleanly("encryption required "
3157 switch(info_level) {
3158 case SMB_SET_CIFS_UNIX_INFO:
3160 uint16 client_unix_major;
3161 uint16 client_unix_minor;
3162 uint32 client_unix_cap_low;
3163 uint32 client_unix_cap_high;
3165 if (!lp_unix_extensions()) {
3167 NT_STATUS_INVALID_LEVEL);
3171 /* There should be 12 bytes of capabilities set. */
3172 if (total_data < 8) {
3175 NT_STATUS_INVALID_PARAMETER);
3178 client_unix_major = SVAL(pdata,0);
3179 client_unix_minor = SVAL(pdata,2);
3180 client_unix_cap_low = IVAL(pdata,4);
3181 client_unix_cap_high = IVAL(pdata,8);
3182 /* Just print these values for now. */
3183 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3184 cap_low = 0x%x, cap_high = 0x%x\n",
3185 (unsigned int)client_unix_major,
3186 (unsigned int)client_unix_minor,
3187 (unsigned int)client_unix_cap_low,
3188 (unsigned int)client_unix_cap_high ));
3190 /* Here is where we must switch to posix pathname processing... */
3191 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3192 lp_set_posix_pathnames();
3193 mangle_change_to_posix();
3196 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3197 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3198 /* Client that knows how to do posix locks,
3199 * but not posix open/mkdir operations. Set a
3200 * default type for read/write checks. */
3202 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3208 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3211 size_t param_len = 0;
3212 size_t data_len = total_data;
3214 if (!lp_unix_extensions()) {
3217 NT_STATUS_INVALID_LEVEL);
3221 if (lp_smb_encrypt(SNUM(conn)) == false) {
3224 NT_STATUS_NOT_SUPPORTED);
3228 DEBUG( 4,("call_trans2setfsinfo: "
3229 "request transport encryption.\n"));
3231 status = srv_request_encryption_setup(conn,
3232 (unsigned char **)ppdata,
3234 (unsigned char **)pparams,
3237 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3238 !NT_STATUS_IS_OK(status)) {
3239 reply_nterror(req, status);
3243 send_trans2_replies(conn, req,
3250 if (NT_STATUS_IS_OK(status)) {
3251 /* Server-side transport
3252 * encryption is now *on*. */
3253 status = srv_encryption_start(conn);
3254 if (!NT_STATUS_IS_OK(status)) {
3255 exit_server_cleanly(
3256 "Failure in setting "
3257 "up encrypted transport");
3263 case SMB_FS_QUOTA_INFORMATION:
3265 files_struct *fsp = NULL;
3266 SMB_NTQUOTA_STRUCT quotas;
3268 ZERO_STRUCT(quotas);
3271 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3272 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3273 lp_servicename(SNUM(conn)),conn->user));
3274 reply_doserror(req, ERRSRV, ERRaccess);
3278 /* note: normaly there're 48 bytes,
3279 * but we didn't use the last 6 bytes for now
3282 fsp = file_fsp(SVAL(params,0));
3283 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3284 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3286 req, NT_STATUS_INVALID_HANDLE);
3290 if (total_data < 42) {
3291 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3295 NT_STATUS_INVALID_PARAMETER);
3299 /* unknown_1 24 NULL bytes in pdata*/
3301 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3302 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3303 #ifdef LARGE_SMB_OFF_T
3304 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3305 #else /* LARGE_SMB_OFF_T */
3306 if ((IVAL(pdata,28) != 0)&&
3307 ((quotas.softlim != 0xFFFFFFFF)||
3308 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3309 /* more than 32 bits? */
3312 NT_STATUS_INVALID_PARAMETER);
3315 #endif /* LARGE_SMB_OFF_T */
3317 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3318 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3319 #ifdef LARGE_SMB_OFF_T
3320 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3321 #else /* LARGE_SMB_OFF_T */
3322 if ((IVAL(pdata,36) != 0)&&
3323 ((quotas.hardlim != 0xFFFFFFFF)||
3324 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3325 /* more than 32 bits? */
3328 NT_STATUS_INVALID_PARAMETER);
3331 #endif /* LARGE_SMB_OFF_T */
3333 /* quota_flags 2 bytes **/
3334 quotas.qflags = SVAL(pdata,40);
3336 /* unknown_2 6 NULL bytes follow*/
3338 /* now set the quotas */
3339 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3340 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3341 reply_doserror(req, ERRSRV, ERRerror);
3348 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3350 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3356 * sending this reply works fine,
3357 * but I'm not sure it's the same
3358 * like windows do...
3361 reply_outbuf(req, 10, 0);
3364 #if defined(HAVE_POSIX_ACLS)
3365 /****************************************************************************
3366 Utility function to count the number of entries in a POSIX acl.
3367 ****************************************************************************/
3369 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3371 unsigned int ace_count = 0;
3372 int entry_id = SMB_ACL_FIRST_ENTRY;
3373 SMB_ACL_ENTRY_T entry;
3375 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3377 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3378 entry_id = SMB_ACL_NEXT_ENTRY;
3385 /****************************************************************************
3386 Utility function to marshall a POSIX acl into wire format.
3387 ****************************************************************************/
3389 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3391 int entry_id = SMB_ACL_FIRST_ENTRY;
3392 SMB_ACL_ENTRY_T entry;
3394 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3395 SMB_ACL_TAG_T tagtype;
3396 SMB_ACL_PERMSET_T permset;
3397 unsigned char perms = 0;
3398 unsigned int own_grp;
3401 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3402 entry_id = SMB_ACL_NEXT_ENTRY;
3405 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3406 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3410 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3411 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3415 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3416 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3417 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3419 SCVAL(pdata,1,perms);
3422 case SMB_ACL_USER_OBJ:
3423 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3424 own_grp = (unsigned int)pst->st_uid;
3425 SIVAL(pdata,2,own_grp);
3430 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3432 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3435 own_grp = (unsigned int)*puid;
3436 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3437 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3438 SIVAL(pdata,2,own_grp);
3442 case SMB_ACL_GROUP_OBJ:
3443 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3444 own_grp = (unsigned int)pst->st_gid;
3445 SIVAL(pdata,2,own_grp);
3450 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3452 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3455 own_grp = (unsigned int)*pgid;
3456 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3457 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3458 SIVAL(pdata,2,own_grp);
3463 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3464 SIVAL(pdata,2,0xFFFFFFFF);
3465 SIVAL(pdata,6,0xFFFFFFFF);
3468 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3469 SIVAL(pdata,2,0xFFFFFFFF);
3470 SIVAL(pdata,6,0xFFFFFFFF);
3473 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3476 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3483 /****************************************************************************
3484 Store the FILE_UNIX_BASIC info.
3485 ****************************************************************************/
3487 static char *store_file_unix_basic(connection_struct *conn,
3490 const SMB_STRUCT_STAT *psbuf)
3492 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3493 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3495 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3498 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3501 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3502 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3503 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3506 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3510 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3514 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3517 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3521 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3525 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3528 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3532 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3539 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3540 * the chflags(2) (or equivalent) flags.
3542 * XXX: this really should be behind the VFS interface. To do this, we would
3543 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3544 * Each VFS module could then implement its own mapping as appropriate for the
3545 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3547 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3551 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3555 { UF_IMMUTABLE, EXT_IMMUTABLE },
3559 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3563 { UF_HIDDEN, EXT_HIDDEN },
3566 /* Do not remove. We need to guarantee that this array has at least one
3567 * entry to build on HP-UX.
3573 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3574 uint32 *smb_fflags, uint32 *smb_fmask)
3576 #ifdef HAVE_STAT_ST_FLAGS
3579 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3580 *smb_fmask |= info2_flags_map[i].smb_fflag;
3581 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3582 *smb_fflags |= info2_flags_map[i].smb_fflag;
3585 #endif /* HAVE_STAT_ST_FLAGS */
3588 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3589 const uint32 smb_fflags,
3590 const uint32 smb_fmask,
3593 #ifdef HAVE_STAT_ST_FLAGS
3594 uint32 max_fmask = 0;
3597 *stat_fflags = psbuf->st_flags;
3599 /* For each flags requested in smb_fmask, check the state of the
3600 * corresponding flag in smb_fflags and set or clear the matching
3604 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3605 max_fmask |= info2_flags_map[i].smb_fflag;
3606 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3607 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3608 *stat_fflags |= info2_flags_map[i].stat_fflag;
3610 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3615 /* If smb_fmask is asking to set any bits that are not supported by
3616 * our flag mappings, we should fail.
3618 if ((smb_fmask & max_fmask) != smb_fmask) {
3625 #endif /* HAVE_STAT_ST_FLAGS */
3629 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3630 * of file flags and birth (create) time.
3632 static char *store_file_unix_basic_info2(connection_struct *conn,
3635 const SMB_STRUCT_STAT *psbuf)
3637 uint32 file_flags = 0;
3638 uint32 flags_mask = 0;
3640 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3642 /* Create (birth) time 64 bit */
3643 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3646 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3647 SIVAL(pdata, 0, file_flags); /* flags */
3648 SIVAL(pdata, 4, flags_mask); /* mask */
3654 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3655 const struct stream_struct *streams,
3657 unsigned int max_data_bytes,
3658 unsigned int *data_size)
3661 unsigned int ofs = 0;
3663 for (i=0; i<num_streams; i++) {
3664 unsigned int next_offset;
3666 smb_ucs2_t *namebuf;
3668 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3671 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3672 return NT_STATUS_INVALID_PARAMETER;
3676 * name_buf is now null-terminated, we need to marshall as not
3682 if (ofs + 24 + namelen > max_data_bytes) {
3683 TALLOC_FREE(namebuf);
3684 return NT_STATUS_BUFFER_TOO_SMALL;
3687 SIVAL(data, ofs+4, namelen);
3688 SOFF_T(data, ofs+8, streams[i].size);
3689 SOFF_T(data, ofs+16, streams[i].alloc_size);
3690 memcpy(data+ofs+24, namebuf, namelen);
3691 TALLOC_FREE(namebuf);
3693 next_offset = ofs + 24 + namelen;
3695 if (i == num_streams-1) {
3696 SIVAL(data, ofs, 0);
3699 unsigned int align = ndr_align_size(next_offset, 8);
3701 if (next_offset + align > max_data_bytes) {
3702 return NT_STATUS_BUFFER_TOO_SMALL;
3705 memset(data+next_offset, 0, align);
3706 next_offset += align;
3708 SIVAL(data, ofs, next_offset - ofs);
3717 return NT_STATUS_OK;
3720 /****************************************************************************
3721 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3722 ****************************************************************************/
3724 static void call_trans2qpipeinfo(connection_struct *conn,
3725 struct smb_request *req,
3726 unsigned int tran_call,
3727 char **pparams, int total_params,
3728 char **ppdata, int total_data,
3729 unsigned int max_data_bytes)
3731 char *params = *pparams;
3732 char *pdata = *ppdata;
3733 unsigned int data_size = 0;
3734 unsigned int param_size = 2;
3736 smb_np_struct *p_pipe = NULL;
3739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3743 if (total_params < 4) {
3744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3748 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3749 if (p_pipe == NULL) {
3750 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3754 info_level = SVAL(params,2);
3756 *pparams = (char *)SMB_REALLOC(*pparams,2);
3757 if (*pparams == NULL) {
3758 reply_nterror(req, NT_STATUS_NO_MEMORY);
3763 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3764 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3765 if (*ppdata == NULL ) {
3766 reply_nterror(req, NT_STATUS_NO_MEMORY);
3771 switch (info_level) {
3772 case SMB_FILE_STANDARD_INFORMATION:
3774 SOFF_T(pdata,0,4096LL);
3781 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3785 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3791 /****************************************************************************
3792 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3793 file name or file id).
3794 ****************************************************************************/
3796 static void call_trans2qfilepathinfo(connection_struct *conn,
3797 struct smb_request *req,
3798 unsigned int tran_call,
3799 char **pparams, int total_params,
3800 char **ppdata, int total_data,
3801 unsigned int max_data_bytes)
3803 char *params = *pparams;
3804 char *pdata = *ppdata;
3805 char *dstart, *dend;
3809 SMB_OFF_T file_size=0;
3810 SMB_BIG_UINT allocation_size=0;
3811 unsigned int data_size = 0;
3812 unsigned int param_size = 2;
3813 SMB_STRUCT_STAT sbuf;
3814 char *dos_fname = NULL;
3820 bool delete_pending = False;
3822 time_t create_time, mtime, atime;
3823 struct timespec create_time_ts, mtime_ts, atime_ts;
3824 struct timespec write_time_ts;
3825 files_struct *fsp = NULL;
3826 struct file_id fileid;
3827 struct ea_list *ea_list = NULL;
3828 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3829 char *lock_data = NULL;
3830 bool ms_dfs_link = false;
3831 TALLOC_CTX *ctx = talloc_tos();
3834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3839 ZERO_STRUCT(write_time_ts);
3841 if (tran_call == TRANSACT2_QFILEINFO) {
3842 if (total_params < 4) {
3843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3848 call_trans2qpipeinfo(conn, req, tran_call,
3849 pparams, total_params,
3855 fsp = file_fsp(SVAL(params,0));
3856 info_level = SVAL(params,2);
3858 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3860 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3861 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3865 /* Initial check for valid fsp ptr. */
3866 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3870 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3872 reply_nterror(req, NT_STATUS_NO_MEMORY);
3876 if(fsp->fake_file_handle) {
3878 * This is actually for the QUOTA_FAKE_FILE --metze
3881 /* We know this name is ok, it's already passed the checks. */
3883 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3885 * This is actually a QFILEINFO on a directory
3886 * handle (returned from an NT SMB). NT5.0 seems
3887 * to do this call. JRA.
3890 if (INFO_LEVEL_IS_UNIX(info_level)) {
3891 /* Always do lstat for UNIX calls. */
3892 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3893 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3894 reply_unixerror(req,ERRDOS,ERRbadpath);
3897 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3898 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3899 reply_unixerror(req, ERRDOS, ERRbadpath);
3903 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3904 get_file_infos(fileid, &delete_pending, &write_time_ts);
3907 * Original code - this is an open file.
3909 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3913 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3914 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3915 reply_unixerror(req, ERRDOS, ERRbadfid);
3918 pos = fsp->fh->position_information;
3919 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3920 get_file_infos(fileid, &delete_pending, &write_time_ts);
3921 access_mask = fsp->access_mask;
3925 NTSTATUS status = NT_STATUS_OK;
3928 if (total_params < 7) {
3929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3933 info_level = SVAL(params,0);
3935 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3937 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3938 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3942 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3944 STR_TERMINATE, &status);
3945 if (!NT_STATUS_IS_OK(status)) {
3946 reply_nterror(req, status);
3950 status = resolve_dfspath(ctx,
3952 req->flags2 & FLAGS2_DFS_PATHNAMES,
3955 if (!NT_STATUS_IS_OK(status)) {
3956 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3957 reply_botherror(req,
3958 NT_STATUS_PATH_NOT_COVERED,
3959 ERRSRV, ERRbadpath);
3961 reply_nterror(req, status);
3965 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 reply_nterror(req, status);
3970 status = check_name(conn, fname);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3973 reply_nterror(req, status);
3977 if (INFO_LEVEL_IS_UNIX(info_level)) {
3978 /* Always do lstat for UNIX calls. */
3979 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3980 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3981 reply_unixerror(req, ERRDOS, ERRbadpath);
3985 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3986 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
3989 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3990 reply_unixerror(req, ERRDOS, ERRbadpath);
3995 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3996 get_file_infos(fileid, &delete_pending, &write_time_ts);
3997 if (delete_pending) {
3998 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4003 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4004 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4008 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4009 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4011 p = strrchr_m(fname,'/');
4018 mode = dos_mode_msdfs(conn,fname,&sbuf);
4020 mode = dos_mode(conn,fname,&sbuf);
4023 mode = FILE_ATTRIBUTE_NORMAL;
4025 nlink = sbuf.st_nlink;
4027 if (nlink && (mode&aDIR)) {
4031 if ((nlink > 0) && delete_pending) {
4035 fullpathname = fname;
4037 file_size = get_file_size(sbuf);
4039 /* Pull out any data sent here before we realloc. */
4040 switch (info_level) {
4041 case SMB_INFO_QUERY_EAS_FROM_LIST:
4043 /* Pull any EA list from the data portion. */
4046 if (total_data < 4) {
4048 req, NT_STATUS_INVALID_PARAMETER);
4051 ea_size = IVAL(pdata,0);
4053 if (total_data > 0 && ea_size != total_data) {
4054 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4055 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4057 req, NT_STATUS_INVALID_PARAMETER);
4061 if (!lp_ea_support(SNUM(conn))) {
4062 reply_doserror(req, ERRDOS,
4063 ERReasnotsupported);
4067 /* Pull out the list of names. */
4068 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4071 req, NT_STATUS_INVALID_PARAMETER);
4077 case SMB_QUERY_POSIX_LOCK:
4079 if (fsp == NULL || fsp->fh->fd == -1) {
4080 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4084 if (total_data != POSIX_LOCK_DATA_SIZE) {
4086 req, NT_STATUS_INVALID_PARAMETER);
4090 /* Copy the lock range data. */
4091 lock_data = (char *)TALLOC_MEMDUP(
4092 ctx, pdata, total_data);
4094 reply_nterror(req, NT_STATUS_NO_MEMORY);
4102 *pparams = (char *)SMB_REALLOC(*pparams,2);
4103 if (*pparams == NULL) {
4104 reply_nterror(req, NT_STATUS_NO_MEMORY);
4109 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4110 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4111 if (*ppdata == NULL ) {
4112 reply_nterror(req, NT_STATUS_NO_MEMORY);
4117 dend = dstart + data_size - 1;
4119 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4120 mtime_ts = get_mtimespec(&sbuf);
4121 atime_ts = get_atimespec(&sbuf);
4123 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4126 /* Do we have this path open ? */
4128 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4129 fsp1 = file_find_di_first(fileid);
4130 if (fsp1 && fsp1->initial_allocation_size) {
4131 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4135 if (!null_timespec(write_time_ts)) {
4136 mtime_ts = write_time_ts;
4139 if (lp_dos_filetime_resolution(SNUM(conn))) {
4140 dos_filetime_timespec(&create_time_ts);
4141 dos_filetime_timespec(&mtime_ts);
4142 dos_filetime_timespec(&atime_ts);
4145 create_time = convert_timespec_to_time_t(create_time_ts);
4146 mtime = convert_timespec_to_time_t(mtime_ts);
4147 atime = convert_timespec_to_time_t(atime_ts);
4149 /* NT expects the name to be in an exact form of the *full*
4150 filename. See the trans2 torture test */
4151 if (ISDOT(base_name)) {
4152 dos_fname = talloc_strdup(ctx, "\\");
4154 reply_nterror(req, NT_STATUS_NO_MEMORY);
4158 dos_fname = talloc_asprintf(ctx,
4162 reply_nterror(req, NT_STATUS_NO_MEMORY);
4165 string_replace(dos_fname, '/', '\\');
4168 switch (info_level) {
4169 case SMB_INFO_STANDARD:
4170 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4172 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4173 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4174 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4175 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4176 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4177 SSVAL(pdata,l1_attrFile,mode);
4180 case SMB_INFO_QUERY_EA_SIZE:
4182 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4183 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4185 srv_put_dos_date2(pdata,0,create_time);
4186 srv_put_dos_date2(pdata,4,atime);
4187 srv_put_dos_date2(pdata,8,mtime); /* write time */
4188 SIVAL(pdata,12,(uint32)file_size);
4189 SIVAL(pdata,16,(uint32)allocation_size);
4190 SSVAL(pdata,20,mode);
4191 SIVAL(pdata,22,ea_size);
4195 case SMB_INFO_IS_NAME_VALID:
4196 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4197 if (tran_call == TRANSACT2_QFILEINFO) {
4198 /* os/2 needs this ? really ?*/
4199 reply_doserror(req, ERRDOS, ERRbadfunc);
4206 case SMB_INFO_QUERY_EAS_FROM_LIST:
4208 size_t total_ea_len = 0;
4209 struct ea_list *ea_file_list = NULL;
4211 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4213 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4214 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4216 if (!ea_list || (total_ea_len > data_size)) {
4218 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4222 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4226 case SMB_INFO_QUERY_ALL_EAS:
4228 /* We have data_size bytes to put EA's into. */
4229 size_t total_ea_len = 0;
4231 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4233 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4234 if (!ea_list || (total_ea_len > data_size)) {
4236 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4240 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4244 case SMB_FILE_BASIC_INFORMATION:
4245 case SMB_QUERY_FILE_BASIC_INFO:
4247 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4248 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4249 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4251 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4255 put_long_date_timespec(pdata,create_time_ts);
4256 put_long_date_timespec(pdata+8,atime_ts);
4257 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4258 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4259 SIVAL(pdata,32,mode);
4261 DEBUG(5,("SMB_QFBI - "));
4262 DEBUG(5,("create: %s ", ctime(&create_time)));
4263 DEBUG(5,("access: %s ", ctime(&atime)));
4264 DEBUG(5,("write: %s ", ctime(&mtime)));
4265 DEBUG(5,("change: %s ", ctime(&mtime)));
4266 DEBUG(5,("mode: %x\n", mode));
4269 case SMB_FILE_STANDARD_INFORMATION:
4270 case SMB_QUERY_FILE_STANDARD_INFO:
4272 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4274 SOFF_T(pdata,0,allocation_size);
4275 SOFF_T(pdata,8,file_size);
4276 SIVAL(pdata,16,nlink);
4277 SCVAL(pdata,20,delete_pending?1:0);
4278 SCVAL(pdata,21,(mode&aDIR)?1:0);
4279 SSVAL(pdata,22,0); /* Padding. */
4282 case SMB_FILE_EA_INFORMATION:
4283 case SMB_QUERY_FILE_EA_INFO:
4285 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4286 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4288 SIVAL(pdata,0,ea_size);
4292 /* Get the 8.3 name - used if NT SMB was negotiated. */
4293 case SMB_QUERY_FILE_ALT_NAME_INFO:
4294 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4296 char mangled_name[13];
4297 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4298 if (!name_to_8_3(base_name,mangled_name,
4299 True,conn->params)) {
4302 NT_STATUS_NO_MEMORY);
4304 len = srvstr_push(dstart, req->flags2,
4305 pdata+4, mangled_name,
4306 PTR_DIFF(dend, pdata+4),
4308 data_size = 4 + len;
4313 case SMB_QUERY_FILE_NAME_INFO:
4315 this must be *exactly* right for ACLs on mapped drives to work
4317 len = srvstr_push(dstart, req->flags2,
4319 PTR_DIFF(dend, pdata+4),
4321 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4322 data_size = 4 + len;
4326 case SMB_FILE_ALLOCATION_INFORMATION:
4327 case SMB_QUERY_FILE_ALLOCATION_INFO:
4328 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4330 SOFF_T(pdata,0,allocation_size);
4333 case SMB_FILE_END_OF_FILE_INFORMATION:
4334 case SMB_QUERY_FILE_END_OF_FILEINFO:
4335 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4337 SOFF_T(pdata,0,file_size);
4340 case SMB_QUERY_FILE_ALL_INFO:
4341 case SMB_FILE_ALL_INFORMATION:
4343 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4344 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4345 put_long_date_timespec(pdata,create_time_ts);
4346 put_long_date_timespec(pdata+8,atime_ts);
4347 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4348 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4349 SIVAL(pdata,32,mode);
4350 SIVAL(pdata,36,0); /* padding. */
4352 SOFF_T(pdata,0,allocation_size);
4353 SOFF_T(pdata,8,file_size);
4354 SIVAL(pdata,16,nlink);
4355 SCVAL(pdata,20,delete_pending);
4356 SCVAL(pdata,21,(mode&aDIR)?1:0);
4359 SIVAL(pdata,0,ea_size);
4360 pdata += 4; /* EA info */
4361 len = srvstr_push(dstart, req->flags2,
4363 PTR_DIFF(dend, pdata+4),
4367 data_size = PTR_DIFF(pdata,(*ppdata));
4370 case SMB_FILE_INTERNAL_INFORMATION:
4371 /* This should be an index number - looks like
4374 I think this causes us to fail the IFSKIT
4375 BasicFileInformationTest. -tpot */
4377 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4378 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4379 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4383 case SMB_FILE_ACCESS_INFORMATION:
4384 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4385 SIVAL(pdata,0,access_mask);
4389 case SMB_FILE_NAME_INFORMATION:
4390 /* Pathname with leading '\'. */
4393 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4394 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4395 SIVAL(pdata,0,byte_len);
4396 data_size = 4 + byte_len;
4400 case SMB_FILE_DISPOSITION_INFORMATION:
4401 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4403 SCVAL(pdata,0,delete_pending);
4406 case SMB_FILE_POSITION_INFORMATION:
4407 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4409 SOFF_T(pdata,0,pos);
4412 case SMB_FILE_MODE_INFORMATION:
4413 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4414 SIVAL(pdata,0,mode);
4418 case SMB_FILE_ALIGNMENT_INFORMATION:
4419 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4420 SIVAL(pdata,0,0); /* No alignment needed. */
4425 * NT4 server just returns "invalid query" to this - if we try
4426 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4429 /* The first statement above is false - verified using Thursby
4430 * client against NT4 -- gcolley.
4432 case SMB_QUERY_FILE_STREAM_INFO:
4433 case SMB_FILE_STREAM_INFORMATION: {
4434 unsigned int num_streams;
4435 struct stream_struct *streams;
4438 DEBUG(10,("call_trans2qfilepathinfo: "
4439 "SMB_FILE_STREAM_INFORMATION\n"));
4441 status = SMB_VFS_STREAMINFO(
4442 conn, fsp, fname, talloc_tos(),
4443 &num_streams, &streams);
4445 if (!NT_STATUS_IS_OK(status)) {
4446 DEBUG(10, ("could not get stream info: %s\n",
4447 nt_errstr(status)));
4448 reply_nterror(req, status);
4452 status = marshall_stream_info(num_streams, streams,
4453 pdata, max_data_bytes,
4456 if (!NT_STATUS_IS_OK(status)) {
4457 DEBUG(10, ("marshall_stream_info failed: %s\n",
4458 nt_errstr(status)));
4459 reply_nterror(req, status);
4463 TALLOC_FREE(streams);
4467 case SMB_QUERY_COMPRESSION_INFO:
4468 case SMB_FILE_COMPRESSION_INFORMATION:
4469 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4470 SOFF_T(pdata,0,file_size);
4471 SIVAL(pdata,8,0); /* ??? */
4472 SIVAL(pdata,12,0); /* ??? */
4476 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4477 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4478 put_long_date_timespec(pdata,create_time_ts);
4479 put_long_date_timespec(pdata+8,atime_ts);
4480 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4481 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4482 SOFF_T(pdata,32,allocation_size);
4483 SOFF_T(pdata,40,file_size);
4484 SIVAL(pdata,48,mode);
4485 SIVAL(pdata,52,0); /* ??? */
4489 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4490 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4491 SIVAL(pdata,0,mode);
4497 * CIFS UNIX Extensions.
4500 case SMB_QUERY_FILE_UNIX_BASIC:
4502 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4503 data_size = PTR_DIFF(pdata,(*ppdata));
4507 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4509 for (i=0; i<100; i++)
4510 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4516 case SMB_QUERY_FILE_UNIX_INFO2:
4518 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4519 data_size = PTR_DIFF(pdata,(*ppdata));
4523 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4525 for (i=0; i<100; i++)
4526 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4532 case SMB_QUERY_FILE_UNIX_LINK:
4534 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4537 reply_nterror(req, NT_STATUS_NO_MEMORY);
4541 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4543 if(!S_ISLNK(sbuf.st_mode)) {
4544 reply_unixerror(req, ERRSRV,
4549 reply_unixerror(req, ERRDOS, ERRbadlink);
4552 len = SMB_VFS_READLINK(conn,fullpathname,
4555 reply_unixerror(req, ERRDOS,
4560 len = srvstr_push(dstart, req->flags2,
4562 PTR_DIFF(dend, pdata),
4565 data_size = PTR_DIFF(pdata,(*ppdata));
4570 #if defined(HAVE_POSIX_ACLS)
4571 case SMB_QUERY_POSIX_ACL:
4573 SMB_ACL_T file_acl = NULL;
4574 SMB_ACL_T def_acl = NULL;
4575 uint16 num_file_acls = 0;
4576 uint16 num_def_acls = 0;
4578 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4579 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4581 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4584 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4585 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4589 NT_STATUS_NOT_IMPLEMENTED);
4593 if (S_ISDIR(sbuf.st_mode)) {
4594 if (fsp && fsp->is_directory) {
4595 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4597 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4599 def_acl = free_empty_sys_acl(conn, def_acl);
4602 num_file_acls = count_acl_entries(conn, file_acl);
4603 num_def_acls = count_acl_entries(conn, def_acl);
4605 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4606 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4608 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4609 SMB_POSIX_ACL_HEADER_SIZE) ));
4611 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4614 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4618 NT_STATUS_BUFFER_TOO_SMALL);
4622 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4623 SSVAL(pdata,2,num_file_acls);
4624 SSVAL(pdata,4,num_def_acls);
4625 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4627 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4630 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4633 req, NT_STATUS_INTERNAL_ERROR);
4636 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4638 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4641 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4645 NT_STATUS_INTERNAL_ERROR);
4650 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4653 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4655 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4661 case SMB_QUERY_POSIX_LOCK:
4663 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4665 SMB_BIG_UINT offset;
4667 enum brl_type lock_type;
4669 if (total_data != POSIX_LOCK_DATA_SIZE) {
4671 req, NT_STATUS_INVALID_PARAMETER);
4675 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4676 case POSIX_LOCK_TYPE_READ:
4677 lock_type = READ_LOCK;
4679 case POSIX_LOCK_TYPE_WRITE:
4680 lock_type = WRITE_LOCK;
4682 case POSIX_LOCK_TYPE_UNLOCK:
4684 /* There's no point in asking for an unlock... */
4687 NT_STATUS_INVALID_PARAMETER);
4691 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4692 #if defined(HAVE_LONGLONG)
4693 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4694 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4695 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4696 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4697 #else /* HAVE_LONGLONG */
4698 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4699 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4700 #endif /* HAVE_LONGLONG */
4702 status = query_lock(fsp,
4709 if (ERROR_WAS_LOCK_DENIED(status)) {
4710 /* Here we need to report who has it locked... */
4711 data_size = POSIX_LOCK_DATA_SIZE;
4713 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4714 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4715 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4716 #if defined(HAVE_LONGLONG)
4717 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4718 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4719 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4720 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4721 #else /* HAVE_LONGLONG */
4722 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4723 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4724 #endif /* HAVE_LONGLONG */
4726 } else if (NT_STATUS_IS_OK(status)) {
4727 /* For success we just return a copy of what we sent
4728 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4729 data_size = POSIX_LOCK_DATA_SIZE;
4730 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4731 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4733 reply_nterror(req, status);
4740 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4744 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4750 /****************************************************************************
4751 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4753 ****************************************************************************/
4755 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4756 connection_struct *conn,
4757 const char *oldname_in,
4758 const char *newname_in)
4760 SMB_STRUCT_STAT sbuf1, sbuf2;
4761 char *last_component_oldname = NULL;
4762 char *last_component_newname = NULL;
4763 char *oldname = NULL;
4764 char *newname = NULL;
4765 NTSTATUS status = NT_STATUS_OK;
4770 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4771 &last_component_oldname, &sbuf1);
4772 if (!NT_STATUS_IS_OK(status)) {
4776 status = check_name(conn, oldname);
4777 if (!NT_STATUS_IS_OK(status)) {
4781 /* source must already exist. */
4782 if (!VALID_STAT(sbuf1)) {
4783 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4786 status = unix_convert(ctx, conn, newname_in, False, &newname,
4787 &last_component_newname, &sbuf2);
4788 if (!NT_STATUS_IS_OK(status)) {
4792 status = check_name(conn, newname);
4793 if (!NT_STATUS_IS_OK(status)) {
4797 /* Disallow if newname already exists. */
4798 if (VALID_STAT(sbuf2)) {
4799 return NT_STATUS_OBJECT_NAME_COLLISION;
4802 /* No links from a directory. */
4803 if (S_ISDIR(sbuf1.st_mode)) {
4804 return NT_STATUS_FILE_IS_A_DIRECTORY;
4807 /* Ensure this is within the share. */
4808 status = check_reduced_name(conn, oldname);
4809 if (!NT_STATUS_IS_OK(status)) {
4813 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4815 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4816 status = map_nt_error_from_unix(errno);
4817 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4818 nt_errstr(status), newname, oldname));
4824 /****************************************************************************
4825 Deal with setting the time from any of the setfilepathinfo functions.
4826 ****************************************************************************/
4828 NTSTATUS smb_set_file_time(connection_struct *conn,
4831 const SMB_STRUCT_STAT *psbuf,
4832 struct timespec ts[2],
4833 bool setting_write_time)
4836 FILE_NOTIFY_CHANGE_LAST_ACCESS
4837 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4839 if (!VALID_STAT(*psbuf)) {
4840 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4843 /* get some defaults (no modifications) if any info is zero or -1. */
4844 if (null_timespec(ts[0])) {
4845 ts[0] = get_atimespec(psbuf);
4846 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4849 if (null_timespec(ts[1])) {
4850 ts[1] = get_mtimespec(psbuf);
4851 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4854 if (!setting_write_time) {
4855 /* ts[1] comes from change time, not write time. */
4856 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4859 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4860 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4863 * Try and set the times of this file if
4864 * they are different from the current values.
4868 struct timespec mts = get_mtimespec(psbuf);
4869 struct timespec ats = get_atimespec(psbuf);
4870 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4871 return NT_STATUS_OK;
4875 if (setting_write_time) {
4877 * This was a setfileinfo on an open file.
4878 * NT does this a lot. We also need to
4879 * set the time here, as it can be read by
4880 * FindFirst/FindNext and with the patch for bug #2045
4881 * in smbd/fileio.c it ensures that this timestamp is
4882 * kept sticky even after a write. We save the request
4883 * away and will set it on file close and after a write. JRA.
4886 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4887 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4890 set_sticky_write_time_fsp(fsp, ts[1]);
4892 set_sticky_write_time_path(conn, fname,
4893 vfs_file_id_from_sbuf(conn, psbuf),
4898 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4900 if(file_ntimes(conn, fname, ts)!=0) {
4901 return map_nt_error_from_unix(errno);
4903 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4905 return NT_STATUS_OK;
4908 /****************************************************************************
4909 Deal with setting the dosmode from any of the setfilepathinfo functions.
4910 ****************************************************************************/
4912 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4914 SMB_STRUCT_STAT *psbuf,
4917 if (!VALID_STAT(*psbuf)) {
4918 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4922 if (S_ISDIR(psbuf->st_mode)) {
4929 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4931 /* check the mode isn't different, before changing it */
4932 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4934 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4935 fname, (unsigned int)dosmode ));
4937 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4938 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4939 fname, strerror(errno)));
4940 return map_nt_error_from_unix(errno);
4943 return NT_STATUS_OK;
4946 /****************************************************************************
4947 Deal with setting the size from any of the setfilepathinfo functions.
4948 ****************************************************************************/
4950 static NTSTATUS smb_set_file_size(connection_struct *conn,
4951 struct smb_request *req,
4954 SMB_STRUCT_STAT *psbuf,
4957 NTSTATUS status = NT_STATUS_OK;
4958 files_struct *new_fsp = NULL;
4960 if (!VALID_STAT(*psbuf)) {
4961 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4964 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4966 if (size == get_file_size(*psbuf)) {
4967 return NT_STATUS_OK;
4970 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4971 fname, (double)size ));
4973 if (fsp && fsp->fh->fd != -1) {
4974 /* Handle based call. */
4975 if (vfs_set_filelen(fsp, size) == -1) {
4976 return map_nt_error_from_unix(errno);
4978 trigger_write_time_update_immediate(fsp);
4979 return NT_STATUS_OK;
4982 status = open_file_ntcreate(conn, req, fname, psbuf,
4983 FILE_WRITE_ATTRIBUTES,
4984 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4987 FILE_ATTRIBUTE_NORMAL,
4988 FORCE_OPLOCK_BREAK_TO_NONE,
4991 if (!NT_STATUS_IS_OK(status)) {
4992 /* NB. We check for open_was_deferred in the caller. */
4996 if (vfs_set_filelen(new_fsp, size) == -1) {
4997 status = map_nt_error_from_unix(errno);
4998 close_file(new_fsp,NORMAL_CLOSE);
5002 trigger_write_time_update_immediate(new_fsp);
5003 close_file(new_fsp,NORMAL_CLOSE);
5004 return NT_STATUS_OK;
5007 /****************************************************************************
5008 Deal with SMB_INFO_SET_EA.
5009 ****************************************************************************/
5011 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5017 struct ea_list *ea_list = NULL;
5018 TALLOC_CTX *ctx = NULL;
5019 NTSTATUS status = NT_STATUS_OK;
5021 if (total_data < 10) {
5023 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5024 length. They seem to have no effect. Bug #3212. JRA */
5026 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5027 /* We're done. We only get EA info in this call. */
5028 return NT_STATUS_OK;
5031 return NT_STATUS_INVALID_PARAMETER;
5034 if (IVAL(pdata,0) > total_data) {
5035 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5036 IVAL(pdata,0), (unsigned int)total_data));
5037 return NT_STATUS_INVALID_PARAMETER;
5041 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5043 return NT_STATUS_INVALID_PARAMETER;
5045 status = set_ea(conn, fsp, fname, ea_list);
5050 /****************************************************************************
5051 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5052 ****************************************************************************/
5054 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5059 SMB_STRUCT_STAT *psbuf)
5061 NTSTATUS status = NT_STATUS_OK;
5062 bool delete_on_close;
5065 if (total_data < 1) {
5066 return NT_STATUS_INVALID_PARAMETER;
5070 return NT_STATUS_INVALID_HANDLE;
5073 delete_on_close = (CVAL(pdata,0) ? True : False);
5074 dosmode = dos_mode(conn, fname, psbuf);
5076 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5077 "delete_on_close = %u\n",
5079 (unsigned int)dosmode,
5080 (unsigned int)delete_on_close ));
5082 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5084 if (!NT_STATUS_IS_OK(status)) {
5088 /* The set is across all open files on this dev/inode pair. */
5089 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
5090 return NT_STATUS_ACCESS_DENIED;
5092 return NT_STATUS_OK;
5095 /****************************************************************************
5096 Deal with SMB_FILE_POSITION_INFORMATION.
5097 ****************************************************************************/
5099 static NTSTATUS smb_file_position_information(connection_struct *conn,
5104 SMB_BIG_UINT position_information;
5106 if (total_data < 8) {
5107 return NT_STATUS_INVALID_PARAMETER;
5111 /* Ignore on pathname based set. */
5112 return NT_STATUS_OK;
5115 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5116 #ifdef LARGE_SMB_OFF_T
5117 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5118 #else /* LARGE_SMB_OFF_T */
5119 if (IVAL(pdata,4) != 0) {
5120 /* more than 32 bits? */
5121 return NT_STATUS_INVALID_PARAMETER;
5123 #endif /* LARGE_SMB_OFF_T */
5125 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5126 fsp->fsp_name, (double)position_information ));
5127 fsp->fh->position_information = position_information;
5128 return NT_STATUS_OK;
5131 /****************************************************************************
5132 Deal with SMB_FILE_MODE_INFORMATION.
5133 ****************************************************************************/
5135 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5141 if (total_data < 4) {
5142 return NT_STATUS_INVALID_PARAMETER;
5144 mode = IVAL(pdata,0);
5145 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5146 return NT_STATUS_INVALID_PARAMETER;
5148 return NT_STATUS_OK;
5151 /****************************************************************************
5152 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5153 ****************************************************************************/
5155 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5156 struct smb_request *req,
5161 char *link_target = NULL;
5162 const char *newname = fname;
5163 NTSTATUS status = NT_STATUS_OK;
5164 TALLOC_CTX *ctx = talloc_tos();
5166 /* Set a symbolic link. */
5167 /* Don't allow this if follow links is false. */
5169 if (total_data == 0) {
5170 return NT_STATUS_INVALID_PARAMETER;
5173 if (!lp_symlinks(SNUM(conn))) {
5174 return NT_STATUS_ACCESS_DENIED;
5177 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5178 total_data, STR_TERMINATE);
5181 return NT_STATUS_INVALID_PARAMETER;
5184 /* !widelinks forces the target path to be within the share. */
5185 /* This means we can interpret the target as a pathname. */
5186 if (!lp_widelinks(SNUM(conn))) {
5187 char *rel_name = NULL;
5188 char *last_dirp = NULL;
5190 if (*link_target == '/') {
5191 /* No absolute paths allowed. */
5192 return NT_STATUS_ACCESS_DENIED;
5194 rel_name = talloc_strdup(ctx,newname);
5196 return NT_STATUS_NO_MEMORY;
5198 last_dirp = strrchr_m(rel_name, '/');
5200 last_dirp[1] = '\0';
5202 rel_name = talloc_strdup(ctx,"./");
5204 return NT_STATUS_NO_MEMORY;
5207 rel_name = talloc_asprintf_append(rel_name,
5211 return NT_STATUS_NO_MEMORY;
5214 status = check_name(conn, rel_name);
5215 if (!NT_STATUS_IS_OK(status)) {
5220 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5221 newname, link_target ));
5223 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5224 return map_nt_error_from_unix(errno);
5227 return NT_STATUS_OK;
5230 /****************************************************************************
5231 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5232 ****************************************************************************/
5234 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5235 struct smb_request *req,
5236 const char *pdata, int total_data,
5239 char *oldname = NULL;
5240 TALLOC_CTX *ctx = talloc_tos();
5241 NTSTATUS status = NT_STATUS_OK;
5243 /* Set a hard link. */
5244 if (total_data == 0) {
5245 return NT_STATUS_INVALID_PARAMETER;
5248 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5249 total_data, STR_TERMINATE, &status);
5250 if (!NT_STATUS_IS_OK(status)) {
5254 status = resolve_dfspath(ctx, conn,
5255 req->flags2 & FLAGS2_DFS_PATHNAMES,
5258 if (!NT_STATUS_IS_OK(status)) {
5262 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5265 return hardlink_internals(ctx, conn, oldname, fname);
5268 /****************************************************************************
5269 Deal with SMB_FILE_RENAME_INFORMATION.
5270 ****************************************************************************/
5272 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5273 struct smb_request *req,
5282 char *newname = NULL;
5283 char *base_name = NULL;
5284 bool dest_has_wcard = False;
5285 NTSTATUS status = NT_STATUS_OK;
5287 TALLOC_CTX *ctx = talloc_tos();
5289 if (total_data < 13) {
5290 return NT_STATUS_INVALID_PARAMETER;
5293 overwrite = (CVAL(pdata,0) ? True : False);
5294 root_fid = IVAL(pdata,4);
5295 len = IVAL(pdata,8);
5297 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5298 return NT_STATUS_INVALID_PARAMETER;
5301 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5304 if (!NT_STATUS_IS_OK(status)) {
5308 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5311 status = resolve_dfspath_wcard(ctx, conn,
5312 req->flags2 & FLAGS2_DFS_PATHNAMES,
5316 if (!NT_STATUS_IS_OK(status)) {
5320 /* Check the new name has no '/' characters. */
5321 if (strchr_m(newname, '/')) {
5322 return NT_STATUS_NOT_SUPPORTED;
5325 /* Create the base directory. */
5326 base_name = talloc_strdup(ctx, fname);
5328 return NT_STATUS_NO_MEMORY;
5330 p = strrchr_m(base_name, '/');
5334 base_name = talloc_strdup(ctx, "./");
5336 return NT_STATUS_NO_MEMORY;
5339 /* Append the new name. */
5340 base_name = talloc_asprintf_append(base_name,
5344 return NT_STATUS_NO_MEMORY;
5348 SMB_STRUCT_STAT sbuf;
5349 char *newname_last_component = NULL;
5353 status = unix_convert(ctx, conn, newname, False,
5355 &newname_last_component,
5358 /* If an error we expect this to be
5359 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5361 if (!NT_STATUS_IS_OK(status)
5362 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5367 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5368 fsp->fnum, fsp->fsp_name, base_name ));
5369 status = rename_internals_fsp(conn, fsp, base_name,
5370 newname_last_component, 0,
5373 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5374 fname, base_name ));
5375 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5376 overwrite, False, dest_has_wcard,
5377 FILE_WRITE_ATTRIBUTES);
5383 /****************************************************************************
5384 Deal with SMB_SET_POSIX_ACL.
5385 ****************************************************************************/
5387 #if defined(HAVE_POSIX_ACLS)
5388 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5393 SMB_STRUCT_STAT *psbuf)
5395 uint16 posix_acl_version;
5396 uint16 num_file_acls;
5397 uint16 num_def_acls;
5398 bool valid_file_acls = True;
5399 bool valid_def_acls = True;
5401 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5402 return NT_STATUS_INVALID_PARAMETER;
5404 posix_acl_version = SVAL(pdata,0);
5405 num_file_acls = SVAL(pdata,2);
5406 num_def_acls = SVAL(pdata,4);
5408 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5409 valid_file_acls = False;
5413 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5414 valid_def_acls = False;
5418 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5419 return NT_STATUS_INVALID_PARAMETER;
5422 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5423 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5424 return NT_STATUS_INVALID_PARAMETER;
5427 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5428 fname ? fname : fsp->fsp_name,
5429 (unsigned int)num_file_acls,
5430 (unsigned int)num_def_acls));
5432 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5433 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5434 return map_nt_error_from_unix(errno);
5437 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5438 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5439 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5440 return map_nt_error_from_unix(errno);
5442 return NT_STATUS_OK;
5446 /****************************************************************************
5447 Deal with SMB_SET_POSIX_LOCK.
5448 ****************************************************************************/
5450 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5451 const struct smb_request *req,
5457 SMB_BIG_UINT offset;
5459 bool blocking_lock = False;
5460 enum brl_type lock_type;
5462 NTSTATUS status = NT_STATUS_OK;
5464 if (fsp == NULL || fsp->fh->fd == -1) {
5465 return NT_STATUS_INVALID_HANDLE;
5468 if (total_data != POSIX_LOCK_DATA_SIZE) {
5469 return NT_STATUS_INVALID_PARAMETER;
5472 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5473 case POSIX_LOCK_TYPE_READ:
5474 lock_type = READ_LOCK;
5476 case POSIX_LOCK_TYPE_WRITE:
5477 /* Return the right POSIX-mappable error code for files opened read-only. */
5478 if (!fsp->can_write) {
5479 return NT_STATUS_INVALID_HANDLE;
5481 lock_type = WRITE_LOCK;
5483 case POSIX_LOCK_TYPE_UNLOCK:
5484 lock_type = UNLOCK_LOCK;
5487 return NT_STATUS_INVALID_PARAMETER;
5490 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5491 blocking_lock = False;
5492 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5493 blocking_lock = True;
5495 return NT_STATUS_INVALID_PARAMETER;
5498 if (!lp_blocking_locks(SNUM(conn))) {
5499 blocking_lock = False;
5502 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5503 #if defined(HAVE_LONGLONG)
5504 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5505 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5506 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5507 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5508 #else /* HAVE_LONGLONG */
5509 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5510 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5511 #endif /* HAVE_LONGLONG */
5513 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5514 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5516 (unsigned int)lock_type,
5517 (unsigned int)lock_pid,
5521 if (lock_type == UNLOCK_LOCK) {
5522 status = do_unlock(smbd_messaging_context(),
5529 uint32 block_smbpid;
5531 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5542 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5544 * A blocking lock was requested. Package up
5545 * this smb into a queued request and push it
5546 * onto the blocking lock queue.
5548 if(push_blocking_lock_request(br_lck,
5551 -1, /* infinite timeout. */
5559 TALLOC_FREE(br_lck);
5563 TALLOC_FREE(br_lck);
5569 /****************************************************************************
5570 Deal with SMB_INFO_STANDARD.
5571 ****************************************************************************/
5573 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5578 const SMB_STRUCT_STAT *psbuf)
5580 struct timespec ts[2];
5582 if (total_data < 12) {
5583 return NT_STATUS_INVALID_PARAMETER;
5587 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5589 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5591 DEBUG(10,("smb_set_info_standard: file %s\n",
5592 fname ? fname : fsp->fsp_name ));
5594 return smb_set_file_time(conn,
5602 /****************************************************************************
5603 Deal with SMB_SET_FILE_BASIC_INFO.
5604 ****************************************************************************/
5606 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5611 SMB_STRUCT_STAT *psbuf)
5613 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5614 struct timespec write_time;
5615 struct timespec changed_time;
5617 struct timespec ts[2];
5618 NTSTATUS status = NT_STATUS_OK;
5619 bool setting_write_time = true;
5621 if (total_data < 36) {
5622 return NT_STATUS_INVALID_PARAMETER;
5625 /* Set the attributes */
5626 dosmode = IVAL(pdata,32);
5627 status = smb_set_file_dosmode(conn,
5631 if (!NT_STATUS_IS_OK(status)) {
5635 /* Ignore create time at offset pdata. */
5638 ts[0] = interpret_long_date(pdata+8);
5640 write_time = interpret_long_date(pdata+16);
5641 changed_time = interpret_long_date(pdata+24);
5644 ts[1] = timespec_min(&write_time, &changed_time);
5646 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5650 /* Prefer a defined time to an undefined one. */
5651 if (null_timespec(ts[1])) {
5652 if (null_timespec(write_time)) {
5653 ts[1] = changed_time;
5654 setting_write_time = false;
5660 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5661 fname ? fname : fsp->fsp_name ));
5663 return smb_set_file_time(conn,
5668 setting_write_time);
5671 /****************************************************************************
5672 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5673 ****************************************************************************/
5675 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5676 struct smb_request *req,
5681 SMB_STRUCT_STAT *psbuf)
5683 SMB_BIG_UINT allocation_size = 0;
5684 NTSTATUS status = NT_STATUS_OK;
5685 files_struct *new_fsp = NULL;
5687 if (!VALID_STAT(*psbuf)) {
5688 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5691 if (total_data < 8) {
5692 return NT_STATUS_INVALID_PARAMETER;
5695 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5696 #ifdef LARGE_SMB_OFF_T
5697 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5698 #else /* LARGE_SMB_OFF_T */
5699 if (IVAL(pdata,4) != 0) {
5700 /* more than 32 bits? */
5701 return NT_STATUS_INVALID_PARAMETER;
5703 #endif /* LARGE_SMB_OFF_T */
5705 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5706 fname, (double)allocation_size ));
5708 if (allocation_size) {
5709 allocation_size = smb_roundup(conn, allocation_size);
5712 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5713 fname, (double)allocation_size ));
5715 if (fsp && fsp->fh->fd != -1) {
5716 /* Open file handle. */
5717 /* Only change if needed. */
5718 if (allocation_size != get_file_size(*psbuf)) {
5719 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5720 return map_nt_error_from_unix(errno);
5723 /* But always update the time. */
5725 * This is equivalent to a write. Ensure it's seen immediately
5726 * if there are no pending writes.
5728 trigger_write_time_update_immediate(fsp);
5729 return NT_STATUS_OK;
5732 /* Pathname or stat or directory file. */
5734 status = open_file_ntcreate(conn, req, fname, psbuf,
5736 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5739 FILE_ATTRIBUTE_NORMAL,
5740 FORCE_OPLOCK_BREAK_TO_NONE,
5743 if (!NT_STATUS_IS_OK(status)) {
5744 /* NB. We check for open_was_deferred in the caller. */
5748 /* Only change if needed. */
5749 if (allocation_size != get_file_size(*psbuf)) {
5750 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5751 status = map_nt_error_from_unix(errno);
5752 close_file(new_fsp,NORMAL_CLOSE);
5757 /* Changing the allocation size should set the last mod time. */
5759 * This is equivalent to a write. Ensure it's seen immediately
5760 * if there are no pending writes.
5762 trigger_write_time_update_immediate(new_fsp);
5764 close_file(new_fsp,NORMAL_CLOSE);
5765 return NT_STATUS_OK;
5768 /****************************************************************************
5769 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5770 ****************************************************************************/
5772 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5773 struct smb_request *req,
5778 SMB_STRUCT_STAT *psbuf)
5782 if (total_data < 8) {
5783 return NT_STATUS_INVALID_PARAMETER;
5786 size = IVAL(pdata,0);
5787 #ifdef LARGE_SMB_OFF_T
5788 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5789 #else /* LARGE_SMB_OFF_T */
5790 if (IVAL(pdata,4) != 0) {
5791 /* more than 32 bits? */
5792 return NT_STATUS_INVALID_PARAMETER;
5794 #endif /* LARGE_SMB_OFF_T */
5795 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5796 "file %s to %.0f\n", fname, (double)size ));
5798 return smb_set_file_size(conn, req,
5805 /****************************************************************************
5806 Allow a UNIX info mknod.
5807 ****************************************************************************/
5809 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5813 SMB_STRUCT_STAT *psbuf)
5815 uint32 file_type = IVAL(pdata,56);
5816 #if defined(HAVE_MAKEDEV)
5817 uint32 dev_major = IVAL(pdata,60);
5818 uint32 dev_minor = IVAL(pdata,68);
5820 SMB_DEV_T dev = (SMB_DEV_T)0;
5821 uint32 raw_unixmode = IVAL(pdata,84);
5825 if (total_data < 100) {
5826 return NT_STATUS_INVALID_PARAMETER;
5829 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5830 if (!NT_STATUS_IS_OK(status)) {
5834 #if defined(HAVE_MAKEDEV)
5835 dev = makedev(dev_major, dev_minor);
5838 switch (file_type) {
5839 #if defined(S_IFIFO)
5840 case UNIX_TYPE_FIFO:
5841 unixmode |= S_IFIFO;
5844 #if defined(S_IFSOCK)
5845 case UNIX_TYPE_SOCKET:
5846 unixmode |= S_IFSOCK;
5849 #if defined(S_IFCHR)
5850 case UNIX_TYPE_CHARDEV:
5851 unixmode |= S_IFCHR;
5854 #if defined(S_IFBLK)
5855 case UNIX_TYPE_BLKDEV:
5856 unixmode |= S_IFBLK;
5860 return NT_STATUS_INVALID_PARAMETER;
5863 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5864 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5866 /* Ok - do the mknod. */
5867 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5868 return map_nt_error_from_unix(errno);
5871 /* If any of the other "set" calls fail we
5872 * don't want to end up with a half-constructed mknod.
5875 if (lp_inherit_perms(SNUM(conn))) {
5877 conn, parent_dirname(fname),
5881 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5882 status = map_nt_error_from_unix(errno);
5883 SMB_VFS_UNLINK(conn,fname);
5886 return NT_STATUS_OK;
5889 /****************************************************************************
5890 Deal with SMB_SET_FILE_UNIX_BASIC.
5891 ****************************************************************************/
5893 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5894 struct smb_request *req,
5899 SMB_STRUCT_STAT *psbuf)
5901 struct timespec ts[2];
5902 uint32 raw_unixmode;
5905 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5906 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5907 NTSTATUS status = NT_STATUS_OK;
5908 bool delete_on_fail = False;
5909 enum perm_type ptype;
5911 if (total_data < 100) {
5912 return NT_STATUS_INVALID_PARAMETER;
5915 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5916 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5917 size=IVAL(pdata,0); /* first 8 Bytes are size */
5918 #ifdef LARGE_SMB_OFF_T
5919 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5920 #else /* LARGE_SMB_OFF_T */
5921 if (IVAL(pdata,4) != 0) {
5922 /* more than 32 bits? */
5923 return NT_STATUS_INVALID_PARAMETER;
5925 #endif /* LARGE_SMB_OFF_T */
5928 ts[0] = interpret_long_date(pdata+24); /* access_time */
5929 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5930 set_owner = (uid_t)IVAL(pdata,40);
5931 set_grp = (gid_t)IVAL(pdata,48);
5932 raw_unixmode = IVAL(pdata,84);
5934 if (VALID_STAT(*psbuf)) {
5935 if (S_ISDIR(psbuf->st_mode)) {
5936 ptype = PERM_EXISTING_DIR;
5938 ptype = PERM_EXISTING_FILE;
5941 ptype = PERM_NEW_FILE;
5944 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5945 if (!NT_STATUS_IS_OK(status)) {
5949 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5950 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5951 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5953 if (!VALID_STAT(*psbuf)) {
5955 * The only valid use of this is to create character and block
5956 * devices, and named pipes. This is deprecated (IMHO) and
5957 * a new info level should be used for mknod. JRA.
5960 status = smb_unix_mknod(conn,
5965 if (!NT_STATUS_IS_OK(status)) {
5969 /* Ensure we don't try and change anything else. */
5970 raw_unixmode = SMB_MODE_NO_CHANGE;
5971 size = get_file_size(*psbuf);
5972 ts[0] = get_atimespec(psbuf);
5973 ts[1] = get_mtimespec(psbuf);
5975 * We continue here as we might want to change the
5978 delete_on_fail = True;
5982 /* Horrible backwards compatibility hack as an old server bug
5983 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5987 size = get_file_size(*psbuf);
5992 * Deal with the UNIX specific mode set.
5995 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5996 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5997 (unsigned int)unixmode, fname ));
5998 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5999 return map_nt_error_from_unix(errno);
6004 * Deal with the UNIX specific uid set.
6007 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6010 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6011 (unsigned int)set_owner, fname ));
6013 if (S_ISLNK(psbuf->st_mode)) {
6014 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6016 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6020 status = map_nt_error_from_unix(errno);
6021 if (delete_on_fail) {
6022 SMB_VFS_UNLINK(conn,fname);
6029 * Deal with the UNIX specific gid set.
6032 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6033 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6034 (unsigned int)set_owner, fname ));
6035 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6036 status = map_nt_error_from_unix(errno);
6037 if (delete_on_fail) {
6038 SMB_VFS_UNLINK(conn,fname);
6044 /* Deal with any size changes. */
6046 status = smb_set_file_size(conn, req,
6051 if (!NT_STATUS_IS_OK(status)) {
6055 /* Deal with any time changes. */
6057 return smb_set_file_time(conn,
6065 /****************************************************************************
6066 Deal with SMB_SET_FILE_UNIX_INFO2.
6067 ****************************************************************************/
6069 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6070 struct smb_request *req,
6075 SMB_STRUCT_STAT *psbuf)
6081 if (total_data < 116) {
6082 return NT_STATUS_INVALID_PARAMETER;
6085 /* Start by setting all the fields that are common between UNIX_BASIC
6088 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6090 if (!NT_STATUS_IS_OK(status)) {
6094 smb_fflags = IVAL(pdata, 108);
6095 smb_fmask = IVAL(pdata, 112);
6097 /* NB: We should only attempt to alter the file flags if the client
6098 * sends a non-zero mask.
6100 if (smb_fmask != 0) {
6101 int stat_fflags = 0;
6103 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6105 /* Client asked to alter a flag we don't understand. */
6106 return NT_STATUS_INVALID_PARAMETER;
6109 if (fsp && fsp->fh->fd != -1) {
6110 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6111 return NT_STATUS_NOT_SUPPORTED;
6113 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6114 return map_nt_error_from_unix(errno);
6119 /* XXX: need to add support for changing the create_time here. You
6120 * can do this for paths on Darwin with setattrlist(2). The right way
6121 * to hook this up is probably by extending the VFS utimes interface.
6124 return NT_STATUS_OK;
6127 /****************************************************************************
6128 Create a directory with POSIX semantics.
6129 ****************************************************************************/
6131 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6132 struct smb_request *req,
6136 SMB_STRUCT_STAT *psbuf,
6137 int *pdata_return_size)
6139 NTSTATUS status = NT_STATUS_OK;
6140 uint32 raw_unixmode = 0;
6141 uint32 mod_unixmode = 0;
6142 mode_t unixmode = (mode_t)0;
6143 files_struct *fsp = NULL;
6144 uint16 info_level_return = 0;
6146 char *pdata = *ppdata;
6148 if (total_data < 18) {
6149 return NT_STATUS_INVALID_PARAMETER;
6152 raw_unixmode = IVAL(pdata,8);
6153 /* Next 4 bytes are not yet defined. */
6155 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6156 if (!NT_STATUS_IS_OK(status)) {
6160 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6162 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6163 fname, (unsigned int)unixmode ));
6165 status = open_directory(conn, req,
6168 FILE_READ_ATTRIBUTES, /* Just a stat open */
6169 FILE_SHARE_NONE, /* Ignored for stat opens */
6176 if (NT_STATUS_IS_OK(status)) {
6177 close_file(fsp, NORMAL_CLOSE);
6180 info_level_return = SVAL(pdata,16);
6182 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6183 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6184 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6185 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6187 *pdata_return_size = 12;
6190 /* Realloc the data size */
6191 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6192 if (*ppdata == NULL) {
6193 *pdata_return_size = 0;
6194 return NT_STATUS_NO_MEMORY;
6198 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6199 SSVAL(pdata,2,0); /* No fnum. */
6200 SIVAL(pdata,4,info); /* Was directory created. */
6202 switch (info_level_return) {
6203 case SMB_QUERY_FILE_UNIX_BASIC:
6204 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6205 SSVAL(pdata,10,0); /* Padding. */
6206 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6208 case SMB_QUERY_FILE_UNIX_INFO2:
6209 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6210 SSVAL(pdata,10,0); /* Padding. */
6211 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6214 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6215 SSVAL(pdata,10,0); /* Padding. */
6222 /****************************************************************************
6223 Open/Create a file with POSIX semantics.
6224 ****************************************************************************/
6226 static NTSTATUS smb_posix_open(connection_struct *conn,
6227 struct smb_request *req,
6231 SMB_STRUCT_STAT *psbuf,
6232 int *pdata_return_size)
6234 bool extended_oplock_granted = False;
6235 char *pdata = *ppdata;
6237 uint32 wire_open_mode = 0;
6238 uint32 raw_unixmode = 0;
6239 uint32 mod_unixmode = 0;
6240 uint32 create_disp = 0;
6241 uint32 access_mask = 0;
6242 uint32 create_options = 0;
6243 NTSTATUS status = NT_STATUS_OK;
6244 mode_t unixmode = (mode_t)0;
6245 files_struct *fsp = NULL;
6246 int oplock_request = 0;
6248 uint16 info_level_return = 0;
6250 if (total_data < 18) {
6251 return NT_STATUS_INVALID_PARAMETER;
6254 flags = IVAL(pdata,0);
6255 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6256 if (oplock_request) {
6257 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6260 wire_open_mode = IVAL(pdata,4);
6262 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6263 return smb_posix_mkdir(conn, req,
6271 switch (wire_open_mode & SMB_ACCMODE) {
6273 access_mask = FILE_READ_DATA;
6276 access_mask = FILE_WRITE_DATA;
6279 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6282 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6283 (unsigned int)wire_open_mode ));
6284 return NT_STATUS_INVALID_PARAMETER;
6287 wire_open_mode &= ~SMB_ACCMODE;
6289 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6290 create_disp = FILE_CREATE;
6291 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6292 create_disp = FILE_OVERWRITE_IF;
6293 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6294 create_disp = FILE_OPEN_IF;
6296 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6297 (unsigned int)wire_open_mode ));
6298 return NT_STATUS_INVALID_PARAMETER;
6301 raw_unixmode = IVAL(pdata,8);
6302 /* Next 4 bytes are not yet defined. */
6304 status = unix_perms_from_wire(conn,
6307 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6310 if (!NT_STATUS_IS_OK(status)) {
6314 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6316 if (wire_open_mode & SMB_O_SYNC) {
6317 create_options |= FILE_WRITE_THROUGH;
6319 if (wire_open_mode & SMB_O_APPEND) {
6320 access_mask |= FILE_APPEND_DATA;
6322 if (wire_open_mode & SMB_O_DIRECT) {
6323 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6326 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6328 (unsigned int)wire_open_mode,
6329 (unsigned int)unixmode ));
6331 status = open_file_ntcreate(conn, req,
6335 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6337 0, /* no create options yet. */
6343 if (!NT_STATUS_IS_OK(status)) {
6347 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6348 extended_oplock_granted = True;
6351 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6352 extended_oplock_granted = True;
6355 info_level_return = SVAL(pdata,16);
6357 /* Allocate the correct return size. */
6359 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6360 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6361 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6362 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6364 *pdata_return_size = 12;
6367 /* Realloc the data size */
6368 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6369 if (*ppdata == NULL) {
6370 close_file(fsp,ERROR_CLOSE);
6371 *pdata_return_size = 0;
6372 return NT_STATUS_NO_MEMORY;
6376 if (extended_oplock_granted) {
6377 if (flags & REQUEST_BATCH_OPLOCK) {
6378 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6380 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6382 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6383 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6385 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6388 SSVAL(pdata,2,fsp->fnum);
6389 SIVAL(pdata,4,info); /* Was file created etc. */
6391 switch (info_level_return) {
6392 case SMB_QUERY_FILE_UNIX_BASIC:
6393 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6394 SSVAL(pdata,10,0); /* padding. */
6395 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6397 case SMB_QUERY_FILE_UNIX_INFO2:
6398 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6399 SSVAL(pdata,10,0); /* padding. */
6400 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6403 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6404 SSVAL(pdata,10,0); /* padding. */
6407 return NT_STATUS_OK;
6410 /****************************************************************************
6411 Delete a file with POSIX semantics.
6412 ****************************************************************************/
6414 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6415 struct smb_request *req,
6419 SMB_STRUCT_STAT *psbuf)
6421 NTSTATUS status = NT_STATUS_OK;
6422 files_struct *fsp = NULL;
6427 struct share_mode_lock *lck = NULL;
6429 if (total_data < 2) {
6430 return NT_STATUS_INVALID_PARAMETER;
6433 flags = SVAL(pdata,0);
6435 if (!VALID_STAT(*psbuf)) {
6436 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6439 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6440 !VALID_STAT_OF_DIR(*psbuf)) {
6441 return NT_STATUS_NOT_A_DIRECTORY;
6444 DEBUG(10,("smb_posix_unlink: %s %s\n",
6445 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6448 if (VALID_STAT_OF_DIR(*psbuf)) {
6449 status = open_directory(conn, req,
6453 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6456 FILE_FLAG_POSIX_SEMANTICS|0777,
6461 status = open_file_ntcreate(conn, req,
6465 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6468 FILE_FLAG_POSIX_SEMANTICS|0777,
6469 0, /* No oplock, but break existing ones. */
6474 if (!NT_STATUS_IS_OK(status)) {
6479 * Don't lie to client. If we can't really delete due to
6480 * non-POSIX opens return SHARING_VIOLATION.
6483 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6486 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6487 "lock for file %s\n", fsp->fsp_name));
6488 close_file(fsp, NORMAL_CLOSE);
6489 return NT_STATUS_INVALID_PARAMETER;
6493 * See if others still have the file open. If this is the case, then
6494 * don't delete. If all opens are POSIX delete we can set the delete
6495 * on close disposition.
6497 for (i=0; i<lck->num_share_modes; i++) {
6498 struct share_mode_entry *e = &lck->share_modes[i];
6499 if (is_valid_share_mode_entry(e)) {
6500 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6503 /* Fail with sharing violation. */
6504 close_file(fsp, NORMAL_CLOSE);
6506 return NT_STATUS_SHARING_VIOLATION;
6511 * Set the delete on close.
6513 status = smb_set_file_disposition_info(conn,
6520 if (!NT_STATUS_IS_OK(status)) {
6521 close_file(fsp, NORMAL_CLOSE);
6526 return close_file(fsp, NORMAL_CLOSE);
6529 /****************************************************************************
6530 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6531 ****************************************************************************/
6533 static void call_trans2setfilepathinfo(connection_struct *conn,
6534 struct smb_request *req,
6535 unsigned int tran_call,
6536 char **pparams, int total_params,
6537 char **ppdata, int total_data,
6538 unsigned int max_data_bytes)
6540 char *params = *pparams;
6541 char *pdata = *ppdata;
6543 SMB_STRUCT_STAT sbuf;
6545 files_struct *fsp = NULL;
6546 NTSTATUS status = NT_STATUS_OK;
6547 int data_return_size = 0;
6548 TALLOC_CTX *ctx = talloc_tos();
6551 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6557 if (tran_call == TRANSACT2_SETFILEINFO) {
6558 if (total_params < 4) {
6559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6563 fsp = file_fsp(SVAL(params,0));
6564 /* Basic check for non-null fsp. */
6565 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6568 info_level = SVAL(params,2);
6570 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6572 reply_nterror(req, NT_STATUS_NO_MEMORY);
6576 if(fsp->is_directory || fsp->fh->fd == -1) {
6578 * This is actually a SETFILEINFO on a directory
6579 * handle (returned from an NT SMB). NT5.0 seems
6580 * to do this call. JRA.
6582 if (INFO_LEVEL_IS_UNIX(info_level)) {
6583 /* Always do lstat for UNIX calls. */
6584 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6585 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6586 reply_unixerror(req,ERRDOS,ERRbadpath);
6590 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6591 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6592 reply_unixerror(req,ERRDOS,ERRbadpath);
6596 } else if (fsp->print_file) {
6598 * Doing a DELETE_ON_CLOSE should cancel a print job.
6600 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6601 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6603 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6606 send_trans2_replies(conn, req, params, 2,
6611 reply_unixerror(req, ERRDOS, ERRbadpath);
6616 * Original code - this is an open file.
6618 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6622 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6623 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6624 reply_unixerror(req, ERRDOS, ERRbadfid);
6630 if (total_params < 7) {
6631 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6635 info_level = SVAL(params,0);
6636 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6637 total_params - 6, STR_TERMINATE,
6639 if (!NT_STATUS_IS_OK(status)) {
6640 reply_nterror(req, status);
6644 status = resolve_dfspath(ctx, conn,
6645 req->flags2 & FLAGS2_DFS_PATHNAMES,
6648 if (!NT_STATUS_IS_OK(status)) {
6649 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6650 reply_botherror(req,
6651 NT_STATUS_PATH_NOT_COVERED,
6652 ERRSRV, ERRbadpath);
6655 reply_nterror(req, status);
6659 status = unix_convert(ctx, conn, fname, False,
6660 &fname, NULL, &sbuf);
6661 if (!NT_STATUS_IS_OK(status)) {
6662 reply_nterror(req, status);
6666 status = check_name(conn, fname);
6667 if (!NT_STATUS_IS_OK(status)) {
6668 reply_nterror(req, status);
6672 if (INFO_LEVEL_IS_UNIX(info_level)) {
6674 * For CIFS UNIX extensions the target name may not exist.
6677 /* Always do lstat for UNIX calls. */
6678 SMB_VFS_LSTAT(conn,fname,&sbuf);
6680 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6681 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6682 reply_unixerror(req, ERRDOS, ERRbadpath);
6687 if (!CAN_WRITE(conn)) {
6688 reply_doserror(req, ERRSRV, ERRaccess);
6692 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6693 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6697 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6698 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6700 /* Realloc the parameter size */
6701 *pparams = (char *)SMB_REALLOC(*pparams,2);
6702 if (*pparams == NULL) {
6703 reply_nterror(req, NT_STATUS_NO_MEMORY);
6710 switch (info_level) {
6712 case SMB_INFO_STANDARD:
6714 status = smb_set_info_standard(conn,
6723 case SMB_INFO_SET_EA:
6725 status = smb_info_set_ea(conn,
6733 case SMB_SET_FILE_BASIC_INFO:
6734 case SMB_FILE_BASIC_INFORMATION:
6736 status = smb_set_file_basic_info(conn,
6745 case SMB_FILE_ALLOCATION_INFORMATION:
6746 case SMB_SET_FILE_ALLOCATION_INFO:
6748 status = smb_set_file_allocation_info(conn, req,
6757 case SMB_FILE_END_OF_FILE_INFORMATION:
6758 case SMB_SET_FILE_END_OF_FILE_INFO:
6760 status = smb_set_file_end_of_file_info(conn, req,
6769 case SMB_FILE_DISPOSITION_INFORMATION:
6770 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6773 /* JRA - We used to just ignore this on a path ?
6774 * Shouldn't this be invalid level on a pathname
6777 if (tran_call != TRANSACT2_SETFILEINFO) {
6778 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6781 status = smb_set_file_disposition_info(conn,
6790 case SMB_FILE_POSITION_INFORMATION:
6792 status = smb_file_position_information(conn,
6799 /* From tridge Samba4 :
6800 * MODE_INFORMATION in setfileinfo (I have no
6801 * idea what "mode information" on a file is - it takes a value of 0,
6802 * 2, 4 or 6. What could it be?).
6805 case SMB_FILE_MODE_INFORMATION:
6807 status = smb_file_mode_information(conn,
6814 * CIFS UNIX extensions.
6817 case SMB_SET_FILE_UNIX_BASIC:
6819 status = smb_set_file_unix_basic(conn, req,
6828 case SMB_SET_FILE_UNIX_INFO2:
6830 status = smb_set_file_unix_info2(conn, req,
6839 case SMB_SET_FILE_UNIX_LINK:
6841 if (tran_call != TRANSACT2_SETPATHINFO) {
6842 /* We must have a pathname for this. */
6843 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6846 status = smb_set_file_unix_link(conn, req, pdata,
6851 case SMB_SET_FILE_UNIX_HLINK:
6853 if (tran_call != TRANSACT2_SETPATHINFO) {
6854 /* We must have a pathname for this. */
6855 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6858 status = smb_set_file_unix_hlink(conn, req,
6864 case SMB_FILE_RENAME_INFORMATION:
6866 status = smb_file_rename_information(conn, req,
6872 #if defined(HAVE_POSIX_ACLS)
6873 case SMB_SET_POSIX_ACL:
6875 status = smb_set_posix_acl(conn,
6885 case SMB_SET_POSIX_LOCK:
6887 if (tran_call != TRANSACT2_SETFILEINFO) {
6888 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6891 status = smb_set_posix_lock(conn, req,
6892 pdata, total_data, fsp);
6896 case SMB_POSIX_PATH_OPEN:
6898 if (tran_call != TRANSACT2_SETPATHINFO) {
6899 /* We must have a pathname for this. */
6900 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6904 status = smb_posix_open(conn, req,
6913 case SMB_POSIX_PATH_UNLINK:
6915 if (tran_call != TRANSACT2_SETPATHINFO) {
6916 /* We must have a pathname for this. */
6917 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6921 status = smb_posix_unlink(conn, req,
6930 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6935 if (!NT_STATUS_IS_OK(status)) {
6936 if (open_was_deferred(req->mid)) {
6937 /* We have re-scheduled this call. */
6940 if (blocking_lock_was_deferred(req->mid)) {
6941 /* We have re-scheduled this call. */
6944 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6945 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6946 ERRSRV, ERRbadpath);
6949 if (info_level == SMB_POSIX_PATH_OPEN) {
6950 reply_openerror(req, status);
6954 reply_nterror(req, status);
6959 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6965 /****************************************************************************
6966 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6967 ****************************************************************************/
6969 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6970 char **pparams, int total_params,
6971 char **ppdata, int total_data,
6972 unsigned int max_data_bytes)
6974 char *params = *pparams;
6975 char *pdata = *ppdata;
6976 char *directory = NULL;
6977 SMB_STRUCT_STAT sbuf;
6978 NTSTATUS status = NT_STATUS_OK;
6979 struct ea_list *ea_list = NULL;
6980 TALLOC_CTX *ctx = talloc_tos();
6982 if (!CAN_WRITE(conn)) {
6983 reply_doserror(req, ERRSRV, ERRaccess);
6987 if (total_params < 5) {
6988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6992 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6993 total_params - 4, STR_TERMINATE,
6995 if (!NT_STATUS_IS_OK(status)) {
6996 reply_nterror(req, status);
7000 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7002 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7003 if (!NT_STATUS_IS_OK(status)) {
7004 reply_nterror(req, status);
7008 status = check_name(conn, directory);
7009 if (!NT_STATUS_IS_OK(status)) {
7010 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7011 reply_nterror(req, status);
7015 /* Any data in this call is an EA list. */
7016 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7017 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7022 * OS/2 workplace shell seems to send SET_EA requests of "null"
7023 * length (4 bytes containing IVAL 4).
7024 * They seem to have no effect. Bug #3212. JRA.
7027 if (total_data != 4) {
7028 if (total_data < 10) {
7029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7033 if (IVAL(pdata,0) > total_data) {
7034 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7035 IVAL(pdata,0), (unsigned int)total_data));
7036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7040 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7043 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7046 } else if (IVAL(pdata,0) != 4) {
7047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7051 status = create_directory(conn, req, directory);
7053 if (!NT_STATUS_IS_OK(status)) {
7054 reply_nterror(req, status);
7058 /* Try and set any given EA. */
7060 status = set_ea(conn, NULL, directory, ea_list);
7061 if (!NT_STATUS_IS_OK(status)) {
7062 reply_nterror(req, status);
7067 /* Realloc the parameter and data sizes */
7068 *pparams = (char *)SMB_REALLOC(*pparams,2);
7069 if(*pparams == NULL) {
7070 reply_nterror(req, NT_STATUS_NO_MEMORY);
7077 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7082 /****************************************************************************
7083 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7084 We don't actually do this - we just send a null response.
7085 ****************************************************************************/
7087 static void call_trans2findnotifyfirst(connection_struct *conn,
7088 struct smb_request *req,
7089 char **pparams, int total_params,
7090 char **ppdata, int total_data,
7091 unsigned int max_data_bytes)
7093 static uint16 fnf_handle = 257;
7094 char *params = *pparams;
7097 if (total_params < 6) {
7098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7102 info_level = SVAL(params,4);
7103 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7105 switch (info_level) {
7110 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7114 /* Realloc the parameter and data sizes */
7115 *pparams = (char *)SMB_REALLOC(*pparams,6);
7116 if (*pparams == NULL) {
7117 reply_nterror(req, NT_STATUS_NO_MEMORY);
7122 SSVAL(params,0,fnf_handle);
7123 SSVAL(params,2,0); /* No changes */
7124 SSVAL(params,4,0); /* No EA errors */
7131 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7136 /****************************************************************************
7137 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7138 changes). Currently this does nothing.
7139 ****************************************************************************/
7141 static void call_trans2findnotifynext(connection_struct *conn,
7142 struct smb_request *req,
7143 char **pparams, int total_params,
7144 char **ppdata, int total_data,
7145 unsigned int max_data_bytes)
7147 char *params = *pparams;
7149 DEBUG(3,("call_trans2findnotifynext\n"));
7151 /* Realloc the parameter and data sizes */
7152 *pparams = (char *)SMB_REALLOC(*pparams,4);
7153 if (*pparams == NULL) {
7154 reply_nterror(req, NT_STATUS_NO_MEMORY);
7159 SSVAL(params,0,0); /* No changes */
7160 SSVAL(params,2,0); /* No EA errors */
7162 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7167 /****************************************************************************
7168 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7169 ****************************************************************************/
7171 static void call_trans2getdfsreferral(connection_struct *conn,
7172 struct smb_request *req,
7173 char **pparams, int total_params,
7174 char **ppdata, int total_data,
7175 unsigned int max_data_bytes)
7177 char *params = *pparams;
7178 char *pathname = NULL;
7180 int max_referral_level;
7181 NTSTATUS status = NT_STATUS_OK;
7182 TALLOC_CTX *ctx = talloc_tos();
7184 DEBUG(10,("call_trans2getdfsreferral\n"));
7186 if (total_params < 3) {
7187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7191 max_referral_level = SVAL(params,0);
7193 if(!lp_host_msdfs()) {
7194 reply_doserror(req, ERRDOS, ERRbadfunc);
7198 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7199 total_params - 2, STR_TERMINATE);
7201 reply_nterror(req, NT_STATUS_NOT_FOUND);
7204 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7205 ppdata,&status)) < 0) {
7206 reply_nterror(req, status);
7210 SSVAL(req->inbuf, smb_flg2,
7211 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7212 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7217 #define LMCAT_SPL 0x53
7218 #define LMFUNC_GETJOBID 0x60
7220 /****************************************************************************
7221 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7222 ****************************************************************************/
7224 static void call_trans2ioctl(connection_struct *conn,
7225 struct smb_request *req,
7226 char **pparams, int total_params,
7227 char **ppdata, int total_data,
7228 unsigned int max_data_bytes)
7230 char *pdata = *ppdata;
7231 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7233 /* check for an invalid fid before proceeding */
7236 reply_doserror(req, ERRDOS, ERRbadfid);
7240 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7241 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7242 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7243 if (*ppdata == NULL) {
7244 reply_nterror(req, NT_STATUS_NO_MEMORY);
7249 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7250 CAN ACCEPT THIS IN UNICODE. JRA. */
7252 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7253 srvstr_push(pdata, req->flags2, pdata + 2,
7254 global_myname(), 15,
7255 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7256 srvstr_push(pdata, req->flags2, pdata+18,
7257 lp_servicename(SNUM(conn)), 13,
7258 STR_ASCII|STR_TERMINATE); /* Service name */
7259 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7264 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7265 reply_doserror(req, ERRSRV, ERRerror);
7268 /****************************************************************************
7269 Reply to a SMBfindclose (stop trans2 directory search).
7270 ****************************************************************************/
7272 void reply_findclose(struct smb_request *req)
7276 START_PROFILE(SMBfindclose);
7279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7280 END_PROFILE(SMBfindclose);
7284 dptr_num = SVALS(req->inbuf,smb_vwv0);
7286 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7288 dptr_close(&dptr_num);
7290 reply_outbuf(req, 0, 0);
7292 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7294 END_PROFILE(SMBfindclose);
7298 /****************************************************************************
7299 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7300 ****************************************************************************/
7302 void reply_findnclose(struct smb_request *req)
7306 START_PROFILE(SMBfindnclose);
7309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7310 END_PROFILE(SMBfindnclose);
7314 dptr_num = SVAL(req->inbuf,smb_vwv0);
7316 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7318 /* We never give out valid handles for a
7319 findnotifyfirst - so any dptr_num is ok here.
7322 reply_outbuf(req, 0, 0);
7324 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7326 END_PROFILE(SMBfindnclose);
7330 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7331 struct trans_state *state)
7333 if (Protocol >= PROTOCOL_NT1) {
7334 req->flags2 |= 0x40; /* IS_LONG_NAME */
7335 SSVAL(req->inbuf,smb_flg2,req->flags2);
7338 if (conn->encrypt_level == Required && !req->encrypted) {
7339 if (state->call != TRANSACT2_QFSINFO &&
7340 state->call != TRANSACT2_SETFSINFO) {
7341 DEBUG(0,("handle_trans2: encryption required "
7343 (unsigned int)state->call));
7344 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7349 /* Now we must call the relevant TRANS2 function */
7350 switch(state->call) {
7351 case TRANSACT2_OPEN:
7353 START_PROFILE(Trans2_open);
7354 call_trans2open(conn, req,
7355 &state->param, state->total_param,
7356 &state->data, state->total_data,
7357 state->max_data_return);
7358 END_PROFILE(Trans2_open);
7362 case TRANSACT2_FINDFIRST:
7364 START_PROFILE(Trans2_findfirst);
7365 call_trans2findfirst(conn, req,
7366 &state->param, state->total_param,
7367 &state->data, state->total_data,
7368 state->max_data_return);
7369 END_PROFILE(Trans2_findfirst);
7373 case TRANSACT2_FINDNEXT:
7375 START_PROFILE(Trans2_findnext);
7376 call_trans2findnext(conn, req,
7377 &state->param, state->total_param,
7378 &state->data, state->total_data,
7379 state->max_data_return);
7380 END_PROFILE(Trans2_findnext);
7384 case TRANSACT2_QFSINFO:
7386 START_PROFILE(Trans2_qfsinfo);
7387 call_trans2qfsinfo(conn, req,
7388 &state->param, state->total_param,
7389 &state->data, state->total_data,
7390 state->max_data_return);
7391 END_PROFILE(Trans2_qfsinfo);
7395 case TRANSACT2_SETFSINFO:
7397 START_PROFILE(Trans2_setfsinfo);
7398 call_trans2setfsinfo(conn, req,
7399 &state->param, state->total_param,
7400 &state->data, state->total_data,
7401 state->max_data_return);
7402 END_PROFILE(Trans2_setfsinfo);
7406 case TRANSACT2_QPATHINFO:
7407 case TRANSACT2_QFILEINFO:
7409 START_PROFILE(Trans2_qpathinfo);
7410 call_trans2qfilepathinfo(conn, req, state->call,
7411 &state->param, state->total_param,
7412 &state->data, state->total_data,
7413 state->max_data_return);
7414 END_PROFILE(Trans2_qpathinfo);
7418 case TRANSACT2_SETPATHINFO:
7419 case TRANSACT2_SETFILEINFO:
7421 START_PROFILE(Trans2_setpathinfo);
7422 call_trans2setfilepathinfo(conn, req, state->call,
7423 &state->param, state->total_param,
7424 &state->data, state->total_data,
7425 state->max_data_return);
7426 END_PROFILE(Trans2_setpathinfo);
7430 case TRANSACT2_FINDNOTIFYFIRST:
7432 START_PROFILE(Trans2_findnotifyfirst);
7433 call_trans2findnotifyfirst(conn, req,
7434 &state->param, state->total_param,
7435 &state->data, state->total_data,
7436 state->max_data_return);
7437 END_PROFILE(Trans2_findnotifyfirst);
7441 case TRANSACT2_FINDNOTIFYNEXT:
7443 START_PROFILE(Trans2_findnotifynext);
7444 call_trans2findnotifynext(conn, req,
7445 &state->param, state->total_param,
7446 &state->data, state->total_data,
7447 state->max_data_return);
7448 END_PROFILE(Trans2_findnotifynext);
7452 case TRANSACT2_MKDIR:
7454 START_PROFILE(Trans2_mkdir);
7455 call_trans2mkdir(conn, req,
7456 &state->param, state->total_param,
7457 &state->data, state->total_data,
7458 state->max_data_return);
7459 END_PROFILE(Trans2_mkdir);
7463 case TRANSACT2_GET_DFS_REFERRAL:
7465 START_PROFILE(Trans2_get_dfs_referral);
7466 call_trans2getdfsreferral(conn, req,
7467 &state->param, state->total_param,
7468 &state->data, state->total_data,
7469 state->max_data_return);
7470 END_PROFILE(Trans2_get_dfs_referral);
7474 case TRANSACT2_IOCTL:
7476 START_PROFILE(Trans2_ioctl);
7477 call_trans2ioctl(conn, req,
7478 &state->param, state->total_param,
7479 &state->data, state->total_data,
7480 state->max_data_return);
7481 END_PROFILE(Trans2_ioctl);
7486 /* Error in request */
7487 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7488 reply_doserror(req, ERRSRV,ERRerror);
7492 /****************************************************************************
7493 Reply to a SMBtrans2.
7494 ****************************************************************************/
7496 void reply_trans2(struct smb_request *req)
7498 connection_struct *conn = req->conn;
7503 unsigned int tran_call;
7505 unsigned int av_size;
7506 struct trans_state *state;
7509 START_PROFILE(SMBtrans2);
7511 if (req->wct < 14) {
7512 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7513 END_PROFILE(SMBtrans2);
7517 dsoff = SVAL(req->inbuf, smb_dsoff);
7518 dscnt = SVAL(req->inbuf, smb_dscnt);
7519 psoff = SVAL(req->inbuf, smb_psoff);
7520 pscnt = SVAL(req->inbuf, smb_pscnt);
7521 tran_call = SVAL(req->inbuf, smb_setup0);
7522 size = smb_len(req->inbuf) + 4;
7523 av_size = smb_len(req->inbuf);
7525 result = allow_new_trans(conn->pending_trans, req->mid);
7526 if (!NT_STATUS_IS_OK(result)) {
7527 DEBUG(2, ("Got invalid trans2 request: %s\n",
7528 nt_errstr(result)));
7529 reply_nterror(req, result);
7530 END_PROFILE(SMBtrans2);
7535 switch (tran_call) {
7536 /* List the allowed trans2 calls on IPC$ */
7537 case TRANSACT2_OPEN:
7538 case TRANSACT2_GET_DFS_REFERRAL:
7539 case TRANSACT2_QFILEINFO:
7540 case TRANSACT2_QFSINFO:
7541 case TRANSACT2_SETFSINFO:
7544 reply_doserror(req, ERRSRV, ERRaccess);
7545 END_PROFILE(SMBtrans2);
7550 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7551 DEBUG(0, ("talloc failed\n"));
7552 reply_nterror(req, NT_STATUS_NO_MEMORY);
7553 END_PROFILE(SMBtrans2);
7557 state->cmd = SMBtrans2;
7559 state->mid = req->mid;
7560 state->vuid = req->vuid;
7561 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7562 state->setup = NULL;
7563 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7564 state->param = NULL;
7565 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7567 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7568 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7569 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7570 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7571 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7573 state->call = tran_call;
7575 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7576 is so as a sanity check */
7577 if (state->setup_count != 1) {
7579 * Need to have rc=0 for ioctl to get job id for OS/2.
7580 * Network printing will fail if function is not successful.
7581 * Similar function in reply.c will be used if protocol
7582 * is LANMAN1.0 instead of LM1.2X002.
7583 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7584 * outbuf doesn't have to be set(only job id is used).
7586 if ( (state->setup_count == 4)
7587 && (tran_call == TRANSACT2_IOCTL)
7588 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7589 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7590 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7592 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7593 DEBUG(2,("Transaction is %d\n",tran_call));
7595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7596 END_PROFILE(SMBtrans2);
7601 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7604 if (state->total_data) {
7605 /* Can't use talloc here, the core routines do realloc on the
7606 * params and data. */
7607 state->data = (char *)SMB_MALLOC(state->total_data);
7608 if (state->data == NULL) {
7609 DEBUG(0,("reply_trans2: data malloc fail for %u "
7610 "bytes !\n", (unsigned int)state->total_data));
7612 reply_nterror(req, NT_STATUS_NO_MEMORY);
7613 END_PROFILE(SMBtrans2);
7617 if (dscnt > state->total_data ||
7618 dsoff+dscnt < dsoff) {
7622 if (dsoff > av_size ||
7624 dsoff+dscnt > av_size) {
7628 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7631 if (state->total_param) {
7632 /* Can't use talloc here, the core routines do realloc on the
7633 * params and data. */
7634 state->param = (char *)SMB_MALLOC(state->total_param);
7635 if (state->param == NULL) {
7636 DEBUG(0,("reply_trans: param malloc fail for %u "
7637 "bytes !\n", (unsigned int)state->total_param));
7638 SAFE_FREE(state->data);
7640 reply_nterror(req, NT_STATUS_NO_MEMORY);
7641 END_PROFILE(SMBtrans2);
7645 if (pscnt > state->total_param ||
7646 psoff+pscnt < psoff) {
7650 if (psoff > av_size ||
7652 psoff+pscnt > av_size) {
7656 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7659 state->received_data = dscnt;
7660 state->received_param = pscnt;
7662 if ((state->received_param == state->total_param) &&
7663 (state->received_data == state->total_data)) {
7665 handle_trans2(conn, req, state);
7667 SAFE_FREE(state->data);
7668 SAFE_FREE(state->param);
7670 END_PROFILE(SMBtrans2);
7674 DLIST_ADD(conn->pending_trans, state);
7676 /* We need to send an interim response then receive the rest
7677 of the parameter/data bytes */
7678 reply_outbuf(req, 0, 0);
7679 show_msg((char *)req->outbuf);
7680 END_PROFILE(SMBtrans2);
7685 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7686 SAFE_FREE(state->data);
7687 SAFE_FREE(state->param);
7689 END_PROFILE(SMBtrans2);
7690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7694 /****************************************************************************
7695 Reply to a SMBtranss2
7696 ****************************************************************************/
7698 void reply_transs2(struct smb_request *req)
7700 connection_struct *conn = req->conn;
7701 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7702 struct trans_state *state;
7704 unsigned int av_size;
7706 START_PROFILE(SMBtranss2);
7708 show_msg((char *)req->inbuf);
7711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7712 END_PROFILE(SMBtranss2);
7716 size = smb_len(req->inbuf)+4;
7717 av_size = smb_len(req->inbuf);
7719 for (state = conn->pending_trans; state != NULL;
7720 state = state->next) {
7721 if (state->mid == req->mid) {
7726 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7727 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7728 END_PROFILE(SMBtranss2);
7732 /* Revise state->total_param and state->total_data in case they have
7733 changed downwards */
7735 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7736 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7737 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7738 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7740 pcnt = SVAL(req->inbuf, smb_spscnt);
7741 poff = SVAL(req->inbuf, smb_spsoff);
7742 pdisp = SVAL(req->inbuf, smb_spsdisp);
7744 dcnt = SVAL(req->inbuf, smb_sdscnt);
7745 doff = SVAL(req->inbuf, smb_sdsoff);
7746 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7748 state->received_param += pcnt;
7749 state->received_data += dcnt;
7751 if ((state->received_data > state->total_data) ||
7752 (state->received_param > state->total_param))
7756 if (pdisp > state->total_param ||
7757 pcnt > state->total_param ||
7758 pdisp+pcnt > state->total_param ||
7759 pdisp+pcnt < pdisp) {
7763 if (poff > av_size ||
7765 poff+pcnt > av_size ||
7770 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7775 if (ddisp > state->total_data ||
7776 dcnt > state->total_data ||
7777 ddisp+dcnt > state->total_data ||
7778 ddisp+dcnt < ddisp) {
7782 if (ddisp > av_size ||
7784 ddisp+dcnt > av_size ||
7785 ddisp+dcnt < ddisp) {
7789 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7793 if ((state->received_param < state->total_param) ||
7794 (state->received_data < state->total_data)) {
7795 END_PROFILE(SMBtranss2);
7800 * construct_reply_common will copy smb_com from inbuf to
7801 * outbuf. SMBtranss2 is wrong here.
7803 SCVAL(req->inbuf,smb_com,SMBtrans2);
7805 handle_trans2(conn, req, state);
7807 DLIST_REMOVE(conn->pending_trans, state);
7808 SAFE_FREE(state->data);
7809 SAFE_FREE(state->param);
7812 END_PROFILE(SMBtranss2);
7817 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7818 DLIST_REMOVE(conn->pending_trans, state);
7819 SAFE_FREE(state->data);
7820 SAFE_FREE(state->param);
7822 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7823 END_PROFILE(SMBtranss2);