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 /* useable_space can never be more than max_send minus the alignment offset. */
742 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
744 while (params_to_send || data_to_send) {
745 /* Calculate whether we will totally or partially fill this packet */
747 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
749 /* We can never send more than useable_space */
751 * Note that 'useable_space' does not include the alignment offsets,
752 * but we must include the alignment offsets in the calculation of
753 * the length of the data we send over the wire, as the alignment offsets
754 * are sent here. Fix from Marc_Jacobsen@hp.com.
757 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
759 reply_outbuf(req, 10, total_sent_thistime);
761 /* Set total params and data to be sent */
762 SSVAL(req->outbuf,smb_tprcnt,paramsize);
763 SSVAL(req->outbuf,smb_tdrcnt,datasize);
765 /* Calculate how many parameters and data we can fit into
766 * this packet. Parameters get precedence
769 params_sent_thistime = MIN(params_to_send,useable_space);
770 data_sent_thistime = useable_space - params_sent_thistime;
771 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
773 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
775 /* smb_proff is the offset from the start of the SMB header to the
776 parameter bytes, however the first 4 bytes of outbuf are
777 the Netbios over TCP header. Thus use smb_base() to subtract
778 them from the calculation */
780 SSVAL(req->outbuf,smb_proff,
781 ((smb_buf(req->outbuf)+alignment_offset)
782 - smb_base(req->outbuf)));
784 if(params_sent_thistime == 0)
785 SSVAL(req->outbuf,smb_prdisp,0);
787 /* Absolute displacement of param bytes sent in this packet */
788 SSVAL(req->outbuf,smb_prdisp,pp - params);
790 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
791 if(data_sent_thistime == 0) {
792 SSVAL(req->outbuf,smb_droff,0);
793 SSVAL(req->outbuf,smb_drdisp, 0);
795 /* The offset of the data bytes is the offset of the
796 parameter bytes plus the number of parameters being sent this time */
797 SSVAL(req->outbuf, smb_droff,
798 ((smb_buf(req->outbuf)+alignment_offset)
799 - smb_base(req->outbuf))
800 + params_sent_thistime + data_alignment_offset);
801 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
804 /* Initialize the padding for alignment */
806 if (alignment_offset != 0) {
807 memset(smb_buf(req->outbuf), 0, alignment_offset);
810 /* Copy the param bytes into the packet */
812 if(params_sent_thistime) {
813 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
814 params_sent_thistime);
817 /* Copy in the data bytes */
818 if(data_sent_thistime) {
819 if (data_alignment_offset != 0) {
820 memset((smb_buf(req->outbuf)+alignment_offset+
821 params_sent_thistime), 0,
822 data_alignment_offset);
824 memcpy(smb_buf(req->outbuf)+alignment_offset
825 +params_sent_thistime+data_alignment_offset,
826 pd,data_sent_thistime);
829 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
830 params_sent_thistime, data_sent_thistime, useable_space));
831 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
832 params_to_send, data_to_send, paramsize, datasize));
835 error_packet_set((char *)req->outbuf,
836 ERRDOS,ERRbufferoverflow,
837 STATUS_BUFFER_OVERFLOW,
841 /* Send the packet */
842 show_msg((char *)req->outbuf);
843 if (!srv_send_smb(smbd_server_fd(),
845 IS_CONN_ENCRYPTED(conn)))
846 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
848 TALLOC_FREE(req->outbuf);
850 pp += params_sent_thistime;
851 pd += data_sent_thistime;
853 params_to_send -= params_sent_thistime;
854 data_to_send -= data_sent_thistime;
857 if(params_to_send < 0 || data_to_send < 0) {
858 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
859 params_to_send, data_to_send));
867 /****************************************************************************
868 Reply to a TRANSACT2_OPEN.
869 ****************************************************************************/
871 static void call_trans2open(connection_struct *conn,
872 struct smb_request *req,
873 char **pparams, int total_params,
874 char **ppdata, int total_data,
875 unsigned int max_data_bytes)
877 char *params = *pparams;
878 char *pdata = *ppdata;
883 bool return_additional_info;
894 SMB_STRUCT_STAT sbuf;
897 struct ea_list *ea_list = NULL;
902 uint32 create_disposition;
903 uint32 create_options = 0;
904 TALLOC_CTX *ctx = talloc_tos();
907 * Ensure we have enough parameters to perform the operation.
910 if (total_params < 29) {
911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
915 flags = SVAL(params, 0);
916 deny_mode = SVAL(params, 2);
917 open_attr = SVAL(params,6);
918 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
919 if (oplock_request) {
920 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
924 return_additional_info = BITSETW(params,0);
925 open_sattr = SVAL(params, 4);
926 open_time = make_unix_date3(params+8);
928 open_ofun = SVAL(params,12);
929 open_size = IVAL(params,14);
933 reply_doserror(req, ERRSRV, ERRaccess);
937 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
938 total_params - 28, STR_TERMINATE,
940 if (!NT_STATUS_IS_OK(status)) {
941 reply_nterror(req, status);
945 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
946 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
947 (unsigned int)open_ofun, open_size));
949 if (open_ofun == 0) {
950 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
954 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
959 reply_doserror(req, ERRDOS, ERRbadaccess);
963 /* Any data in this call is an EA list. */
964 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
965 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
969 if (total_data != 4) {
970 if (total_data < 10) {
971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
975 if (IVAL(pdata,0) > total_data) {
976 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
977 IVAL(pdata,0), (unsigned int)total_data));
978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 ea_list = read_ea_list(talloc_tos(), pdata + 4,
985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
988 } else if (IVAL(pdata,0) != 4) {
989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
993 status = create_file(conn, /* conn */
995 0, /* root_dir_fid */
997 access_mask, /* access_mask */
998 share_mode, /* share_access */
999 create_disposition, /* create_disposition*/
1000 create_options, /* create_options */
1001 open_attr, /* file_attributes */
1002 oplock_request, /* oplock_request */
1003 open_size, /* allocation_size */
1005 ea_list, /* ea_list */
1007 &smb_action, /* pinfo */
1010 if (!NT_STATUS_IS_OK(status)) {
1011 if (open_was_deferred(req->mid)) {
1012 /* We have re-scheduled this call. */
1015 reply_openerror(req, status);
1019 size = get_file_size(sbuf);
1020 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1021 mtime = sbuf.st_mtime;
1022 inode = sbuf.st_ino;
1024 close_file(fsp,ERROR_CLOSE);
1025 reply_doserror(req, ERRDOS,ERRnoaccess);
1029 /* Realloc the size of parameters and data we will return */
1030 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1031 if(*pparams == NULL ) {
1032 reply_nterror(req, NT_STATUS_NO_MEMORY);
1037 SSVAL(params,0,fsp->fnum);
1038 SSVAL(params,2,fattr);
1039 srv_put_dos_date2(params,4, mtime);
1040 SIVAL(params,8, (uint32)size);
1041 SSVAL(params,12,deny_mode);
1042 SSVAL(params,14,0); /* open_type - file or directory. */
1043 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1045 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1046 smb_action |= EXTENDED_OPLOCK_GRANTED;
1049 SSVAL(params,18,smb_action);
1052 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1054 SIVAL(params,20,inode);
1055 SSVAL(params,24,0); /* Padding. */
1057 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1058 SIVAL(params, 26, ea_size);
1060 SIVAL(params, 26, 0);
1063 /* Send the required number of replies */
1064 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1067 /*********************************************************
1068 Routine to check if a given string matches exactly.
1069 as a special case a mask of "." does NOT match. That
1070 is required for correct wildcard semantics
1071 Case can be significant or not.
1072 **********************************************************/
1074 static bool exact_match(connection_struct *conn,
1078 if (mask[0] == '.' && mask[1] == 0)
1080 if (conn->case_sensitive)
1081 return strcmp(str,mask)==0;
1082 if (StrCaseCmp(str,mask) != 0) {
1085 if (dptr_has_wild(conn->dirptr)) {
1091 /****************************************************************************
1092 Return the filetype for UNIX extensions.
1093 ****************************************************************************/
1095 static uint32 unix_filetype(mode_t mode)
1098 return UNIX_TYPE_FILE;
1099 else if(S_ISDIR(mode))
1100 return UNIX_TYPE_DIR;
1102 else if(S_ISLNK(mode))
1103 return UNIX_TYPE_SYMLINK;
1106 else if(S_ISCHR(mode))
1107 return UNIX_TYPE_CHARDEV;
1110 else if(S_ISBLK(mode))
1111 return UNIX_TYPE_BLKDEV;
1114 else if(S_ISFIFO(mode))
1115 return UNIX_TYPE_FIFO;
1118 else if(S_ISSOCK(mode))
1119 return UNIX_TYPE_SOCKET;
1122 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1123 return UNIX_TYPE_UNKNOWN;
1126 /****************************************************************************
1127 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1128 ****************************************************************************/
1130 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1132 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1133 SMB_STRUCT_STAT *psbuf,
1135 enum perm_type ptype,
1140 if (perms == SMB_MODE_NO_CHANGE) {
1141 if (!VALID_STAT(*psbuf)) {
1142 return NT_STATUS_INVALID_PARAMETER;
1144 *ret_perms = psbuf->st_mode;
1145 return NT_STATUS_OK;
1149 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1150 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1151 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1152 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1153 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1154 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1155 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1156 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1157 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1159 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1162 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1165 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1170 /* Apply mode mask */
1171 ret &= lp_create_mask(SNUM(conn));
1172 /* Add in force bits */
1173 ret |= lp_force_create_mode(SNUM(conn));
1176 ret &= lp_dir_mask(SNUM(conn));
1177 /* Add in force bits */
1178 ret |= lp_force_dir_mode(SNUM(conn));
1180 case PERM_EXISTING_FILE:
1181 /* Apply mode mask */
1182 ret &= lp_security_mask(SNUM(conn));
1183 /* Add in force bits */
1184 ret |= lp_force_security_mode(SNUM(conn));
1186 case PERM_EXISTING_DIR:
1187 /* Apply mode mask */
1188 ret &= lp_dir_security_mask(SNUM(conn));
1189 /* Add in force bits */
1190 ret |= lp_force_dir_security_mode(SNUM(conn));
1195 return NT_STATUS_OK;
1198 /****************************************************************************
1199 Needed to show the msdfs symlinks as directories. Modifies psbuf
1200 to be a directory if it's a msdfs link.
1201 ****************************************************************************/
1203 static bool check_msdfs_link(connection_struct *conn,
1204 const char *pathname,
1205 SMB_STRUCT_STAT *psbuf)
1207 int saved_errno = errno;
1208 if(lp_host_msdfs() &&
1209 lp_msdfs_root(SNUM(conn)) &&
1210 is_msdfs_link(conn, pathname, psbuf)) {
1212 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1215 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1216 errno = saved_errno;
1219 errno = saved_errno;
1224 /****************************************************************************
1225 Get a level dependent lanman2 dir entry.
1226 ****************************************************************************/
1228 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1229 connection_struct *conn,
1231 const char *path_mask,
1234 int requires_resume_key,
1240 int space_remaining,
1242 bool *got_exact_match,
1243 int *last_entry_off,
1244 struct ea_list *name_list)
1248 SMB_STRUCT_STAT sbuf;
1249 const char *mask = NULL;
1250 char *pathreal = NULL;
1251 const char *fname = NULL;
1252 char *p, *q, *pdata = *ppdata;
1256 SMB_OFF_T file_size = 0;
1257 SMB_BIG_UINT allocation_size = 0;
1259 struct timespec mdate_ts, adate_ts, create_date_ts;
1260 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1262 char *last_entry_ptr;
1264 uint32 nt_extmode; /* Used for NT connections instead of mode */
1265 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1266 bool check_mangled_names = lp_manglednames(conn->params);
1267 char mangled_name[13]; /* mangled 8.3 name. */
1269 *out_of_space = False;
1270 *got_exact_match = False;
1272 ZERO_STRUCT(mdate_ts);
1273 ZERO_STRUCT(adate_ts);
1274 ZERO_STRUCT(create_date_ts);
1276 if (!conn->dirptr) {
1280 p = strrchr_m(path_mask,'/');
1283 mask = talloc_strdup(ctx,"*.*");
1293 bool ms_dfs_link = False;
1295 /* Needed if we run out of space */
1296 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1297 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1300 * Due to bugs in NT client redirectors we are not using
1301 * resume keys any more - set them to zero.
1302 * Check out the related comments in findfirst/findnext.
1308 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1309 (long)conn->dirptr,curr_dirpos));
1316 * fname may get mangled, dname is never mangled.
1317 * Whenever we're accessing the filesystem we use
1318 * pathreal which is composed from dname.
1324 /* Mangle fname if it's an illegal name. */
1325 if (mangle_must_mangle(dname,conn->params)) {
1326 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1327 continue; /* Error - couldn't mangle. */
1329 fname = mangled_name;
1332 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1333 got_match = mask_match(fname, mask, conn->case_sensitive);
1336 if(!got_match && check_mangled_names &&
1337 !mangle_is_8_3(fname, False, conn->params)) {
1339 * It turns out that NT matches wildcards against
1340 * both long *and* short names. This may explain some
1341 * of the wildcard wierdness from old DOS clients
1342 * that some people have been seeing.... JRA.
1344 /* Force the mangling into 8.3. */
1345 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1346 continue; /* Error - couldn't mangle. */
1349 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1350 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1355 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1357 if (dont_descend && !isdots) {
1363 pathreal = talloc_asprintf(ctx,
1368 pathreal = talloc_asprintf(ctx,
1378 if (INFO_LEVEL_IS_UNIX(info_level)) {
1379 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1380 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1381 pathreal,strerror(errno)));
1382 TALLOC_FREE(pathreal);
1385 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1386 /* Needed to show the msdfs symlinks as
1389 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1391 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1392 pathreal,strerror(errno)));
1393 TALLOC_FREE(pathreal);
1399 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1401 mode = dos_mode(conn,pathreal,&sbuf);
1404 if (!dir_check_ftype(conn,mode,dirtype)) {
1405 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1406 TALLOC_FREE(pathreal);
1410 if (!(mode & aDIR)) {
1411 file_size = get_file_size(sbuf);
1413 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1415 mdate_ts = get_mtimespec(&sbuf);
1416 adate_ts = get_atimespec(&sbuf);
1417 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1419 if (ask_sharemode) {
1420 struct timespec write_time_ts;
1421 struct file_id fileid;
1423 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1424 get_file_infos(fileid, NULL, &write_time_ts);
1425 if (!null_timespec(write_time_ts)) {
1426 mdate_ts = write_time_ts;
1430 if (lp_dos_filetime_resolution(SNUM(conn))) {
1431 dos_filetime_timespec(&create_date_ts);
1432 dos_filetime_timespec(&mdate_ts);
1433 dos_filetime_timespec(&adate_ts);
1436 create_date = convert_timespec_to_time_t(create_date_ts);
1437 mdate = convert_timespec_to_time_t(mdate_ts);
1438 adate = convert_timespec_to_time_t(adate_ts);
1440 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1444 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1451 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1453 switch (info_level) {
1454 case SMB_FIND_INFO_STANDARD:
1455 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1456 if(requires_resume_key) {
1460 srv_put_dos_date2(p,0,create_date);
1461 srv_put_dos_date2(p,4,adate);
1462 srv_put_dos_date2(p,8,mdate);
1463 SIVAL(p,12,(uint32)file_size);
1464 SIVAL(p,16,(uint32)allocation_size);
1468 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1469 p += ucs2_align(base_data, p, 0);
1471 len = srvstr_push(base_data, flags2, p,
1472 fname, PTR_DIFF(end_data, p),
1474 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1476 SCVAL(nameptr, -1, len - 2);
1478 SCVAL(nameptr, -1, 0);
1482 SCVAL(nameptr, -1, len - 1);
1484 SCVAL(nameptr, -1, 0);
1490 case SMB_FIND_EA_SIZE:
1491 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1492 if(requires_resume_key) {
1496 srv_put_dos_date2(p,0,create_date);
1497 srv_put_dos_date2(p,4,adate);
1498 srv_put_dos_date2(p,8,mdate);
1499 SIVAL(p,12,(uint32)file_size);
1500 SIVAL(p,16,(uint32)allocation_size);
1503 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1504 SIVAL(p,22,ea_size); /* Extended attributes */
1508 len = srvstr_push(base_data, flags2,
1509 p, fname, PTR_DIFF(end_data, p),
1510 STR_TERMINATE | STR_NOALIGN);
1511 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1524 SCVAL(nameptr,0,len);
1526 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1529 case SMB_FIND_EA_LIST:
1531 struct ea_list *file_list = NULL;
1534 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1538 if(requires_resume_key) {
1542 srv_put_dos_date2(p,0,create_date);
1543 srv_put_dos_date2(p,4,adate);
1544 srv_put_dos_date2(p,8,mdate);
1545 SIVAL(p,12,(uint32)file_size);
1546 SIVAL(p,16,(uint32)allocation_size);
1548 p += 22; /* p now points to the EA area. */
1550 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1551 name_list = ea_list_union(name_list, file_list, &ea_len);
1553 /* We need to determine if this entry will fit in the space available. */
1554 /* Max string size is 255 bytes. */
1555 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1556 /* Move the dirptr back to prev_dirpos */
1557 dptr_SeekDir(conn->dirptr, prev_dirpos);
1558 *out_of_space = True;
1559 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1560 return False; /* Not finished - just out of space */
1563 /* Push the ea_data followed by the name. */
1564 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1566 len = srvstr_push(base_data, flags2,
1567 p + 1, fname, PTR_DIFF(end_data, p+1),
1568 STR_TERMINATE | STR_NOALIGN);
1569 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1582 SCVAL(nameptr,0,len);
1584 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1588 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1589 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1590 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1592 SIVAL(p,0,reskey); p += 4;
1593 put_long_date_timespec(p,create_date_ts); p += 8;
1594 put_long_date_timespec(p,adate_ts); p += 8;
1595 put_long_date_timespec(p,mdate_ts); p += 8;
1596 put_long_date_timespec(p,mdate_ts); p += 8;
1597 SOFF_T(p,0,file_size); p += 8;
1598 SOFF_T(p,0,allocation_size); p += 8;
1599 SIVAL(p,0,nt_extmode); p += 4;
1600 q = p; p += 4; /* q is placeholder for name length. */
1602 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1603 SIVAL(p,0,ea_size); /* Extended attributes */
1606 /* Clear the short name buffer. This is
1607 * IMPORTANT as not doing so will trigger
1608 * a Win2k client bug. JRA.
1610 if (!was_8_3 && check_mangled_names) {
1611 if (!name_to_8_3(fname,mangled_name,True,
1613 /* Error - mangle failed ! */
1614 memset(mangled_name,'\0',12);
1616 mangled_name[12] = 0;
1617 len = srvstr_push(base_data, flags2,
1618 p+2, mangled_name, 24,
1619 STR_UPPER|STR_UNICODE);
1621 memset(p + 2 + len,'\0',24 - len);
1628 len = srvstr_push(base_data, flags2, p,
1629 fname, PTR_DIFF(end_data, p),
1630 STR_TERMINATE_ASCII);
1633 SIVAL(p,0,0); /* Ensure any padding is null. */
1634 len = PTR_DIFF(p, pdata);
1635 len = (len + 3) & ~3;
1640 case SMB_FIND_FILE_DIRECTORY_INFO:
1641 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1643 SIVAL(p,0,reskey); p += 4;
1644 put_long_date_timespec(p,create_date_ts); p += 8;
1645 put_long_date_timespec(p,adate_ts); p += 8;
1646 put_long_date_timespec(p,mdate_ts); p += 8;
1647 put_long_date_timespec(p,mdate_ts); p += 8;
1648 SOFF_T(p,0,file_size); p += 8;
1649 SOFF_T(p,0,allocation_size); p += 8;
1650 SIVAL(p,0,nt_extmode); p += 4;
1651 len = srvstr_push(base_data, flags2,
1652 p + 4, fname, PTR_DIFF(end_data, p+4),
1653 STR_TERMINATE_ASCII);
1656 SIVAL(p,0,0); /* Ensure any padding is null. */
1657 len = PTR_DIFF(p, pdata);
1658 len = (len + 3) & ~3;
1663 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1664 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1666 SIVAL(p,0,reskey); p += 4;
1667 put_long_date_timespec(p,create_date_ts); p += 8;
1668 put_long_date_timespec(p,adate_ts); p += 8;
1669 put_long_date_timespec(p,mdate_ts); p += 8;
1670 put_long_date_timespec(p,mdate_ts); p += 8;
1671 SOFF_T(p,0,file_size); p += 8;
1672 SOFF_T(p,0,allocation_size); p += 8;
1673 SIVAL(p,0,nt_extmode); p += 4;
1674 q = p; p += 4; /* q is placeholder for name length. */
1676 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1677 SIVAL(p,0,ea_size); /* Extended attributes */
1680 len = srvstr_push(base_data, flags2, p,
1681 fname, PTR_DIFF(end_data, p),
1682 STR_TERMINATE_ASCII);
1686 SIVAL(p,0,0); /* Ensure any padding is null. */
1687 len = PTR_DIFF(p, pdata);
1688 len = (len + 3) & ~3;
1693 case SMB_FIND_FILE_NAMES_INFO:
1694 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1696 SIVAL(p,0,reskey); p += 4;
1698 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1699 acl on a dir (tridge) */
1700 len = srvstr_push(base_data, flags2, p,
1701 fname, PTR_DIFF(end_data, p),
1702 STR_TERMINATE_ASCII);
1705 SIVAL(p,0,0); /* Ensure any padding is null. */
1706 len = PTR_DIFF(p, pdata);
1707 len = (len + 3) & ~3;
1712 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1713 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1715 SIVAL(p,0,reskey); p += 4;
1716 put_long_date_timespec(p,create_date_ts); p += 8;
1717 put_long_date_timespec(p,adate_ts); p += 8;
1718 put_long_date_timespec(p,mdate_ts); p += 8;
1719 put_long_date_timespec(p,mdate_ts); p += 8;
1720 SOFF_T(p,0,file_size); p += 8;
1721 SOFF_T(p,0,allocation_size); p += 8;
1722 SIVAL(p,0,nt_extmode); p += 4;
1723 q = p; p += 4; /* q is placeholder for name length. */
1725 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1726 SIVAL(p,0,ea_size); /* Extended attributes */
1729 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1730 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1731 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1732 len = srvstr_push(base_data, flags2, p,
1733 fname, PTR_DIFF(end_data, p),
1734 STR_TERMINATE_ASCII);
1737 SIVAL(p,0,0); /* Ensure any padding is null. */
1738 len = PTR_DIFF(p, pdata);
1739 len = (len + 3) & ~3;
1744 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1745 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1746 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1748 SIVAL(p,0,reskey); p += 4;
1749 put_long_date_timespec(p,create_date_ts); p += 8;
1750 put_long_date_timespec(p,adate_ts); p += 8;
1751 put_long_date_timespec(p,mdate_ts); p += 8;
1752 put_long_date_timespec(p,mdate_ts); p += 8;
1753 SOFF_T(p,0,file_size); p += 8;
1754 SOFF_T(p,0,allocation_size); p += 8;
1755 SIVAL(p,0,nt_extmode); p += 4;
1756 q = p; p += 4; /* q is placeholder for name length */
1758 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1759 SIVAL(p,0,ea_size); /* Extended attributes */
1762 /* Clear the short name buffer. This is
1763 * IMPORTANT as not doing so will trigger
1764 * a Win2k client bug. JRA.
1766 if (!was_8_3 && check_mangled_names) {
1767 if (!name_to_8_3(fname,mangled_name,True,
1769 /* Error - mangle failed ! */
1770 memset(mangled_name,'\0',12);
1772 mangled_name[12] = 0;
1773 len = srvstr_push(base_data, flags2,
1774 p+2, mangled_name, 24,
1775 STR_UPPER|STR_UNICODE);
1778 memset(p + 2 + len,'\0',24 - len);
1785 SSVAL(p,0,0); p += 2; /* Reserved ? */
1786 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1787 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1788 len = srvstr_push(base_data, flags2, p,
1789 fname, PTR_DIFF(end_data, p),
1790 STR_TERMINATE_ASCII);
1793 SIVAL(p,0,0); /* Ensure any padding is null. */
1794 len = PTR_DIFF(p, pdata);
1795 len = (len + 3) & ~3;
1800 /* CIFS UNIX Extension. */
1802 case SMB_FIND_FILE_UNIX:
1803 case SMB_FIND_FILE_UNIX_INFO2:
1805 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1807 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1809 if (info_level == SMB_FIND_FILE_UNIX) {
1810 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1811 p = store_file_unix_basic(conn, p,
1813 len = srvstr_push(base_data, flags2, p,
1814 fname, PTR_DIFF(end_data, p),
1817 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1818 p = store_file_unix_basic_info2(conn, p,
1822 len = srvstr_push(base_data, flags2, p, fname,
1823 PTR_DIFF(end_data, p), 0);
1824 SIVAL(nameptr, 0, len);
1828 SIVAL(p,0,0); /* Ensure any padding is null. */
1830 len = PTR_DIFF(p, pdata);
1831 len = (len + 3) & ~3;
1832 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1834 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1843 if (PTR_DIFF(p,pdata) > space_remaining) {
1844 /* Move the dirptr back to prev_dirpos */
1845 dptr_SeekDir(conn->dirptr, prev_dirpos);
1846 *out_of_space = True;
1847 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1848 return False; /* Not finished - just out of space */
1851 /* Setup the last entry pointer, as an offset from base_data */
1852 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1853 /* Advance the data pointer to the next slot */
1859 /****************************************************************************
1860 Reply to a TRANS2_FINDFIRST.
1861 ****************************************************************************/
1863 static void call_trans2findfirst(connection_struct *conn,
1864 struct smb_request *req,
1865 char **pparams, int total_params,
1866 char **ppdata, int total_data,
1867 unsigned int max_data_bytes)
1869 /* We must be careful here that we don't return more than the
1870 allowed number of data bytes. If this means returning fewer than
1871 maxentries then so be it. We assume that the redirector has
1872 enough room for the fixed number of parameter bytes it has
1874 char *params = *pparams;
1875 char *pdata = *ppdata;
1879 uint16 findfirst_flags;
1880 bool close_after_first;
1882 bool requires_resume_key;
1884 char *directory = NULL;
1885 const char *mask = NULL;
1887 int last_entry_off=0;
1891 bool finished = False;
1892 bool dont_descend = False;
1893 bool out_of_space = False;
1894 int space_remaining;
1895 bool mask_contains_wcard = False;
1896 SMB_STRUCT_STAT sbuf;
1897 struct ea_list *ea_list = NULL;
1898 NTSTATUS ntstatus = NT_STATUS_OK;
1899 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1900 TALLOC_CTX *ctx = talloc_tos();
1902 if (total_params < 13) {
1903 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1907 dirtype = SVAL(params,0);
1908 maxentries = SVAL(params,2);
1909 findfirst_flags = SVAL(params,4);
1910 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1911 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1912 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1913 info_level = SVAL(params,6);
1915 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1916 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1917 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1918 info_level, max_data_bytes));
1921 /* W2K3 seems to treat zero as 1. */
1925 switch (info_level) {
1926 case SMB_FIND_INFO_STANDARD:
1927 case SMB_FIND_EA_SIZE:
1928 case SMB_FIND_EA_LIST:
1929 case SMB_FIND_FILE_DIRECTORY_INFO:
1930 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1931 case SMB_FIND_FILE_NAMES_INFO:
1932 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1933 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1934 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1936 case SMB_FIND_FILE_UNIX:
1937 case SMB_FIND_FILE_UNIX_INFO2:
1938 if (!lp_unix_extensions()) {
1939 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1944 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1948 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1949 params+12, total_params - 12,
1950 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1951 if (!NT_STATUS_IS_OK(ntstatus)) {
1952 reply_nterror(req, ntstatus);
1956 ntstatus = resolve_dfspath_wcard(ctx, conn,
1957 req->flags2 & FLAGS2_DFS_PATHNAMES,
1960 &mask_contains_wcard);
1961 if (!NT_STATUS_IS_OK(ntstatus)) {
1962 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1963 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1964 ERRSRV, ERRbadpath);
1967 reply_nterror(req, ntstatus);
1971 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1972 if (!NT_STATUS_IS_OK(ntstatus)) {
1973 reply_nterror(req, ntstatus);
1977 ntstatus = check_name(conn, directory);
1978 if (!NT_STATUS_IS_OK(ntstatus)) {
1979 reply_nterror(req, ntstatus);
1983 p = strrchr_m(directory,'/');
1985 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1986 if((directory[0] == '.') && (directory[1] == '\0')) {
1988 mask_contains_wcard = True;
1992 directory = talloc_strdup(talloc_tos(), "./");
1994 reply_nterror(req, NT_STATUS_NO_MEMORY);
2002 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2004 if (info_level == SMB_FIND_EA_LIST) {
2007 if (total_data < 4) {
2008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2012 ea_size = IVAL(pdata,0);
2013 if (ea_size != total_data) {
2014 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2015 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2020 if (!lp_ea_support(SNUM(conn))) {
2021 reply_doserror(req, ERRDOS, ERReasnotsupported);
2025 /* Pull out the list of names. */
2026 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2033 *ppdata = (char *)SMB_REALLOC(
2034 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2035 if(*ppdata == NULL ) {
2036 reply_nterror(req, NT_STATUS_NO_MEMORY);
2040 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2042 /* Realloc the params space */
2043 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2044 if (*pparams == NULL) {
2045 reply_nterror(req, NT_STATUS_NO_MEMORY);
2050 /* Save the wildcard match and attribs we are using on this directory -
2051 needed as lanman2 assumes these are being saved between calls */
2053 ntstatus = dptr_create(conn,
2059 mask_contains_wcard,
2063 if (!NT_STATUS_IS_OK(ntstatus)) {
2064 reply_nterror(req, ntstatus);
2068 dptr_num = dptr_dnum(conn->dirptr);
2069 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2071 /* We don't need to check for VOL here as this is returned by
2072 a different TRANS2 call. */
2074 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2075 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2076 dont_descend = True;
2079 space_remaining = max_data_bytes;
2080 out_of_space = False;
2082 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2083 bool got_exact_match = False;
2085 /* this is a heuristic to avoid seeking the dirptr except when
2086 absolutely necessary. It allows for a filename of about 40 chars */
2087 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2088 out_of_space = True;
2091 finished = !get_lanman2_dir_entry(ctx,
2094 mask,dirtype,info_level,
2095 requires_resume_key,dont_descend,
2098 space_remaining, &out_of_space,
2100 &last_entry_off, ea_list);
2103 if (finished && out_of_space)
2106 if (!finished && !out_of_space)
2110 * As an optimisation if we know we aren't looking
2111 * for a wildcard name (ie. the name matches the wildcard exactly)
2112 * then we can finish on any (first) match.
2113 * This speeds up large directory searches. JRA.
2119 /* Ensure space_remaining never goes -ve. */
2120 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2121 space_remaining = 0;
2122 out_of_space = true;
2124 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2128 /* Check if we can close the dirptr */
2129 if(close_after_first || (finished && close_if_end)) {
2130 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2131 dptr_close(&dptr_num);
2135 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2136 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2137 * the protocol level is less than NT1. Tested with smbclient. JRA.
2138 * This should fix the OS/2 client bug #2335.
2141 if(numentries == 0) {
2142 dptr_close(&dptr_num);
2143 if (Protocol < PROTOCOL_NT1) {
2144 reply_doserror(req, ERRDOS, ERRnofiles);
2147 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2148 ERRDOS, ERRbadfile);
2153 /* At this point pdata points to numentries directory entries. */
2155 /* Set up the return parameter block */
2156 SSVAL(params,0,dptr_num);
2157 SSVAL(params,2,numentries);
2158 SSVAL(params,4,finished);
2159 SSVAL(params,6,0); /* Never an EA error */
2160 SSVAL(params,8,last_entry_off);
2162 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2165 if ((! *directory) && dptr_path(dptr_num)) {
2166 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2168 reply_nterror(req, NT_STATUS_NO_MEMORY);
2172 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2173 smb_fn_name(CVAL(req->inbuf,smb_com)),
2174 mask, directory, dirtype, numentries ) );
2177 * Force a name mangle here to ensure that the
2178 * mask as an 8.3 name is top of the mangled cache.
2179 * The reasons for this are subtle. Don't remove
2180 * this code unless you know what you are doing
2181 * (see PR#13758). JRA.
2184 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2185 char mangled_name[13];
2186 name_to_8_3(mask, mangled_name, True, conn->params);
2192 /****************************************************************************
2193 Reply to a TRANS2_FINDNEXT.
2194 ****************************************************************************/
2196 static void call_trans2findnext(connection_struct *conn,
2197 struct smb_request *req,
2198 char **pparams, int total_params,
2199 char **ppdata, int total_data,
2200 unsigned int max_data_bytes)
2202 /* We must be careful here that we don't return more than the
2203 allowed number of data bytes. If this means returning fewer than
2204 maxentries then so be it. We assume that the redirector has
2205 enough room for the fixed number of parameter bytes it has
2207 char *params = *pparams;
2208 char *pdata = *ppdata;
2214 uint16 findnext_flags;
2215 bool close_after_request;
2217 bool requires_resume_key;
2219 bool mask_contains_wcard = False;
2220 char *resume_name = NULL;
2221 const char *mask = NULL;
2222 const char *directory = NULL;
2226 int i, last_entry_off=0;
2227 bool finished = False;
2228 bool dont_descend = False;
2229 bool out_of_space = False;
2230 int space_remaining;
2231 struct ea_list *ea_list = NULL;
2232 NTSTATUS ntstatus = NT_STATUS_OK;
2233 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2234 TALLOC_CTX *ctx = talloc_tos();
2236 if (total_params < 13) {
2237 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2241 dptr_num = SVAL(params,0);
2242 maxentries = SVAL(params,2);
2243 info_level = SVAL(params,4);
2244 resume_key = IVAL(params,6);
2245 findnext_flags = SVAL(params,10);
2246 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2247 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2248 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2249 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2251 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2253 total_params - 12, STR_TERMINATE, &ntstatus,
2254 &mask_contains_wcard);
2255 if (!NT_STATUS_IS_OK(ntstatus)) {
2256 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2257 complain (it thinks we're asking for the directory above the shared
2258 path or an invalid name). Catch this as the resume name is only compared, never used in
2259 a file access. JRA. */
2260 srvstr_pull_talloc(ctx, params, req->flags2,
2261 &resume_name, params+12,
2265 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2266 reply_nterror(req, ntstatus);
2271 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2272 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2273 resume_key = %d resume name = %s continue=%d level = %d\n",
2274 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2275 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2278 /* W2K3 seems to treat zero as 1. */
2282 switch (info_level) {
2283 case SMB_FIND_INFO_STANDARD:
2284 case SMB_FIND_EA_SIZE:
2285 case SMB_FIND_EA_LIST:
2286 case SMB_FIND_FILE_DIRECTORY_INFO:
2287 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2288 case SMB_FIND_FILE_NAMES_INFO:
2289 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2290 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2291 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2293 case SMB_FIND_FILE_UNIX:
2294 case SMB_FIND_FILE_UNIX_INFO2:
2295 if (!lp_unix_extensions()) {
2296 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2301 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2305 if (info_level == SMB_FIND_EA_LIST) {
2308 if (total_data < 4) {
2309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2313 ea_size = IVAL(pdata,0);
2314 if (ea_size != total_data) {
2315 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2316 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2321 if (!lp_ea_support(SNUM(conn))) {
2322 reply_doserror(req, ERRDOS, ERReasnotsupported);
2326 /* Pull out the list of names. */
2327 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2334 *ppdata = (char *)SMB_REALLOC(
2335 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2336 if(*ppdata == NULL) {
2337 reply_nterror(req, NT_STATUS_NO_MEMORY);
2342 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2344 /* Realloc the params space */
2345 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2346 if(*pparams == NULL ) {
2347 reply_nterror(req, NT_STATUS_NO_MEMORY);
2353 /* Check that the dptr is valid */
2354 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2355 reply_doserror(req, ERRDOS, ERRnofiles);
2359 string_set(&conn->dirpath,dptr_path(dptr_num));
2361 /* Get the wildcard mask from the dptr */
2362 if((p = dptr_wcard(dptr_num))== NULL) {
2363 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2364 reply_doserror(req, ERRDOS, ERRnofiles);
2369 directory = conn->dirpath;
2371 /* Get the attr mask from the dptr */
2372 dirtype = dptr_attr(dptr_num);
2374 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2375 dptr_num, mask, dirtype,
2377 dptr_TellDir(conn->dirptr)));
2379 /* We don't need to check for VOL here as this is returned by
2380 a different TRANS2 call. */
2382 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2383 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2384 dont_descend = True;
2387 space_remaining = max_data_bytes;
2388 out_of_space = False;
2391 * Seek to the correct position. We no longer use the resume key but
2392 * depend on the last file name instead.
2395 if(*resume_name && !continue_bit) {
2398 long current_pos = 0;
2400 * Remember, name_to_8_3 is called by
2401 * get_lanman2_dir_entry(), so the resume name
2402 * could be mangled. Ensure we check the unmangled name.
2405 if (mangle_is_mangled(resume_name, conn->params)) {
2406 char *new_resume_name = NULL;
2407 mangle_lookup_name_from_8_3(ctx,
2411 if (new_resume_name) {
2412 resume_name = new_resume_name;
2417 * Fix for NT redirector problem triggered by resume key indexes
2418 * changing between directory scans. We now return a resume key of 0
2419 * and instead look for the filename to continue from (also given
2420 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2421 * findfirst/findnext (as is usual) then the directory pointer
2422 * should already be at the correct place.
2425 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2426 } /* end if resume_name && !continue_bit */
2428 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2429 bool got_exact_match = False;
2431 /* this is a heuristic to avoid seeking the dirptr except when
2432 absolutely necessary. It allows for a filename of about 40 chars */
2433 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2434 out_of_space = True;
2437 finished = !get_lanman2_dir_entry(ctx,
2440 mask,dirtype,info_level,
2441 requires_resume_key,dont_descend,
2444 space_remaining, &out_of_space,
2446 &last_entry_off, ea_list);
2449 if (finished && out_of_space)
2452 if (!finished && !out_of_space)
2456 * As an optimisation if we know we aren't looking
2457 * for a wildcard name (ie. the name matches the wildcard exactly)
2458 * then we can finish on any (first) match.
2459 * This speeds up large directory searches. JRA.
2465 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2468 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2469 smb_fn_name(CVAL(req->inbuf,smb_com)),
2470 mask, directory, dirtype, numentries ) );
2472 /* Check if we can close the dirptr */
2473 if(close_after_request || (finished && close_if_end)) {
2474 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2475 dptr_close(&dptr_num); /* This frees up the saved mask */
2478 /* Set up the return parameter block */
2479 SSVAL(params,0,numentries);
2480 SSVAL(params,2,finished);
2481 SSVAL(params,4,0); /* Never an EA error */
2482 SSVAL(params,6,last_entry_off);
2484 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2490 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2492 E_md4hash(lp_servicename(SNUM(conn)),objid);
2496 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2498 SMB_ASSERT(extended_info != NULL);
2500 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2501 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2502 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2503 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2504 #ifdef SAMBA_VERSION_REVISION
2505 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2507 extended_info->samba_subversion = 0;
2508 #ifdef SAMBA_VERSION_RC_RELEASE
2509 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2511 #ifdef SAMBA_VERSION_PRE_RELEASE
2512 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2515 #ifdef SAMBA_VERSION_VENDOR_PATCH
2516 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2518 extended_info->samba_gitcommitdate = 0;
2519 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2520 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2523 memset(extended_info->samba_version_string, 0,
2524 sizeof(extended_info->samba_version_string));
2526 snprintf (extended_info->samba_version_string,
2527 sizeof(extended_info->samba_version_string),
2528 "%s", samba_version_string());
2531 /****************************************************************************
2532 Reply to a TRANS2_QFSINFO (query filesystem info).
2533 ****************************************************************************/
2535 static void call_trans2qfsinfo(connection_struct *conn,
2536 struct smb_request *req,
2537 char **pparams, int total_params,
2538 char **ppdata, int total_data,
2539 unsigned int max_data_bytes)
2541 char *pdata, *end_data;
2542 char *params = *pparams;
2546 const char *vname = volume_label(SNUM(conn));
2547 int snum = SNUM(conn);
2548 char *fstype = lp_fstype(SNUM(conn));
2549 uint32 additional_flags = 0;
2551 if (total_params < 2) {
2552 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2556 info_level = SVAL(params,0);
2559 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2560 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2561 "info level (0x%x) on IPC$.\n",
2562 (unsigned int)info_level));
2563 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2568 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2569 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2570 DEBUG(0,("call_trans2qfsinfo: encryption required "
2571 "and info level 0x%x sent.\n",
2572 (unsigned int)info_level));
2573 exit_server_cleanly("encryption required "
2579 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2581 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2582 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2583 reply_doserror(req, ERRSRV, ERRinvdevice);
2587 *ppdata = (char *)SMB_REALLOC(
2588 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2589 if (*ppdata == NULL ) {
2590 reply_nterror(req, NT_STATUS_NO_MEMORY);
2595 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2596 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2598 switch (info_level) {
2599 case SMB_INFO_ALLOCATION:
2601 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2603 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2604 reply_unixerror(req, ERRHRD, ERRgeneral);
2608 block_size = lp_block_size(snum);
2609 if (bsize < block_size) {
2610 SMB_BIG_UINT factor = block_size/bsize;
2615 if (bsize > block_size) {
2616 SMB_BIG_UINT factor = bsize/block_size;
2621 bytes_per_sector = 512;
2622 sectors_per_unit = bsize/bytes_per_sector;
2624 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2625 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2626 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2628 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2629 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2630 SIVAL(pdata,l1_cUnit,dsize);
2631 SIVAL(pdata,l1_cUnitAvail,dfree);
2632 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2636 case SMB_INFO_VOLUME:
2637 /* Return volume name */
2639 * Add volume serial number - hash of a combination of
2640 * the called hostname and the service name.
2642 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2644 * Win2k3 and previous mess this up by sending a name length
2645 * one byte short. I believe only older clients (OS/2 Win9x) use
2646 * this call so try fixing this by adding a terminating null to
2647 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2651 pdata+l2_vol_szVolLabel, vname,
2652 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2653 STR_NOALIGN|STR_TERMINATE);
2654 SCVAL(pdata,l2_vol_cch,len);
2655 data_len = l2_vol_szVolLabel + len;
2656 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2657 (unsigned)st.st_ctime, len, vname));
2660 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2661 case SMB_FS_ATTRIBUTE_INFORMATION:
2663 additional_flags = 0;
2664 #if defined(HAVE_SYS_QUOTAS)
2665 additional_flags |= FILE_VOLUME_QUOTAS;
2668 if(lp_nt_acl_support(SNUM(conn))) {
2669 additional_flags |= FILE_PERSISTENT_ACLS;
2672 /* Capabilities are filled in at connection time through STATVFS call */
2673 additional_flags |= conn->fs_capabilities;
2675 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2676 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2677 additional_flags); /* FS ATTRIBUTES */
2679 SIVAL(pdata,4,255); /* Max filename component length */
2680 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2681 and will think we can't do long filenames */
2682 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2683 PTR_DIFF(end_data, pdata+12),
2686 data_len = 12 + len;
2689 case SMB_QUERY_FS_LABEL_INFO:
2690 case SMB_FS_LABEL_INFORMATION:
2691 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2692 PTR_DIFF(end_data, pdata+4), 0);
2697 case SMB_QUERY_FS_VOLUME_INFO:
2698 case SMB_FS_VOLUME_INFORMATION:
2701 * Add volume serial number - hash of a combination of
2702 * the called hostname and the service name.
2704 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2705 (str_checksum(get_local_machine_name())<<16));
2707 /* Max label len is 32 characters. */
2708 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2709 PTR_DIFF(end_data, pdata+18),
2711 SIVAL(pdata,12,len);
2714 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2715 (int)strlen(vname),vname, lp_servicename(snum)));
2718 case SMB_QUERY_FS_SIZE_INFO:
2719 case SMB_FS_SIZE_INFORMATION:
2721 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2723 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2724 reply_unixerror(req, ERRHRD, ERRgeneral);
2727 block_size = lp_block_size(snum);
2728 if (bsize < block_size) {
2729 SMB_BIG_UINT factor = block_size/bsize;
2734 if (bsize > block_size) {
2735 SMB_BIG_UINT factor = bsize/block_size;
2740 bytes_per_sector = 512;
2741 sectors_per_unit = bsize/bytes_per_sector;
2742 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2743 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2744 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2745 SBIG_UINT(pdata,0,dsize);
2746 SBIG_UINT(pdata,8,dfree);
2747 SIVAL(pdata,16,sectors_per_unit);
2748 SIVAL(pdata,20,bytes_per_sector);
2752 case SMB_FS_FULL_SIZE_INFORMATION:
2754 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2756 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2757 reply_unixerror(req, ERRHRD, ERRgeneral);
2760 block_size = lp_block_size(snum);
2761 if (bsize < block_size) {
2762 SMB_BIG_UINT factor = block_size/bsize;
2767 if (bsize > block_size) {
2768 SMB_BIG_UINT factor = bsize/block_size;
2773 bytes_per_sector = 512;
2774 sectors_per_unit = bsize/bytes_per_sector;
2775 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2776 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2777 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2778 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2779 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2780 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2781 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2782 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2786 case SMB_QUERY_FS_DEVICE_INFO:
2787 case SMB_FS_DEVICE_INFORMATION:
2789 SIVAL(pdata,0,0); /* dev type */
2790 SIVAL(pdata,4,0); /* characteristics */
2793 #ifdef HAVE_SYS_QUOTAS
2794 case SMB_FS_QUOTA_INFORMATION:
2796 * what we have to send --metze:
2798 * Unknown1: 24 NULL bytes
2799 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2800 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2801 * Quota Flags: 2 byte :
2802 * Unknown3: 6 NULL bytes
2806 * details for Quota Flags:
2808 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2809 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2810 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2811 * 0x0001 Enable Quotas: enable quota for this fs
2815 /* we need to fake up a fsp here,
2816 * because its not send in this call
2819 SMB_NTQUOTA_STRUCT quotas;
2822 ZERO_STRUCT(quotas);
2828 if (current_user.ut.uid != 0) {
2829 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2830 lp_servicename(SNUM(conn)),conn->user));
2831 reply_doserror(req, ERRDOS, ERRnoaccess);
2835 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2836 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2837 reply_doserror(req, ERRSRV, ERRerror);
2843 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2845 /* Unknown1 24 NULL bytes*/
2846 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2847 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2848 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2850 /* Default Soft Quota 8 bytes */
2851 SBIG_UINT(pdata,24,quotas.softlim);
2853 /* Default Hard Quota 8 bytes */
2854 SBIG_UINT(pdata,32,quotas.hardlim);
2856 /* Quota flag 2 bytes */
2857 SSVAL(pdata,40,quotas.qflags);
2859 /* Unknown3 6 NULL bytes */
2865 #endif /* HAVE_SYS_QUOTAS */
2866 case SMB_FS_OBJECTID_INFORMATION:
2868 unsigned char objid[16];
2869 struct smb_extended_info extended_info;
2870 memcpy(pdata,create_volume_objectid(conn, objid),16);
2871 samba_extended_info_version (&extended_info);
2872 SIVAL(pdata,16,extended_info.samba_magic);
2873 SIVAL(pdata,20,extended_info.samba_version);
2874 SIVAL(pdata,24,extended_info.samba_subversion);
2875 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2876 memcpy(pdata+36,extended_info.samba_version_string,28);
2882 * Query the version and capabilities of the CIFS UNIX extensions
2886 case SMB_QUERY_CIFS_UNIX_INFO:
2888 bool large_write = lp_min_receive_file_size() &&
2889 !srv_is_signing_active();
2890 bool large_read = !srv_is_signing_active();
2891 int encrypt_caps = 0;
2893 if (!lp_unix_extensions()) {
2894 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2898 switch (conn->encrypt_level) {
2904 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2907 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2908 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2909 large_write = false;
2915 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2916 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2918 /* We have POSIX ACLs, pathname, encryption,
2919 * large read/write, and locking capability. */
2921 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2922 CIFS_UNIX_POSIX_ACLS_CAP|
2923 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2924 CIFS_UNIX_FCNTL_LOCKS_CAP|
2925 CIFS_UNIX_EXTATTR_CAP|
2926 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2928 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2930 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2934 case SMB_QUERY_POSIX_FS_INFO:
2937 vfs_statvfs_struct svfs;
2939 if (!lp_unix_extensions()) {
2940 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2944 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2948 SIVAL(pdata,0,svfs.OptimalTransferSize);
2949 SIVAL(pdata,4,svfs.BlockSize);
2950 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2951 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2952 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2953 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2954 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2955 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2956 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2958 } else if (rc == EOPNOTSUPP) {
2959 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2961 #endif /* EOPNOTSUPP */
2963 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2964 reply_doserror(req, ERRSRV, ERRerror);
2970 case SMB_QUERY_POSIX_WHOAMI:
2976 if (!lp_unix_extensions()) {
2977 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2981 if (max_data_bytes < 40) {
2982 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2986 /* We ARE guest if global_sid_Builtin_Guests is
2987 * in our list of SIDs.
2989 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2990 current_user.nt_user_token)) {
2991 flags |= SMB_WHOAMI_GUEST;
2994 /* We are NOT guest if global_sid_Authenticated_Users
2995 * is in our list of SIDs.
2997 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2998 current_user.nt_user_token)) {
2999 flags &= ~SMB_WHOAMI_GUEST;
3002 /* NOTE: 8 bytes for UID/GID, irrespective of native
3003 * platform size. This matches
3004 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3006 data_len = 4 /* flags */
3013 + 4 /* pad/reserved */
3014 + (current_user.ut.ngroups * 8)
3016 + (current_user.nt_user_token->num_sids *
3020 SIVAL(pdata, 0, flags);
3021 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3022 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
3023 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
3026 if (data_len >= max_data_bytes) {
3027 /* Potential overflow, skip the GIDs and SIDs. */
3029 SIVAL(pdata, 24, 0); /* num_groups */
3030 SIVAL(pdata, 28, 0); /* num_sids */
3031 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3032 SIVAL(pdata, 36, 0); /* reserved */
3038 SIVAL(pdata, 24, current_user.ut.ngroups);
3040 current_user.nt_user_token->num_sids);
3042 /* We walk the SID list twice, but this call is fairly
3043 * infrequent, and I don't expect that it's performance
3044 * sensitive -- jpeach
3046 for (i = 0, sid_bytes = 0;
3047 i < current_user.nt_user_token->num_sids; ++i) {
3048 sid_bytes += ndr_size_dom_sid(
3049 ¤t_user.nt_user_token->user_sids[i], 0);
3052 /* SID list byte count */
3053 SIVAL(pdata, 32, sid_bytes);
3055 /* 4 bytes pad/reserved - must be zero */
3056 SIVAL(pdata, 36, 0);
3060 for (i = 0; i < current_user.ut.ngroups; ++i) {
3061 SBIG_UINT(pdata, data_len,
3062 (SMB_BIG_UINT)current_user.ut.groups[i]);
3068 i < current_user.nt_user_token->num_sids; ++i) {
3069 int sid_len = ndr_size_dom_sid(
3070 ¤t_user.nt_user_token->user_sids[i], 0);
3072 sid_linearize(pdata + data_len, sid_len,
3073 ¤t_user.nt_user_token->user_sids[i]);
3074 data_len += sid_len;
3080 case SMB_MAC_QUERY_FS_INFO:
3082 * Thursby MAC extension... ONLY on NTFS filesystems
3083 * once we do streams then we don't need this
3085 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3087 SIVAL(pdata,84,0x100); /* Don't support mac... */
3092 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3097 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3100 DEBUG( 4, ( "%s info_level = %d\n",
3101 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3106 /****************************************************************************
3107 Reply to a TRANS2_SETFSINFO (set filesystem info).
3108 ****************************************************************************/
3110 static void call_trans2setfsinfo(connection_struct *conn,
3111 struct smb_request *req,
3112 char **pparams, int total_params,
3113 char **ppdata, int total_data,
3114 unsigned int max_data_bytes)
3116 char *pdata = *ppdata;
3117 char *params = *pparams;
3120 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3123 if (total_params < 4) {
3124 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3130 info_level = SVAL(params,2);
3133 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3134 info_level != SMB_SET_CIFS_UNIX_INFO) {
3135 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3136 "info level (0x%x) on IPC$.\n",
3137 (unsigned int)info_level));
3138 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3143 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3144 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3145 DEBUG(0,("call_trans2setfsinfo: encryption required "
3146 "and info level 0x%x sent.\n",
3147 (unsigned int)info_level));
3148 exit_server_cleanly("encryption required "
3154 switch(info_level) {
3155 case SMB_SET_CIFS_UNIX_INFO:
3157 uint16 client_unix_major;
3158 uint16 client_unix_minor;
3159 uint32 client_unix_cap_low;
3160 uint32 client_unix_cap_high;
3162 if (!lp_unix_extensions()) {
3164 NT_STATUS_INVALID_LEVEL);
3168 /* There should be 12 bytes of capabilities set. */
3169 if (total_data < 8) {
3172 NT_STATUS_INVALID_PARAMETER);
3175 client_unix_major = SVAL(pdata,0);
3176 client_unix_minor = SVAL(pdata,2);
3177 client_unix_cap_low = IVAL(pdata,4);
3178 client_unix_cap_high = IVAL(pdata,8);
3179 /* Just print these values for now. */
3180 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3181 cap_low = 0x%x, cap_high = 0x%x\n",
3182 (unsigned int)client_unix_major,
3183 (unsigned int)client_unix_minor,
3184 (unsigned int)client_unix_cap_low,
3185 (unsigned int)client_unix_cap_high ));
3187 /* Here is where we must switch to posix pathname processing... */
3188 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3189 lp_set_posix_pathnames();
3190 mangle_change_to_posix();
3193 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3194 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3195 /* Client that knows how to do posix locks,
3196 * but not posix open/mkdir operations. Set a
3197 * default type for read/write checks. */
3199 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3205 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3208 size_t param_len = 0;
3209 size_t data_len = total_data;
3211 if (!lp_unix_extensions()) {
3214 NT_STATUS_INVALID_LEVEL);
3218 if (lp_smb_encrypt(SNUM(conn)) == false) {
3221 NT_STATUS_NOT_SUPPORTED);
3225 DEBUG( 4,("call_trans2setfsinfo: "
3226 "request transport encryption.\n"));
3228 status = srv_request_encryption_setup(conn,
3229 (unsigned char **)ppdata,
3231 (unsigned char **)pparams,
3234 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3235 !NT_STATUS_IS_OK(status)) {
3236 reply_nterror(req, status);
3240 send_trans2_replies(conn, req,
3247 if (NT_STATUS_IS_OK(status)) {
3248 /* Server-side transport
3249 * encryption is now *on*. */
3250 status = srv_encryption_start(conn);
3251 if (!NT_STATUS_IS_OK(status)) {
3252 exit_server_cleanly(
3253 "Failure in setting "
3254 "up encrypted transport");
3260 case SMB_FS_QUOTA_INFORMATION:
3262 files_struct *fsp = NULL;
3263 SMB_NTQUOTA_STRUCT quotas;
3265 ZERO_STRUCT(quotas);
3268 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3269 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3270 lp_servicename(SNUM(conn)),conn->user));
3271 reply_doserror(req, ERRSRV, ERRaccess);
3275 /* note: normaly there're 48 bytes,
3276 * but we didn't use the last 6 bytes for now
3279 fsp = file_fsp(SVAL(params,0));
3280 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3281 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3283 req, NT_STATUS_INVALID_HANDLE);
3287 if (total_data < 42) {
3288 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3292 NT_STATUS_INVALID_PARAMETER);
3296 /* unknown_1 24 NULL bytes in pdata*/
3298 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3299 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3300 #ifdef LARGE_SMB_OFF_T
3301 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3302 #else /* LARGE_SMB_OFF_T */
3303 if ((IVAL(pdata,28) != 0)&&
3304 ((quotas.softlim != 0xFFFFFFFF)||
3305 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3306 /* more than 32 bits? */
3309 NT_STATUS_INVALID_PARAMETER);
3312 #endif /* LARGE_SMB_OFF_T */
3314 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3315 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3316 #ifdef LARGE_SMB_OFF_T
3317 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3318 #else /* LARGE_SMB_OFF_T */
3319 if ((IVAL(pdata,36) != 0)&&
3320 ((quotas.hardlim != 0xFFFFFFFF)||
3321 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3322 /* more than 32 bits? */
3325 NT_STATUS_INVALID_PARAMETER);
3328 #endif /* LARGE_SMB_OFF_T */
3330 /* quota_flags 2 bytes **/
3331 quotas.qflags = SVAL(pdata,40);
3333 /* unknown_2 6 NULL bytes follow*/
3335 /* now set the quotas */
3336 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3337 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3338 reply_doserror(req, ERRSRV, ERRerror);
3345 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3347 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3353 * sending this reply works fine,
3354 * but I'm not sure it's the same
3355 * like windows do...
3358 reply_outbuf(req, 10, 0);
3361 #if defined(HAVE_POSIX_ACLS)
3362 /****************************************************************************
3363 Utility function to count the number of entries in a POSIX acl.
3364 ****************************************************************************/
3366 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3368 unsigned int ace_count = 0;
3369 int entry_id = SMB_ACL_FIRST_ENTRY;
3370 SMB_ACL_ENTRY_T entry;
3372 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3374 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3375 entry_id = SMB_ACL_NEXT_ENTRY;
3382 /****************************************************************************
3383 Utility function to marshall a POSIX acl into wire format.
3384 ****************************************************************************/
3386 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3388 int entry_id = SMB_ACL_FIRST_ENTRY;
3389 SMB_ACL_ENTRY_T entry;
3391 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3392 SMB_ACL_TAG_T tagtype;
3393 SMB_ACL_PERMSET_T permset;
3394 unsigned char perms = 0;
3395 unsigned int own_grp;
3398 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3399 entry_id = SMB_ACL_NEXT_ENTRY;
3402 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3403 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3407 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3408 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3412 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3413 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3414 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3416 SCVAL(pdata,1,perms);
3419 case SMB_ACL_USER_OBJ:
3420 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3421 own_grp = (unsigned int)pst->st_uid;
3422 SIVAL(pdata,2,own_grp);
3427 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3429 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3432 own_grp = (unsigned int)*puid;
3433 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3434 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3435 SIVAL(pdata,2,own_grp);
3439 case SMB_ACL_GROUP_OBJ:
3440 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3441 own_grp = (unsigned int)pst->st_gid;
3442 SIVAL(pdata,2,own_grp);
3447 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3449 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3452 own_grp = (unsigned int)*pgid;
3453 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3454 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3455 SIVAL(pdata,2,own_grp);
3460 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3461 SIVAL(pdata,2,0xFFFFFFFF);
3462 SIVAL(pdata,6,0xFFFFFFFF);
3465 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3466 SIVAL(pdata,2,0xFFFFFFFF);
3467 SIVAL(pdata,6,0xFFFFFFFF);
3470 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3473 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3480 /****************************************************************************
3481 Store the FILE_UNIX_BASIC info.
3482 ****************************************************************************/
3484 static char *store_file_unix_basic(connection_struct *conn,
3487 const SMB_STRUCT_STAT *psbuf)
3489 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3490 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3492 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3495 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3498 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3499 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3500 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3503 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3507 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3511 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3514 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3518 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3522 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3525 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3529 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3536 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3537 * the chflags(2) (or equivalent) flags.
3539 * XXX: this really should be behind the VFS interface. To do this, we would
3540 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3541 * Each VFS module could then implement its own mapping as appropriate for the
3542 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3544 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3548 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3552 { UF_IMMUTABLE, EXT_IMMUTABLE },
3556 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3560 { UF_HIDDEN, EXT_HIDDEN },
3563 /* Do not remove. We need to guarantee that this array has at least one
3564 * entry to build on HP-UX.
3570 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3571 uint32 *smb_fflags, uint32 *smb_fmask)
3573 #ifdef HAVE_STAT_ST_FLAGS
3576 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3577 *smb_fmask |= info2_flags_map[i].smb_fflag;
3578 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3579 *smb_fflags |= info2_flags_map[i].smb_fflag;
3582 #endif /* HAVE_STAT_ST_FLAGS */
3585 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3586 const uint32 smb_fflags,
3587 const uint32 smb_fmask,
3590 #ifdef HAVE_STAT_ST_FLAGS
3591 uint32 max_fmask = 0;
3594 *stat_fflags = psbuf->st_flags;
3596 /* For each flags requested in smb_fmask, check the state of the
3597 * corresponding flag in smb_fflags and set or clear the matching
3601 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3602 max_fmask |= info2_flags_map[i].smb_fflag;
3603 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3604 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3605 *stat_fflags |= info2_flags_map[i].stat_fflag;
3607 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3612 /* If smb_fmask is asking to set any bits that are not supported by
3613 * our flag mappings, we should fail.
3615 if ((smb_fmask & max_fmask) != smb_fmask) {
3622 #endif /* HAVE_STAT_ST_FLAGS */
3626 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3627 * of file flags and birth (create) time.
3629 static char *store_file_unix_basic_info2(connection_struct *conn,
3632 const SMB_STRUCT_STAT *psbuf)
3634 uint32 file_flags = 0;
3635 uint32 flags_mask = 0;
3637 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3639 /* Create (birth) time 64 bit */
3640 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3643 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3644 SIVAL(pdata, 0, file_flags); /* flags */
3645 SIVAL(pdata, 4, flags_mask); /* mask */
3651 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3652 const struct stream_struct *streams,
3654 unsigned int max_data_bytes,
3655 unsigned int *data_size)
3658 unsigned int ofs = 0;
3660 for (i=0; i<num_streams; i++) {
3661 unsigned int next_offset;
3663 smb_ucs2_t *namebuf;
3665 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3668 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3669 return NT_STATUS_INVALID_PARAMETER;
3673 * name_buf is now null-terminated, we need to marshall as not
3679 if (ofs + 24 + namelen > max_data_bytes) {
3680 TALLOC_FREE(namebuf);
3681 return NT_STATUS_BUFFER_TOO_SMALL;
3684 SIVAL(data, ofs+4, namelen);
3685 SOFF_T(data, ofs+8, streams[i].size);
3686 SOFF_T(data, ofs+16, streams[i].alloc_size);
3687 memcpy(data+ofs+24, namebuf, namelen);
3688 TALLOC_FREE(namebuf);
3690 next_offset = ofs + 24 + namelen;
3692 if (i == num_streams-1) {
3693 SIVAL(data, ofs, 0);
3696 unsigned int align = ndr_align_size(next_offset, 8);
3698 if (next_offset + align > max_data_bytes) {
3699 return NT_STATUS_BUFFER_TOO_SMALL;
3702 memset(data+next_offset, 0, align);
3703 next_offset += align;
3705 SIVAL(data, ofs, next_offset - ofs);
3714 return NT_STATUS_OK;
3717 /****************************************************************************
3718 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3719 ****************************************************************************/
3721 static void call_trans2qpipeinfo(connection_struct *conn,
3722 struct smb_request *req,
3723 unsigned int tran_call,
3724 char **pparams, int total_params,
3725 char **ppdata, int total_data,
3726 unsigned int max_data_bytes)
3728 char *params = *pparams;
3729 char *pdata = *ppdata;
3730 unsigned int data_size = 0;
3731 unsigned int param_size = 2;
3733 smb_np_struct *p_pipe = NULL;
3736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3740 if (total_params < 4) {
3741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3745 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3746 if (p_pipe == NULL) {
3747 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3751 info_level = SVAL(params,2);
3753 *pparams = (char *)SMB_REALLOC(*pparams,2);
3754 if (*pparams == NULL) {
3755 reply_nterror(req, NT_STATUS_NO_MEMORY);
3760 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3761 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3762 if (*ppdata == NULL ) {
3763 reply_nterror(req, NT_STATUS_NO_MEMORY);
3768 switch (info_level) {
3769 case SMB_FILE_STANDARD_INFORMATION:
3771 SOFF_T(pdata,0,4096LL);
3778 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3782 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3788 /****************************************************************************
3789 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3790 file name or file id).
3791 ****************************************************************************/
3793 static void call_trans2qfilepathinfo(connection_struct *conn,
3794 struct smb_request *req,
3795 unsigned int tran_call,
3796 char **pparams, int total_params,
3797 char **ppdata, int total_data,
3798 unsigned int max_data_bytes)
3800 char *params = *pparams;
3801 char *pdata = *ppdata;
3802 char *dstart, *dend;
3806 SMB_OFF_T file_size=0;
3807 SMB_BIG_UINT allocation_size=0;
3808 unsigned int data_size = 0;
3809 unsigned int param_size = 2;
3810 SMB_STRUCT_STAT sbuf;
3811 char *dos_fname = NULL;
3817 bool delete_pending = False;
3819 time_t create_time, mtime, atime;
3820 struct timespec create_time_ts, mtime_ts, atime_ts;
3821 struct timespec write_time_ts;
3822 files_struct *fsp = NULL;
3823 struct file_id fileid;
3824 struct ea_list *ea_list = NULL;
3825 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3826 char *lock_data = NULL;
3827 bool ms_dfs_link = false;
3828 TALLOC_CTX *ctx = talloc_tos();
3831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3836 ZERO_STRUCT(write_time_ts);
3838 if (tran_call == TRANSACT2_QFILEINFO) {
3839 if (total_params < 4) {
3840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3845 call_trans2qpipeinfo(conn, req, tran_call,
3846 pparams, total_params,
3852 fsp = file_fsp(SVAL(params,0));
3853 info_level = SVAL(params,2);
3855 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3857 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3858 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3862 /* Initial check for valid fsp ptr. */
3863 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3867 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3869 reply_nterror(req, NT_STATUS_NO_MEMORY);
3873 if(fsp->fake_file_handle) {
3875 * This is actually for the QUOTA_FAKE_FILE --metze
3878 /* We know this name is ok, it's already passed the checks. */
3880 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3882 * This is actually a QFILEINFO on a directory
3883 * handle (returned from an NT SMB). NT5.0 seems
3884 * to do this call. JRA.
3887 if (INFO_LEVEL_IS_UNIX(info_level)) {
3888 /* Always do lstat for UNIX calls. */
3889 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3890 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3891 reply_unixerror(req,ERRDOS,ERRbadpath);
3894 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3895 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3896 reply_unixerror(req, ERRDOS, ERRbadpath);
3900 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3901 get_file_infos(fileid, &delete_pending, &write_time_ts);
3904 * Original code - this is an open file.
3906 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3910 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3911 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3912 reply_unixerror(req, ERRDOS, ERRbadfid);
3915 pos = fsp->fh->position_information;
3916 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3917 get_file_infos(fileid, &delete_pending, &write_time_ts);
3918 access_mask = fsp->access_mask;
3922 NTSTATUS status = NT_STATUS_OK;
3925 if (total_params < 7) {
3926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3930 info_level = SVAL(params,0);
3932 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3934 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3935 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3939 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3941 STR_TERMINATE, &status);
3942 if (!NT_STATUS_IS_OK(status)) {
3943 reply_nterror(req, status);
3947 status = resolve_dfspath(ctx,
3949 req->flags2 & FLAGS2_DFS_PATHNAMES,
3952 if (!NT_STATUS_IS_OK(status)) {
3953 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3954 reply_botherror(req,
3955 NT_STATUS_PATH_NOT_COVERED,
3956 ERRSRV, ERRbadpath);
3958 reply_nterror(req, status);
3962 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3963 if (!NT_STATUS_IS_OK(status)) {
3964 reply_nterror(req, status);
3967 status = check_name(conn, fname);
3968 if (!NT_STATUS_IS_OK(status)) {
3969 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3970 reply_nterror(req, status);
3974 if (INFO_LEVEL_IS_UNIX(info_level)) {
3975 /* Always do lstat for UNIX calls. */
3976 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3977 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3978 reply_unixerror(req, ERRDOS, ERRbadpath);
3982 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3983 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
3986 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3987 reply_unixerror(req, ERRDOS, ERRbadpath);
3992 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3993 get_file_infos(fileid, &delete_pending, &write_time_ts);
3994 if (delete_pending) {
3995 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4000 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4001 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4005 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4006 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4008 p = strrchr_m(fname,'/');
4015 mode = dos_mode_msdfs(conn,fname,&sbuf);
4017 mode = dos_mode(conn,fname,&sbuf);
4020 mode = FILE_ATTRIBUTE_NORMAL;
4022 nlink = sbuf.st_nlink;
4024 if (nlink && (mode&aDIR)) {
4028 if ((nlink > 0) && delete_pending) {
4032 fullpathname = fname;
4034 file_size = get_file_size(sbuf);
4036 /* Pull out any data sent here before we realloc. */
4037 switch (info_level) {
4038 case SMB_INFO_QUERY_EAS_FROM_LIST:
4040 /* Pull any EA list from the data portion. */
4043 if (total_data < 4) {
4045 req, NT_STATUS_INVALID_PARAMETER);
4048 ea_size = IVAL(pdata,0);
4050 if (total_data > 0 && ea_size != total_data) {
4051 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4052 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4054 req, NT_STATUS_INVALID_PARAMETER);
4058 if (!lp_ea_support(SNUM(conn))) {
4059 reply_doserror(req, ERRDOS,
4060 ERReasnotsupported);
4064 /* Pull out the list of names. */
4065 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4068 req, NT_STATUS_INVALID_PARAMETER);
4074 case SMB_QUERY_POSIX_LOCK:
4076 if (fsp == NULL || fsp->fh->fd == -1) {
4077 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4081 if (total_data != POSIX_LOCK_DATA_SIZE) {
4083 req, NT_STATUS_INVALID_PARAMETER);
4087 /* Copy the lock range data. */
4088 lock_data = (char *)TALLOC_MEMDUP(
4089 ctx, pdata, total_data);
4091 reply_nterror(req, NT_STATUS_NO_MEMORY);
4099 *pparams = (char *)SMB_REALLOC(*pparams,2);
4100 if (*pparams == NULL) {
4101 reply_nterror(req, NT_STATUS_NO_MEMORY);
4106 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4107 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4108 if (*ppdata == NULL ) {
4109 reply_nterror(req, NT_STATUS_NO_MEMORY);
4114 dend = dstart + data_size - 1;
4116 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4117 mtime_ts = get_mtimespec(&sbuf);
4118 atime_ts = get_atimespec(&sbuf);
4120 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4123 /* Do we have this path open ? */
4125 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4126 fsp1 = file_find_di_first(fileid);
4127 if (fsp1 && fsp1->initial_allocation_size) {
4128 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4132 if (!null_timespec(write_time_ts)) {
4133 mtime_ts = write_time_ts;
4136 if (lp_dos_filetime_resolution(SNUM(conn))) {
4137 dos_filetime_timespec(&create_time_ts);
4138 dos_filetime_timespec(&mtime_ts);
4139 dos_filetime_timespec(&atime_ts);
4142 create_time = convert_timespec_to_time_t(create_time_ts);
4143 mtime = convert_timespec_to_time_t(mtime_ts);
4144 atime = convert_timespec_to_time_t(atime_ts);
4146 /* NT expects the name to be in an exact form of the *full*
4147 filename. See the trans2 torture test */
4148 if (ISDOT(base_name)) {
4149 dos_fname = talloc_strdup(ctx, "\\");
4151 reply_nterror(req, NT_STATUS_NO_MEMORY);
4155 dos_fname = talloc_asprintf(ctx,
4159 reply_nterror(req, NT_STATUS_NO_MEMORY);
4162 string_replace(dos_fname, '/', '\\');
4165 switch (info_level) {
4166 case SMB_INFO_STANDARD:
4167 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4169 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4170 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4171 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4172 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4173 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4174 SSVAL(pdata,l1_attrFile,mode);
4177 case SMB_INFO_QUERY_EA_SIZE:
4179 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4180 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4182 srv_put_dos_date2(pdata,0,create_time);
4183 srv_put_dos_date2(pdata,4,atime);
4184 srv_put_dos_date2(pdata,8,mtime); /* write time */
4185 SIVAL(pdata,12,(uint32)file_size);
4186 SIVAL(pdata,16,(uint32)allocation_size);
4187 SSVAL(pdata,20,mode);
4188 SIVAL(pdata,22,ea_size);
4192 case SMB_INFO_IS_NAME_VALID:
4193 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4194 if (tran_call == TRANSACT2_QFILEINFO) {
4195 /* os/2 needs this ? really ?*/
4196 reply_doserror(req, ERRDOS, ERRbadfunc);
4203 case SMB_INFO_QUERY_EAS_FROM_LIST:
4205 size_t total_ea_len = 0;
4206 struct ea_list *ea_file_list = NULL;
4208 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4210 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4211 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4213 if (!ea_list || (total_ea_len > data_size)) {
4215 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4219 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4223 case SMB_INFO_QUERY_ALL_EAS:
4225 /* We have data_size bytes to put EA's into. */
4226 size_t total_ea_len = 0;
4228 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4230 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4231 if (!ea_list || (total_ea_len > data_size)) {
4233 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4237 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4241 case SMB_FILE_BASIC_INFORMATION:
4242 case SMB_QUERY_FILE_BASIC_INFO:
4244 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4245 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4246 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4248 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4252 put_long_date_timespec(pdata,create_time_ts);
4253 put_long_date_timespec(pdata+8,atime_ts);
4254 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4255 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4256 SIVAL(pdata,32,mode);
4258 DEBUG(5,("SMB_QFBI - "));
4259 DEBUG(5,("create: %s ", ctime(&create_time)));
4260 DEBUG(5,("access: %s ", ctime(&atime)));
4261 DEBUG(5,("write: %s ", ctime(&mtime)));
4262 DEBUG(5,("change: %s ", ctime(&mtime)));
4263 DEBUG(5,("mode: %x\n", mode));
4266 case SMB_FILE_STANDARD_INFORMATION:
4267 case SMB_QUERY_FILE_STANDARD_INFO:
4269 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4271 SOFF_T(pdata,0,allocation_size);
4272 SOFF_T(pdata,8,file_size);
4273 SIVAL(pdata,16,nlink);
4274 SCVAL(pdata,20,delete_pending?1:0);
4275 SCVAL(pdata,21,(mode&aDIR)?1:0);
4276 SSVAL(pdata,22,0); /* Padding. */
4279 case SMB_FILE_EA_INFORMATION:
4280 case SMB_QUERY_FILE_EA_INFO:
4282 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4283 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4285 SIVAL(pdata,0,ea_size);
4289 /* Get the 8.3 name - used if NT SMB was negotiated. */
4290 case SMB_QUERY_FILE_ALT_NAME_INFO:
4291 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4293 char mangled_name[13];
4294 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4295 if (!name_to_8_3(base_name,mangled_name,
4296 True,conn->params)) {
4299 NT_STATUS_NO_MEMORY);
4301 len = srvstr_push(dstart, req->flags2,
4302 pdata+4, mangled_name,
4303 PTR_DIFF(dend, pdata+4),
4305 data_size = 4 + len;
4310 case SMB_QUERY_FILE_NAME_INFO:
4312 this must be *exactly* right for ACLs on mapped drives to work
4314 len = srvstr_push(dstart, req->flags2,
4316 PTR_DIFF(dend, pdata+4),
4318 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4319 data_size = 4 + len;
4323 case SMB_FILE_ALLOCATION_INFORMATION:
4324 case SMB_QUERY_FILE_ALLOCATION_INFO:
4325 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4327 SOFF_T(pdata,0,allocation_size);
4330 case SMB_FILE_END_OF_FILE_INFORMATION:
4331 case SMB_QUERY_FILE_END_OF_FILEINFO:
4332 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4334 SOFF_T(pdata,0,file_size);
4337 case SMB_QUERY_FILE_ALL_INFO:
4338 case SMB_FILE_ALL_INFORMATION:
4340 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4341 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4342 put_long_date_timespec(pdata,create_time_ts);
4343 put_long_date_timespec(pdata+8,atime_ts);
4344 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4345 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4346 SIVAL(pdata,32,mode);
4347 SIVAL(pdata,36,0); /* padding. */
4349 SOFF_T(pdata,0,allocation_size);
4350 SOFF_T(pdata,8,file_size);
4351 SIVAL(pdata,16,nlink);
4352 SCVAL(pdata,20,delete_pending);
4353 SCVAL(pdata,21,(mode&aDIR)?1:0);
4356 SIVAL(pdata,0,ea_size);
4357 pdata += 4; /* EA info */
4358 len = srvstr_push(dstart, req->flags2,
4360 PTR_DIFF(dend, pdata+4),
4364 data_size = PTR_DIFF(pdata,(*ppdata));
4367 case SMB_FILE_INTERNAL_INFORMATION:
4368 /* This should be an index number - looks like
4371 I think this causes us to fail the IFSKIT
4372 BasicFileInformationTest. -tpot */
4374 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4375 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4376 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4380 case SMB_FILE_ACCESS_INFORMATION:
4381 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4382 SIVAL(pdata,0,access_mask);
4386 case SMB_FILE_NAME_INFORMATION:
4387 /* Pathname with leading '\'. */
4390 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4391 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4392 SIVAL(pdata,0,byte_len);
4393 data_size = 4 + byte_len;
4397 case SMB_FILE_DISPOSITION_INFORMATION:
4398 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4400 SCVAL(pdata,0,delete_pending);
4403 case SMB_FILE_POSITION_INFORMATION:
4404 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4406 SOFF_T(pdata,0,pos);
4409 case SMB_FILE_MODE_INFORMATION:
4410 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4411 SIVAL(pdata,0,mode);
4415 case SMB_FILE_ALIGNMENT_INFORMATION:
4416 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4417 SIVAL(pdata,0,0); /* No alignment needed. */
4422 * NT4 server just returns "invalid query" to this - if we try
4423 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4426 /* The first statement above is false - verified using Thursby
4427 * client against NT4 -- gcolley.
4429 case SMB_QUERY_FILE_STREAM_INFO:
4430 case SMB_FILE_STREAM_INFORMATION: {
4431 unsigned int num_streams;
4432 struct stream_struct *streams;
4435 DEBUG(10,("call_trans2qfilepathinfo: "
4436 "SMB_FILE_STREAM_INFORMATION\n"));
4438 status = SMB_VFS_STREAMINFO(
4439 conn, fsp, fname, talloc_tos(),
4440 &num_streams, &streams);
4442 if (!NT_STATUS_IS_OK(status)) {
4443 DEBUG(10, ("could not get stream info: %s\n",
4444 nt_errstr(status)));
4445 reply_nterror(req, status);
4449 status = marshall_stream_info(num_streams, streams,
4450 pdata, max_data_bytes,
4453 if (!NT_STATUS_IS_OK(status)) {
4454 DEBUG(10, ("marshall_stream_info failed: %s\n",
4455 nt_errstr(status)));
4456 reply_nterror(req, status);
4460 TALLOC_FREE(streams);
4464 case SMB_QUERY_COMPRESSION_INFO:
4465 case SMB_FILE_COMPRESSION_INFORMATION:
4466 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4467 SOFF_T(pdata,0,file_size);
4468 SIVAL(pdata,8,0); /* ??? */
4469 SIVAL(pdata,12,0); /* ??? */
4473 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4474 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4475 put_long_date_timespec(pdata,create_time_ts);
4476 put_long_date_timespec(pdata+8,atime_ts);
4477 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4478 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4479 SOFF_T(pdata,32,allocation_size);
4480 SOFF_T(pdata,40,file_size);
4481 SIVAL(pdata,48,mode);
4482 SIVAL(pdata,52,0); /* ??? */
4486 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4487 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4488 SIVAL(pdata,0,mode);
4494 * CIFS UNIX Extensions.
4497 case SMB_QUERY_FILE_UNIX_BASIC:
4499 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4500 data_size = PTR_DIFF(pdata,(*ppdata));
4504 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4506 for (i=0; i<100; i++)
4507 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4513 case SMB_QUERY_FILE_UNIX_INFO2:
4515 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4516 data_size = PTR_DIFF(pdata,(*ppdata));
4520 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4522 for (i=0; i<100; i++)
4523 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4529 case SMB_QUERY_FILE_UNIX_LINK:
4531 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4534 reply_nterror(req, NT_STATUS_NO_MEMORY);
4538 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4540 if(!S_ISLNK(sbuf.st_mode)) {
4541 reply_unixerror(req, ERRSRV,
4546 reply_unixerror(req, ERRDOS, ERRbadlink);
4549 len = SMB_VFS_READLINK(conn,fullpathname,
4552 reply_unixerror(req, ERRDOS,
4557 len = srvstr_push(dstart, req->flags2,
4559 PTR_DIFF(dend, pdata),
4562 data_size = PTR_DIFF(pdata,(*ppdata));
4567 #if defined(HAVE_POSIX_ACLS)
4568 case SMB_QUERY_POSIX_ACL:
4570 SMB_ACL_T file_acl = NULL;
4571 SMB_ACL_T def_acl = NULL;
4572 uint16 num_file_acls = 0;
4573 uint16 num_def_acls = 0;
4575 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4576 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4578 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4581 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4582 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4586 NT_STATUS_NOT_IMPLEMENTED);
4590 if (S_ISDIR(sbuf.st_mode)) {
4591 if (fsp && fsp->is_directory) {
4592 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4594 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4596 def_acl = free_empty_sys_acl(conn, def_acl);
4599 num_file_acls = count_acl_entries(conn, file_acl);
4600 num_def_acls = count_acl_entries(conn, def_acl);
4602 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4603 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4605 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4606 SMB_POSIX_ACL_HEADER_SIZE) ));
4608 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4611 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4615 NT_STATUS_BUFFER_TOO_SMALL);
4619 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4620 SSVAL(pdata,2,num_file_acls);
4621 SSVAL(pdata,4,num_def_acls);
4622 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4624 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4627 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4630 req, NT_STATUS_INTERNAL_ERROR);
4633 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4635 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4638 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4642 NT_STATUS_INTERNAL_ERROR);
4647 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4650 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4652 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4658 case SMB_QUERY_POSIX_LOCK:
4660 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4662 SMB_BIG_UINT offset;
4664 enum brl_type lock_type;
4666 if (total_data != POSIX_LOCK_DATA_SIZE) {
4668 req, NT_STATUS_INVALID_PARAMETER);
4672 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4673 case POSIX_LOCK_TYPE_READ:
4674 lock_type = READ_LOCK;
4676 case POSIX_LOCK_TYPE_WRITE:
4677 lock_type = WRITE_LOCK;
4679 case POSIX_LOCK_TYPE_UNLOCK:
4681 /* There's no point in asking for an unlock... */
4684 NT_STATUS_INVALID_PARAMETER);
4688 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4689 #if defined(HAVE_LONGLONG)
4690 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4691 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4692 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4693 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4694 #else /* HAVE_LONGLONG */
4695 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4696 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4697 #endif /* HAVE_LONGLONG */
4699 status = query_lock(fsp,
4706 if (ERROR_WAS_LOCK_DENIED(status)) {
4707 /* Here we need to report who has it locked... */
4708 data_size = POSIX_LOCK_DATA_SIZE;
4710 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4711 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4712 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4713 #if defined(HAVE_LONGLONG)
4714 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4715 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4716 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4717 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4718 #else /* HAVE_LONGLONG */
4719 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4720 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4721 #endif /* HAVE_LONGLONG */
4723 } else if (NT_STATUS_IS_OK(status)) {
4724 /* For success we just return a copy of what we sent
4725 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4726 data_size = POSIX_LOCK_DATA_SIZE;
4727 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4728 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4730 reply_nterror(req, status);
4737 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4741 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4747 /****************************************************************************
4748 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4750 ****************************************************************************/
4752 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4753 connection_struct *conn,
4754 const char *oldname_in,
4755 const char *newname_in)
4757 SMB_STRUCT_STAT sbuf1, sbuf2;
4758 char *last_component_oldname = NULL;
4759 char *last_component_newname = NULL;
4760 char *oldname = NULL;
4761 char *newname = NULL;
4762 NTSTATUS status = NT_STATUS_OK;
4767 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4768 &last_component_oldname, &sbuf1);
4769 if (!NT_STATUS_IS_OK(status)) {
4773 status = check_name(conn, oldname);
4774 if (!NT_STATUS_IS_OK(status)) {
4778 /* source must already exist. */
4779 if (!VALID_STAT(sbuf1)) {
4780 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4783 status = unix_convert(ctx, conn, newname_in, False, &newname,
4784 &last_component_newname, &sbuf2);
4785 if (!NT_STATUS_IS_OK(status)) {
4789 status = check_name(conn, newname);
4790 if (!NT_STATUS_IS_OK(status)) {
4794 /* Disallow if newname already exists. */
4795 if (VALID_STAT(sbuf2)) {
4796 return NT_STATUS_OBJECT_NAME_COLLISION;
4799 /* No links from a directory. */
4800 if (S_ISDIR(sbuf1.st_mode)) {
4801 return NT_STATUS_FILE_IS_A_DIRECTORY;
4804 /* Ensure this is within the share. */
4805 status = check_reduced_name(conn, oldname);
4806 if (!NT_STATUS_IS_OK(status)) {
4810 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4812 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4813 status = map_nt_error_from_unix(errno);
4814 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4815 nt_errstr(status), newname, oldname));
4821 /****************************************************************************
4822 Deal with setting the time from any of the setfilepathinfo functions.
4823 ****************************************************************************/
4825 NTSTATUS smb_set_file_time(connection_struct *conn,
4828 const SMB_STRUCT_STAT *psbuf,
4829 struct timespec ts[2],
4830 bool setting_write_time)
4833 FILE_NOTIFY_CHANGE_LAST_ACCESS
4834 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4836 if (!VALID_STAT(*psbuf)) {
4837 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4840 /* get some defaults (no modifications) if any info is zero or -1. */
4841 if (null_timespec(ts[0])) {
4842 ts[0] = get_atimespec(psbuf);
4843 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4846 if (null_timespec(ts[1])) {
4847 ts[1] = get_mtimespec(psbuf);
4848 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4851 if (!setting_write_time) {
4852 /* ts[1] comes from change time, not write time. */
4853 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4856 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4857 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4860 * Try and set the times of this file if
4861 * they are different from the current values.
4865 struct timespec mts = get_mtimespec(psbuf);
4866 struct timespec ats = get_atimespec(psbuf);
4867 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4868 return NT_STATUS_OK;
4872 if (setting_write_time) {
4874 * This was a setfileinfo on an open file.
4875 * NT does this a lot. We also need to
4876 * set the time here, as it can be read by
4877 * FindFirst/FindNext and with the patch for bug #2045
4878 * in smbd/fileio.c it ensures that this timestamp is
4879 * kept sticky even after a write. We save the request
4880 * away and will set it on file close and after a write. JRA.
4883 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4884 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4887 set_write_time_fsp(fsp, ts[1], true);
4889 set_write_time_path(conn, fname,
4890 vfs_file_id_from_sbuf(conn, psbuf),
4895 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4897 if(file_ntimes(conn, fname, ts)!=0) {
4898 return map_nt_error_from_unix(errno);
4900 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4902 return NT_STATUS_OK;
4905 /****************************************************************************
4906 Deal with setting the dosmode from any of the setfilepathinfo functions.
4907 ****************************************************************************/
4909 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4911 SMB_STRUCT_STAT *psbuf,
4914 if (!VALID_STAT(*psbuf)) {
4915 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4919 if (S_ISDIR(psbuf->st_mode)) {
4926 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4928 /* check the mode isn't different, before changing it */
4929 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4931 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4932 fname, (unsigned int)dosmode ));
4934 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4935 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4936 fname, strerror(errno)));
4937 return map_nt_error_from_unix(errno);
4940 return NT_STATUS_OK;
4943 /****************************************************************************
4944 Deal with setting the size from any of the setfilepathinfo functions.
4945 ****************************************************************************/
4947 static NTSTATUS smb_set_file_size(connection_struct *conn,
4948 struct smb_request *req,
4951 SMB_STRUCT_STAT *psbuf,
4954 NTSTATUS status = NT_STATUS_OK;
4955 files_struct *new_fsp = NULL;
4957 if (!VALID_STAT(*psbuf)) {
4958 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4961 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4963 if (size == get_file_size(*psbuf)) {
4964 return NT_STATUS_OK;
4967 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4968 fname, (double)size ));
4970 if (fsp && fsp->fh->fd != -1) {
4971 /* Handle based call. */
4972 if (vfs_set_filelen(fsp, size) == -1) {
4973 return map_nt_error_from_unix(errno);
4975 return NT_STATUS_OK;
4978 status = open_file_ntcreate(conn, req, fname, psbuf,
4979 FILE_WRITE_ATTRIBUTES,
4980 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4983 FILE_ATTRIBUTE_NORMAL,
4984 FORCE_OPLOCK_BREAK_TO_NONE,
4987 if (!NT_STATUS_IS_OK(status)) {
4988 /* NB. We check for open_was_deferred in the caller. */
4992 if (vfs_set_filelen(new_fsp, size) == -1) {
4993 status = map_nt_error_from_unix(errno);
4994 close_file(new_fsp,NORMAL_CLOSE);
4998 close_file(new_fsp,NORMAL_CLOSE);
4999 return NT_STATUS_OK;
5002 /****************************************************************************
5003 Deal with SMB_INFO_SET_EA.
5004 ****************************************************************************/
5006 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5012 struct ea_list *ea_list = NULL;
5013 TALLOC_CTX *ctx = NULL;
5014 NTSTATUS status = NT_STATUS_OK;
5016 if (total_data < 10) {
5018 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5019 length. They seem to have no effect. Bug #3212. JRA */
5021 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5022 /* We're done. We only get EA info in this call. */
5023 return NT_STATUS_OK;
5026 return NT_STATUS_INVALID_PARAMETER;
5029 if (IVAL(pdata,0) > total_data) {
5030 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5031 IVAL(pdata,0), (unsigned int)total_data));
5032 return NT_STATUS_INVALID_PARAMETER;
5036 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5038 return NT_STATUS_INVALID_PARAMETER;
5040 status = set_ea(conn, fsp, fname, ea_list);
5045 /****************************************************************************
5046 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5047 ****************************************************************************/
5049 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5054 SMB_STRUCT_STAT *psbuf)
5056 NTSTATUS status = NT_STATUS_OK;
5057 bool delete_on_close;
5060 if (total_data < 1) {
5061 return NT_STATUS_INVALID_PARAMETER;
5065 return NT_STATUS_INVALID_HANDLE;
5068 delete_on_close = (CVAL(pdata,0) ? True : False);
5069 dosmode = dos_mode(conn, fname, psbuf);
5071 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5072 "delete_on_close = %u\n",
5074 (unsigned int)dosmode,
5075 (unsigned int)delete_on_close ));
5077 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5079 if (!NT_STATUS_IS_OK(status)) {
5083 /* The set is across all open files on this dev/inode pair. */
5084 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
5085 return NT_STATUS_ACCESS_DENIED;
5087 return NT_STATUS_OK;
5090 /****************************************************************************
5091 Deal with SMB_FILE_POSITION_INFORMATION.
5092 ****************************************************************************/
5094 static NTSTATUS smb_file_position_information(connection_struct *conn,
5099 SMB_BIG_UINT position_information;
5101 if (total_data < 8) {
5102 return NT_STATUS_INVALID_PARAMETER;
5106 /* Ignore on pathname based set. */
5107 return NT_STATUS_OK;
5110 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5111 #ifdef LARGE_SMB_OFF_T
5112 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5113 #else /* LARGE_SMB_OFF_T */
5114 if (IVAL(pdata,4) != 0) {
5115 /* more than 32 bits? */
5116 return NT_STATUS_INVALID_PARAMETER;
5118 #endif /* LARGE_SMB_OFF_T */
5120 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5121 fsp->fsp_name, (double)position_information ));
5122 fsp->fh->position_information = position_information;
5123 return NT_STATUS_OK;
5126 /****************************************************************************
5127 Deal with SMB_FILE_MODE_INFORMATION.
5128 ****************************************************************************/
5130 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5136 if (total_data < 4) {
5137 return NT_STATUS_INVALID_PARAMETER;
5139 mode = IVAL(pdata,0);
5140 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5141 return NT_STATUS_INVALID_PARAMETER;
5143 return NT_STATUS_OK;
5146 /****************************************************************************
5147 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5148 ****************************************************************************/
5150 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5151 struct smb_request *req,
5156 char *link_target = NULL;
5157 const char *newname = fname;
5158 NTSTATUS status = NT_STATUS_OK;
5159 TALLOC_CTX *ctx = talloc_tos();
5161 /* Set a symbolic link. */
5162 /* Don't allow this if follow links is false. */
5164 if (total_data == 0) {
5165 return NT_STATUS_INVALID_PARAMETER;
5168 if (!lp_symlinks(SNUM(conn))) {
5169 return NT_STATUS_ACCESS_DENIED;
5172 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5173 total_data, STR_TERMINATE);
5176 return NT_STATUS_INVALID_PARAMETER;
5179 /* !widelinks forces the target path to be within the share. */
5180 /* This means we can interpret the target as a pathname. */
5181 if (!lp_widelinks(SNUM(conn))) {
5182 char *rel_name = NULL;
5183 char *last_dirp = NULL;
5185 if (*link_target == '/') {
5186 /* No absolute paths allowed. */
5187 return NT_STATUS_ACCESS_DENIED;
5189 rel_name = talloc_strdup(ctx,newname);
5191 return NT_STATUS_NO_MEMORY;
5193 last_dirp = strrchr_m(rel_name, '/');
5195 last_dirp[1] = '\0';
5197 rel_name = talloc_strdup(ctx,"./");
5199 return NT_STATUS_NO_MEMORY;
5202 rel_name = talloc_asprintf_append(rel_name,
5206 return NT_STATUS_NO_MEMORY;
5209 status = check_name(conn, rel_name);
5210 if (!NT_STATUS_IS_OK(status)) {
5215 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5216 newname, link_target ));
5218 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5219 return map_nt_error_from_unix(errno);
5222 return NT_STATUS_OK;
5225 /****************************************************************************
5226 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5227 ****************************************************************************/
5229 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5230 struct smb_request *req,
5231 const char *pdata, int total_data,
5234 char *oldname = NULL;
5235 TALLOC_CTX *ctx = talloc_tos();
5236 NTSTATUS status = NT_STATUS_OK;
5238 /* Set a hard link. */
5239 if (total_data == 0) {
5240 return NT_STATUS_INVALID_PARAMETER;
5243 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5244 total_data, STR_TERMINATE, &status);
5245 if (!NT_STATUS_IS_OK(status)) {
5249 status = resolve_dfspath(ctx, conn,
5250 req->flags2 & FLAGS2_DFS_PATHNAMES,
5253 if (!NT_STATUS_IS_OK(status)) {
5257 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5260 return hardlink_internals(ctx, conn, oldname, fname);
5263 /****************************************************************************
5264 Deal with SMB_FILE_RENAME_INFORMATION.
5265 ****************************************************************************/
5267 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5268 struct smb_request *req,
5277 char *newname = NULL;
5278 char *base_name = NULL;
5279 bool dest_has_wcard = False;
5280 NTSTATUS status = NT_STATUS_OK;
5282 TALLOC_CTX *ctx = talloc_tos();
5284 if (total_data < 13) {
5285 return NT_STATUS_INVALID_PARAMETER;
5288 overwrite = (CVAL(pdata,0) ? True : False);
5289 root_fid = IVAL(pdata,4);
5290 len = IVAL(pdata,8);
5292 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5293 return NT_STATUS_INVALID_PARAMETER;
5296 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5299 if (!NT_STATUS_IS_OK(status)) {
5303 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5306 status = resolve_dfspath_wcard(ctx, conn,
5307 req->flags2 & FLAGS2_DFS_PATHNAMES,
5311 if (!NT_STATUS_IS_OK(status)) {
5315 /* Check the new name has no '/' characters. */
5316 if (strchr_m(newname, '/')) {
5317 return NT_STATUS_NOT_SUPPORTED;
5320 /* Create the base directory. */
5321 base_name = talloc_strdup(ctx, fname);
5323 return NT_STATUS_NO_MEMORY;
5325 p = strrchr_m(base_name, '/');
5329 base_name = talloc_strdup(ctx, "./");
5331 return NT_STATUS_NO_MEMORY;
5334 /* Append the new name. */
5335 base_name = talloc_asprintf_append(base_name,
5339 return NT_STATUS_NO_MEMORY;
5343 SMB_STRUCT_STAT sbuf;
5344 char *newname_last_component = NULL;
5348 status = unix_convert(ctx, conn, newname, False,
5350 &newname_last_component,
5353 /* If an error we expect this to be
5354 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5356 if (!NT_STATUS_IS_OK(status)
5357 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5362 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5363 fsp->fnum, fsp->fsp_name, base_name ));
5364 status = rename_internals_fsp(conn, fsp, base_name,
5365 newname_last_component, 0,
5368 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5369 fname, base_name ));
5370 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5371 overwrite, False, dest_has_wcard,
5372 FILE_WRITE_ATTRIBUTES);
5378 /****************************************************************************
5379 Deal with SMB_SET_POSIX_ACL.
5380 ****************************************************************************/
5382 #if defined(HAVE_POSIX_ACLS)
5383 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5388 SMB_STRUCT_STAT *psbuf)
5390 uint16 posix_acl_version;
5391 uint16 num_file_acls;
5392 uint16 num_def_acls;
5393 bool valid_file_acls = True;
5394 bool valid_def_acls = True;
5396 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5397 return NT_STATUS_INVALID_PARAMETER;
5399 posix_acl_version = SVAL(pdata,0);
5400 num_file_acls = SVAL(pdata,2);
5401 num_def_acls = SVAL(pdata,4);
5403 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5404 valid_file_acls = False;
5408 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5409 valid_def_acls = False;
5413 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5414 return NT_STATUS_INVALID_PARAMETER;
5417 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5418 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5419 return NT_STATUS_INVALID_PARAMETER;
5422 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5423 fname ? fname : fsp->fsp_name,
5424 (unsigned int)num_file_acls,
5425 (unsigned int)num_def_acls));
5427 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5428 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5429 return map_nt_error_from_unix(errno);
5432 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5433 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5434 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5435 return map_nt_error_from_unix(errno);
5437 return NT_STATUS_OK;
5441 /****************************************************************************
5442 Deal with SMB_SET_POSIX_LOCK.
5443 ****************************************************************************/
5445 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5446 const struct smb_request *req,
5452 SMB_BIG_UINT offset;
5454 bool blocking_lock = False;
5455 enum brl_type lock_type;
5457 NTSTATUS status = NT_STATUS_OK;
5459 if (fsp == NULL || fsp->fh->fd == -1) {
5460 return NT_STATUS_INVALID_HANDLE;
5463 if (total_data != POSIX_LOCK_DATA_SIZE) {
5464 return NT_STATUS_INVALID_PARAMETER;
5467 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5468 case POSIX_LOCK_TYPE_READ:
5469 lock_type = READ_LOCK;
5471 case POSIX_LOCK_TYPE_WRITE:
5472 /* Return the right POSIX-mappable error code for files opened read-only. */
5473 if (!fsp->can_write) {
5474 return NT_STATUS_INVALID_HANDLE;
5476 lock_type = WRITE_LOCK;
5478 case POSIX_LOCK_TYPE_UNLOCK:
5479 lock_type = UNLOCK_LOCK;
5482 return NT_STATUS_INVALID_PARAMETER;
5485 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5486 blocking_lock = False;
5487 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5488 blocking_lock = True;
5490 return NT_STATUS_INVALID_PARAMETER;
5493 if (!lp_blocking_locks(SNUM(conn))) {
5494 blocking_lock = False;
5497 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5498 #if defined(HAVE_LONGLONG)
5499 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5500 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5501 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5502 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5503 #else /* HAVE_LONGLONG */
5504 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5505 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5506 #endif /* HAVE_LONGLONG */
5508 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5509 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5511 (unsigned int)lock_type,
5512 (unsigned int)lock_pid,
5516 if (lock_type == UNLOCK_LOCK) {
5517 status = do_unlock(smbd_messaging_context(),
5524 uint32 block_smbpid;
5526 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5537 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5539 * A blocking lock was requested. Package up
5540 * this smb into a queued request and push it
5541 * onto the blocking lock queue.
5543 if(push_blocking_lock_request(br_lck,
5546 -1, /* infinite timeout. */
5554 TALLOC_FREE(br_lck);
5558 TALLOC_FREE(br_lck);
5564 /****************************************************************************
5565 Deal with SMB_INFO_STANDARD.
5566 ****************************************************************************/
5568 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5573 const SMB_STRUCT_STAT *psbuf)
5575 struct timespec ts[2];
5577 if (total_data < 12) {
5578 return NT_STATUS_INVALID_PARAMETER;
5582 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5584 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5586 DEBUG(10,("smb_set_info_standard: file %s\n",
5587 fname ? fname : fsp->fsp_name ));
5589 return smb_set_file_time(conn,
5597 /****************************************************************************
5598 Deal with SMB_SET_FILE_BASIC_INFO.
5599 ****************************************************************************/
5601 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5606 SMB_STRUCT_STAT *psbuf)
5608 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5609 struct timespec write_time;
5610 struct timespec changed_time;
5612 struct timespec ts[2];
5613 NTSTATUS status = NT_STATUS_OK;
5614 bool setting_write_time = true;
5616 if (total_data < 36) {
5617 return NT_STATUS_INVALID_PARAMETER;
5620 /* Set the attributes */
5621 dosmode = IVAL(pdata,32);
5622 status = smb_set_file_dosmode(conn,
5626 if (!NT_STATUS_IS_OK(status)) {
5630 /* Ignore create time at offset pdata. */
5633 ts[0] = interpret_long_date(pdata+8);
5635 write_time = interpret_long_date(pdata+16);
5636 changed_time = interpret_long_date(pdata+24);
5639 ts[1] = timespec_min(&write_time, &changed_time);
5641 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5645 /* Prefer a defined time to an undefined one. */
5646 if (null_timespec(ts[1])) {
5647 if (null_timespec(write_time)) {
5648 ts[1] = changed_time;
5649 setting_write_time = false;
5655 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5656 fname ? fname : fsp->fsp_name ));
5658 return smb_set_file_time(conn,
5663 setting_write_time);
5666 /****************************************************************************
5667 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5668 ****************************************************************************/
5670 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5671 struct smb_request *req,
5676 SMB_STRUCT_STAT *psbuf)
5678 SMB_BIG_UINT allocation_size = 0;
5679 NTSTATUS status = NT_STATUS_OK;
5680 files_struct *new_fsp = NULL;
5682 if (!VALID_STAT(*psbuf)) {
5683 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5686 if (total_data < 8) {
5687 return NT_STATUS_INVALID_PARAMETER;
5690 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5691 #ifdef LARGE_SMB_OFF_T
5692 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5693 #else /* LARGE_SMB_OFF_T */
5694 if (IVAL(pdata,4) != 0) {
5695 /* more than 32 bits? */
5696 return NT_STATUS_INVALID_PARAMETER;
5698 #endif /* LARGE_SMB_OFF_T */
5700 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5701 fname, (double)allocation_size ));
5703 if (allocation_size) {
5704 allocation_size = smb_roundup(conn, allocation_size);
5707 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5708 fname, (double)allocation_size ));
5710 if (fsp && fsp->fh->fd != -1) {
5711 /* Open file handle. */
5712 /* Only change if needed. */
5713 if (allocation_size != get_file_size(*psbuf)) {
5714 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5715 return map_nt_error_from_unix(errno);
5718 /* But always update the time. */
5720 * This is equivalent to a write. Ensure it's seen immediately
5721 * if there are no pending writes.
5723 trigger_write_time_update(fsp);
5724 return NT_STATUS_OK;
5727 /* Pathname or stat or directory file. */
5729 status = open_file_ntcreate(conn, req, fname, psbuf,
5731 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5734 FILE_ATTRIBUTE_NORMAL,
5735 FORCE_OPLOCK_BREAK_TO_NONE,
5738 if (!NT_STATUS_IS_OK(status)) {
5739 /* NB. We check for open_was_deferred in the caller. */
5743 /* Only change if needed. */
5744 if (allocation_size != get_file_size(*psbuf)) {
5745 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5746 status = map_nt_error_from_unix(errno);
5747 close_file(new_fsp,NORMAL_CLOSE);
5752 /* Changing the allocation size should set the last mod time. */
5754 * This is equivalent to a write. Ensure it's seen immediately
5755 * if there are no pending writes.
5757 trigger_write_time_update(new_fsp);
5759 close_file(new_fsp,NORMAL_CLOSE);
5760 return NT_STATUS_OK;
5763 /****************************************************************************
5764 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5765 ****************************************************************************/
5767 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5768 struct smb_request *req,
5773 SMB_STRUCT_STAT *psbuf)
5777 if (total_data < 8) {
5778 return NT_STATUS_INVALID_PARAMETER;
5781 size = IVAL(pdata,0);
5782 #ifdef LARGE_SMB_OFF_T
5783 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5784 #else /* LARGE_SMB_OFF_T */
5785 if (IVAL(pdata,4) != 0) {
5786 /* more than 32 bits? */
5787 return NT_STATUS_INVALID_PARAMETER;
5789 #endif /* LARGE_SMB_OFF_T */
5790 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5791 "file %s to %.0f\n", fname, (double)size ));
5793 return smb_set_file_size(conn, req,
5800 /****************************************************************************
5801 Allow a UNIX info mknod.
5802 ****************************************************************************/
5804 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5808 SMB_STRUCT_STAT *psbuf)
5810 uint32 file_type = IVAL(pdata,56);
5811 #if defined(HAVE_MAKEDEV)
5812 uint32 dev_major = IVAL(pdata,60);
5813 uint32 dev_minor = IVAL(pdata,68);
5815 SMB_DEV_T dev = (SMB_DEV_T)0;
5816 uint32 raw_unixmode = IVAL(pdata,84);
5820 if (total_data < 100) {
5821 return NT_STATUS_INVALID_PARAMETER;
5824 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5825 if (!NT_STATUS_IS_OK(status)) {
5829 #if defined(HAVE_MAKEDEV)
5830 dev = makedev(dev_major, dev_minor);
5833 switch (file_type) {
5834 #if defined(S_IFIFO)
5835 case UNIX_TYPE_FIFO:
5836 unixmode |= S_IFIFO;
5839 #if defined(S_IFSOCK)
5840 case UNIX_TYPE_SOCKET:
5841 unixmode |= S_IFSOCK;
5844 #if defined(S_IFCHR)
5845 case UNIX_TYPE_CHARDEV:
5846 unixmode |= S_IFCHR;
5849 #if defined(S_IFBLK)
5850 case UNIX_TYPE_BLKDEV:
5851 unixmode |= S_IFBLK;
5855 return NT_STATUS_INVALID_PARAMETER;
5858 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5859 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5861 /* Ok - do the mknod. */
5862 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5863 return map_nt_error_from_unix(errno);
5866 /* If any of the other "set" calls fail we
5867 * don't want to end up with a half-constructed mknod.
5870 if (lp_inherit_perms(SNUM(conn))) {
5871 inherit_access_posix_acl(
5872 conn, parent_dirname(fname),
5876 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5877 status = map_nt_error_from_unix(errno);
5878 SMB_VFS_UNLINK(conn,fname);
5881 return NT_STATUS_OK;
5884 /****************************************************************************
5885 Deal with SMB_SET_FILE_UNIX_BASIC.
5886 ****************************************************************************/
5888 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5889 struct smb_request *req,
5894 SMB_STRUCT_STAT *psbuf)
5896 struct timespec ts[2];
5897 uint32 raw_unixmode;
5900 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5901 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5902 NTSTATUS status = NT_STATUS_OK;
5903 bool delete_on_fail = False;
5904 enum perm_type ptype;
5906 if (total_data < 100) {
5907 return NT_STATUS_INVALID_PARAMETER;
5910 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5911 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5912 size=IVAL(pdata,0); /* first 8 Bytes are size */
5913 #ifdef LARGE_SMB_OFF_T
5914 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5915 #else /* LARGE_SMB_OFF_T */
5916 if (IVAL(pdata,4) != 0) {
5917 /* more than 32 bits? */
5918 return NT_STATUS_INVALID_PARAMETER;
5920 #endif /* LARGE_SMB_OFF_T */
5923 ts[0] = interpret_long_date(pdata+24); /* access_time */
5924 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5925 set_owner = (uid_t)IVAL(pdata,40);
5926 set_grp = (gid_t)IVAL(pdata,48);
5927 raw_unixmode = IVAL(pdata,84);
5929 if (VALID_STAT(*psbuf)) {
5930 if (S_ISDIR(psbuf->st_mode)) {
5931 ptype = PERM_EXISTING_DIR;
5933 ptype = PERM_EXISTING_FILE;
5936 ptype = PERM_NEW_FILE;
5939 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5940 if (!NT_STATUS_IS_OK(status)) {
5944 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5945 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5946 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5948 if (!VALID_STAT(*psbuf)) {
5950 * The only valid use of this is to create character and block
5951 * devices, and named pipes. This is deprecated (IMHO) and
5952 * a new info level should be used for mknod. JRA.
5955 status = smb_unix_mknod(conn,
5960 if (!NT_STATUS_IS_OK(status)) {
5964 /* Ensure we don't try and change anything else. */
5965 raw_unixmode = SMB_MODE_NO_CHANGE;
5966 size = get_file_size(*psbuf);
5967 ts[0] = get_atimespec(psbuf);
5968 ts[1] = get_mtimespec(psbuf);
5970 * We continue here as we might want to change the
5973 delete_on_fail = True;
5977 /* Horrible backwards compatibility hack as an old server bug
5978 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5982 size = get_file_size(*psbuf);
5987 * Deal with the UNIX specific mode set.
5990 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5991 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5992 (unsigned int)unixmode, fname ));
5993 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5994 return map_nt_error_from_unix(errno);
5999 * Deal with the UNIX specific uid set.
6002 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6005 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6006 (unsigned int)set_owner, fname ));
6008 if (S_ISLNK(psbuf->st_mode)) {
6009 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6011 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6015 status = map_nt_error_from_unix(errno);
6016 if (delete_on_fail) {
6017 SMB_VFS_UNLINK(conn,fname);
6024 * Deal with the UNIX specific gid set.
6027 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6028 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6029 (unsigned int)set_owner, fname ));
6030 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6031 status = map_nt_error_from_unix(errno);
6032 if (delete_on_fail) {
6033 SMB_VFS_UNLINK(conn,fname);
6039 /* Deal with any size changes. */
6041 status = smb_set_file_size(conn, req,
6046 if (!NT_STATUS_IS_OK(status)) {
6050 /* Deal with any time changes. */
6052 return smb_set_file_time(conn,
6060 /****************************************************************************
6061 Deal with SMB_SET_FILE_UNIX_INFO2.
6062 ****************************************************************************/
6064 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6065 struct smb_request *req,
6070 SMB_STRUCT_STAT *psbuf)
6076 if (total_data < 116) {
6077 return NT_STATUS_INVALID_PARAMETER;
6080 /* Start by setting all the fields that are common between UNIX_BASIC
6083 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6085 if (!NT_STATUS_IS_OK(status)) {
6089 smb_fflags = IVAL(pdata, 108);
6090 smb_fmask = IVAL(pdata, 112);
6092 /* NB: We should only attempt to alter the file flags if the client
6093 * sends a non-zero mask.
6095 if (smb_fmask != 0) {
6096 int stat_fflags = 0;
6098 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6100 /* Client asked to alter a flag we don't understand. */
6101 return NT_STATUS_INVALID_PARAMETER;
6104 if (fsp && fsp->fh->fd != -1) {
6105 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6106 return NT_STATUS_NOT_SUPPORTED;
6108 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6109 return map_nt_error_from_unix(errno);
6114 /* XXX: need to add support for changing the create_time here. You
6115 * can do this for paths on Darwin with setattrlist(2). The right way
6116 * to hook this up is probably by extending the VFS utimes interface.
6119 return NT_STATUS_OK;
6122 /****************************************************************************
6123 Create a directory with POSIX semantics.
6124 ****************************************************************************/
6126 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6127 struct smb_request *req,
6131 SMB_STRUCT_STAT *psbuf,
6132 int *pdata_return_size)
6134 NTSTATUS status = NT_STATUS_OK;
6135 uint32 raw_unixmode = 0;
6136 uint32 mod_unixmode = 0;
6137 mode_t unixmode = (mode_t)0;
6138 files_struct *fsp = NULL;
6139 uint16 info_level_return = 0;
6141 char *pdata = *ppdata;
6143 if (total_data < 18) {
6144 return NT_STATUS_INVALID_PARAMETER;
6147 raw_unixmode = IVAL(pdata,8);
6148 /* Next 4 bytes are not yet defined. */
6150 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6151 if (!NT_STATUS_IS_OK(status)) {
6155 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6157 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6158 fname, (unsigned int)unixmode ));
6160 status = open_directory(conn, req,
6163 FILE_READ_ATTRIBUTES, /* Just a stat open */
6164 FILE_SHARE_NONE, /* Ignored for stat opens */
6171 if (NT_STATUS_IS_OK(status)) {
6172 close_file(fsp, NORMAL_CLOSE);
6175 info_level_return = SVAL(pdata,16);
6177 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6178 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6179 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6180 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6182 *pdata_return_size = 12;
6185 /* Realloc the data size */
6186 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6187 if (*ppdata == NULL) {
6188 *pdata_return_size = 0;
6189 return NT_STATUS_NO_MEMORY;
6193 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6194 SSVAL(pdata,2,0); /* No fnum. */
6195 SIVAL(pdata,4,info); /* Was directory created. */
6197 switch (info_level_return) {
6198 case SMB_QUERY_FILE_UNIX_BASIC:
6199 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6200 SSVAL(pdata,10,0); /* Padding. */
6201 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6203 case SMB_QUERY_FILE_UNIX_INFO2:
6204 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6205 SSVAL(pdata,10,0); /* Padding. */
6206 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6209 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6210 SSVAL(pdata,10,0); /* Padding. */
6217 /****************************************************************************
6218 Open/Create a file with POSIX semantics.
6219 ****************************************************************************/
6221 static NTSTATUS smb_posix_open(connection_struct *conn,
6222 struct smb_request *req,
6226 SMB_STRUCT_STAT *psbuf,
6227 int *pdata_return_size)
6229 bool extended_oplock_granted = False;
6230 char *pdata = *ppdata;
6232 uint32 wire_open_mode = 0;
6233 uint32 raw_unixmode = 0;
6234 uint32 mod_unixmode = 0;
6235 uint32 create_disp = 0;
6236 uint32 access_mask = 0;
6237 uint32 create_options = 0;
6238 NTSTATUS status = NT_STATUS_OK;
6239 mode_t unixmode = (mode_t)0;
6240 files_struct *fsp = NULL;
6241 int oplock_request = 0;
6243 uint16 info_level_return = 0;
6245 if (total_data < 18) {
6246 return NT_STATUS_INVALID_PARAMETER;
6249 flags = IVAL(pdata,0);
6250 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6251 if (oplock_request) {
6252 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6255 wire_open_mode = IVAL(pdata,4);
6257 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6258 return smb_posix_mkdir(conn, req,
6266 switch (wire_open_mode & SMB_ACCMODE) {
6268 access_mask = FILE_READ_DATA;
6271 access_mask = FILE_WRITE_DATA;
6274 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6277 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6278 (unsigned int)wire_open_mode ));
6279 return NT_STATUS_INVALID_PARAMETER;
6282 wire_open_mode &= ~SMB_ACCMODE;
6284 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6285 create_disp = FILE_CREATE;
6286 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6287 create_disp = FILE_OVERWRITE_IF;
6288 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6289 create_disp = FILE_OPEN_IF;
6291 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6292 (unsigned int)wire_open_mode ));
6293 return NT_STATUS_INVALID_PARAMETER;
6296 raw_unixmode = IVAL(pdata,8);
6297 /* Next 4 bytes are not yet defined. */
6299 status = unix_perms_from_wire(conn,
6302 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6305 if (!NT_STATUS_IS_OK(status)) {
6309 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6311 if (wire_open_mode & SMB_O_SYNC) {
6312 create_options |= FILE_WRITE_THROUGH;
6314 if (wire_open_mode & SMB_O_APPEND) {
6315 access_mask |= FILE_APPEND_DATA;
6317 if (wire_open_mode & SMB_O_DIRECT) {
6318 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6321 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6323 (unsigned int)wire_open_mode,
6324 (unsigned int)unixmode ));
6326 status = open_file_ntcreate(conn, req,
6330 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6332 0, /* no create options yet. */
6338 if (!NT_STATUS_IS_OK(status)) {
6342 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6343 extended_oplock_granted = True;
6346 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6347 extended_oplock_granted = True;
6350 info_level_return = SVAL(pdata,16);
6352 /* Allocate the correct return size. */
6354 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6355 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6356 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6357 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6359 *pdata_return_size = 12;
6362 /* Realloc the data size */
6363 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6364 if (*ppdata == NULL) {
6365 close_file(fsp,ERROR_CLOSE);
6366 *pdata_return_size = 0;
6367 return NT_STATUS_NO_MEMORY;
6371 if (extended_oplock_granted) {
6372 if (flags & REQUEST_BATCH_OPLOCK) {
6373 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6375 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6377 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6378 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6380 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6383 SSVAL(pdata,2,fsp->fnum);
6384 SIVAL(pdata,4,info); /* Was file created etc. */
6386 switch (info_level_return) {
6387 case SMB_QUERY_FILE_UNIX_BASIC:
6388 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6389 SSVAL(pdata,10,0); /* padding. */
6390 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6392 case SMB_QUERY_FILE_UNIX_INFO2:
6393 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6394 SSVAL(pdata,10,0); /* padding. */
6395 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6398 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6399 SSVAL(pdata,10,0); /* padding. */
6402 return NT_STATUS_OK;
6405 /****************************************************************************
6406 Delete a file with POSIX semantics.
6407 ****************************************************************************/
6409 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6410 struct smb_request *req,
6414 SMB_STRUCT_STAT *psbuf)
6416 NTSTATUS status = NT_STATUS_OK;
6417 files_struct *fsp = NULL;
6422 struct share_mode_lock *lck = NULL;
6424 if (total_data < 2) {
6425 return NT_STATUS_INVALID_PARAMETER;
6428 flags = SVAL(pdata,0);
6430 if (!VALID_STAT(*psbuf)) {
6431 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6434 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6435 !VALID_STAT_OF_DIR(*psbuf)) {
6436 return NT_STATUS_NOT_A_DIRECTORY;
6439 DEBUG(10,("smb_posix_unlink: %s %s\n",
6440 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6443 if (VALID_STAT_OF_DIR(*psbuf)) {
6444 status = open_directory(conn, req,
6448 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6451 FILE_FLAG_POSIX_SEMANTICS|0777,
6456 status = open_file_ntcreate(conn, req,
6460 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6463 FILE_FLAG_POSIX_SEMANTICS|0777,
6464 0, /* No oplock, but break existing ones. */
6469 if (!NT_STATUS_IS_OK(status)) {
6474 * Don't lie to client. If we can't really delete due to
6475 * non-POSIX opens return SHARING_VIOLATION.
6478 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6481 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6482 "lock for file %s\n", fsp->fsp_name));
6483 close_file(fsp, NORMAL_CLOSE);
6484 return NT_STATUS_INVALID_PARAMETER;
6488 * See if others still have the file open. If this is the case, then
6489 * don't delete. If all opens are POSIX delete we can set the delete
6490 * on close disposition.
6492 for (i=0; i<lck->num_share_modes; i++) {
6493 struct share_mode_entry *e = &lck->share_modes[i];
6494 if (is_valid_share_mode_entry(e)) {
6495 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6498 /* Fail with sharing violation. */
6499 close_file(fsp, NORMAL_CLOSE);
6501 return NT_STATUS_SHARING_VIOLATION;
6506 * Set the delete on close.
6508 status = smb_set_file_disposition_info(conn,
6515 if (!NT_STATUS_IS_OK(status)) {
6516 close_file(fsp, NORMAL_CLOSE);
6521 return close_file(fsp, NORMAL_CLOSE);
6524 /****************************************************************************
6525 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6526 ****************************************************************************/
6528 static void call_trans2setfilepathinfo(connection_struct *conn,
6529 struct smb_request *req,
6530 unsigned int tran_call,
6531 char **pparams, int total_params,
6532 char **ppdata, int total_data,
6533 unsigned int max_data_bytes)
6535 char *params = *pparams;
6536 char *pdata = *ppdata;
6538 SMB_STRUCT_STAT sbuf;
6540 files_struct *fsp = NULL;
6541 NTSTATUS status = NT_STATUS_OK;
6542 int data_return_size = 0;
6543 TALLOC_CTX *ctx = talloc_tos();
6546 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6552 if (tran_call == TRANSACT2_SETFILEINFO) {
6553 if (total_params < 4) {
6554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6558 fsp = file_fsp(SVAL(params,0));
6559 /* Basic check for non-null fsp. */
6560 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6563 info_level = SVAL(params,2);
6565 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6567 reply_nterror(req, NT_STATUS_NO_MEMORY);
6571 if(fsp->is_directory || fsp->fh->fd == -1) {
6573 * This is actually a SETFILEINFO on a directory
6574 * handle (returned from an NT SMB). NT5.0 seems
6575 * to do this call. JRA.
6577 if (INFO_LEVEL_IS_UNIX(info_level)) {
6578 /* Always do lstat for UNIX calls. */
6579 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6580 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6581 reply_unixerror(req,ERRDOS,ERRbadpath);
6585 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6586 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6587 reply_unixerror(req,ERRDOS,ERRbadpath);
6591 } else if (fsp->print_file) {
6593 * Doing a DELETE_ON_CLOSE should cancel a print job.
6595 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6596 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6598 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6601 send_trans2_replies(conn, req, params, 2,
6606 reply_unixerror(req, ERRDOS, ERRbadpath);
6611 * Original code - this is an open file.
6613 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6617 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6618 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6619 reply_unixerror(req, ERRDOS, ERRbadfid);
6625 if (total_params < 7) {
6626 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6630 info_level = SVAL(params,0);
6631 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6632 total_params - 6, STR_TERMINATE,
6634 if (!NT_STATUS_IS_OK(status)) {
6635 reply_nterror(req, status);
6639 status = resolve_dfspath(ctx, conn,
6640 req->flags2 & FLAGS2_DFS_PATHNAMES,
6643 if (!NT_STATUS_IS_OK(status)) {
6644 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6645 reply_botherror(req,
6646 NT_STATUS_PATH_NOT_COVERED,
6647 ERRSRV, ERRbadpath);
6650 reply_nterror(req, status);
6654 status = unix_convert(ctx, conn, fname, False,
6655 &fname, NULL, &sbuf);
6656 if (!NT_STATUS_IS_OK(status)) {
6657 reply_nterror(req, status);
6661 status = check_name(conn, fname);
6662 if (!NT_STATUS_IS_OK(status)) {
6663 reply_nterror(req, status);
6667 if (INFO_LEVEL_IS_UNIX(info_level)) {
6669 * For CIFS UNIX extensions the target name may not exist.
6672 /* Always do lstat for UNIX calls. */
6673 SMB_VFS_LSTAT(conn,fname,&sbuf);
6675 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6676 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6677 reply_unixerror(req, ERRDOS, ERRbadpath);
6682 if (!CAN_WRITE(conn)) {
6683 reply_doserror(req, ERRSRV, ERRaccess);
6687 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6688 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6692 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6693 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6695 /* Realloc the parameter size */
6696 *pparams = (char *)SMB_REALLOC(*pparams,2);
6697 if (*pparams == NULL) {
6698 reply_nterror(req, NT_STATUS_NO_MEMORY);
6705 switch (info_level) {
6707 case SMB_INFO_STANDARD:
6709 status = smb_set_info_standard(conn,
6718 case SMB_INFO_SET_EA:
6720 status = smb_info_set_ea(conn,
6728 case SMB_SET_FILE_BASIC_INFO:
6729 case SMB_FILE_BASIC_INFORMATION:
6731 status = smb_set_file_basic_info(conn,
6740 case SMB_FILE_ALLOCATION_INFORMATION:
6741 case SMB_SET_FILE_ALLOCATION_INFO:
6743 status = smb_set_file_allocation_info(conn, req,
6752 case SMB_FILE_END_OF_FILE_INFORMATION:
6753 case SMB_SET_FILE_END_OF_FILE_INFO:
6755 status = smb_set_file_end_of_file_info(conn, req,
6764 case SMB_FILE_DISPOSITION_INFORMATION:
6765 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6768 /* JRA - We used to just ignore this on a path ?
6769 * Shouldn't this be invalid level on a pathname
6772 if (tran_call != TRANSACT2_SETFILEINFO) {
6773 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6776 status = smb_set_file_disposition_info(conn,
6785 case SMB_FILE_POSITION_INFORMATION:
6787 status = smb_file_position_information(conn,
6794 /* From tridge Samba4 :
6795 * MODE_INFORMATION in setfileinfo (I have no
6796 * idea what "mode information" on a file is - it takes a value of 0,
6797 * 2, 4 or 6. What could it be?).
6800 case SMB_FILE_MODE_INFORMATION:
6802 status = smb_file_mode_information(conn,
6809 * CIFS UNIX extensions.
6812 case SMB_SET_FILE_UNIX_BASIC:
6814 status = smb_set_file_unix_basic(conn, req,
6823 case SMB_SET_FILE_UNIX_INFO2:
6825 status = smb_set_file_unix_info2(conn, req,
6834 case SMB_SET_FILE_UNIX_LINK:
6836 if (tran_call != TRANSACT2_SETPATHINFO) {
6837 /* We must have a pathname for this. */
6838 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6841 status = smb_set_file_unix_link(conn, req, pdata,
6846 case SMB_SET_FILE_UNIX_HLINK:
6848 if (tran_call != TRANSACT2_SETPATHINFO) {
6849 /* We must have a pathname for this. */
6850 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6853 status = smb_set_file_unix_hlink(conn, req,
6859 case SMB_FILE_RENAME_INFORMATION:
6861 status = smb_file_rename_information(conn, req,
6867 #if defined(HAVE_POSIX_ACLS)
6868 case SMB_SET_POSIX_ACL:
6870 status = smb_set_posix_acl(conn,
6880 case SMB_SET_POSIX_LOCK:
6882 if (tran_call != TRANSACT2_SETFILEINFO) {
6883 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6886 status = smb_set_posix_lock(conn, req,
6887 pdata, total_data, fsp);
6891 case SMB_POSIX_PATH_OPEN:
6893 if (tran_call != TRANSACT2_SETPATHINFO) {
6894 /* We must have a pathname for this. */
6895 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6899 status = smb_posix_open(conn, req,
6908 case SMB_POSIX_PATH_UNLINK:
6910 if (tran_call != TRANSACT2_SETPATHINFO) {
6911 /* We must have a pathname for this. */
6912 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6916 status = smb_posix_unlink(conn, req,
6925 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6930 if (!NT_STATUS_IS_OK(status)) {
6931 if (open_was_deferred(req->mid)) {
6932 /* We have re-scheduled this call. */
6935 if (blocking_lock_was_deferred(req->mid)) {
6936 /* We have re-scheduled this call. */
6939 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6940 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6941 ERRSRV, ERRbadpath);
6944 if (info_level == SMB_POSIX_PATH_OPEN) {
6945 reply_openerror(req, status);
6949 reply_nterror(req, status);
6954 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6960 /****************************************************************************
6961 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6962 ****************************************************************************/
6964 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6965 char **pparams, int total_params,
6966 char **ppdata, int total_data,
6967 unsigned int max_data_bytes)
6969 char *params = *pparams;
6970 char *pdata = *ppdata;
6971 char *directory = NULL;
6972 SMB_STRUCT_STAT sbuf;
6973 NTSTATUS status = NT_STATUS_OK;
6974 struct ea_list *ea_list = NULL;
6975 TALLOC_CTX *ctx = talloc_tos();
6977 if (!CAN_WRITE(conn)) {
6978 reply_doserror(req, ERRSRV, ERRaccess);
6982 if (total_params < 5) {
6983 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6987 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6988 total_params - 4, STR_TERMINATE,
6990 if (!NT_STATUS_IS_OK(status)) {
6991 reply_nterror(req, status);
6995 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6997 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6998 if (!NT_STATUS_IS_OK(status)) {
6999 reply_nterror(req, status);
7003 status = check_name(conn, directory);
7004 if (!NT_STATUS_IS_OK(status)) {
7005 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7006 reply_nterror(req, status);
7010 /* Any data in this call is an EA list. */
7011 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7012 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7017 * OS/2 workplace shell seems to send SET_EA requests of "null"
7018 * length (4 bytes containing IVAL 4).
7019 * They seem to have no effect. Bug #3212. JRA.
7022 if (total_data != 4) {
7023 if (total_data < 10) {
7024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7028 if (IVAL(pdata,0) > total_data) {
7029 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7030 IVAL(pdata,0), (unsigned int)total_data));
7031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7035 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7038 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7041 } else if (IVAL(pdata,0) != 4) {
7042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7046 status = create_directory(conn, req, directory);
7048 if (!NT_STATUS_IS_OK(status)) {
7049 reply_nterror(req, status);
7053 /* Try and set any given EA. */
7055 status = set_ea(conn, NULL, directory, ea_list);
7056 if (!NT_STATUS_IS_OK(status)) {
7057 reply_nterror(req, status);
7062 /* Realloc the parameter and data sizes */
7063 *pparams = (char *)SMB_REALLOC(*pparams,2);
7064 if(*pparams == NULL) {
7065 reply_nterror(req, NT_STATUS_NO_MEMORY);
7072 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7077 /****************************************************************************
7078 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7079 We don't actually do this - we just send a null response.
7080 ****************************************************************************/
7082 static void call_trans2findnotifyfirst(connection_struct *conn,
7083 struct smb_request *req,
7084 char **pparams, int total_params,
7085 char **ppdata, int total_data,
7086 unsigned int max_data_bytes)
7088 static uint16 fnf_handle = 257;
7089 char *params = *pparams;
7092 if (total_params < 6) {
7093 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7097 info_level = SVAL(params,4);
7098 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7100 switch (info_level) {
7105 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7109 /* Realloc the parameter and data sizes */
7110 *pparams = (char *)SMB_REALLOC(*pparams,6);
7111 if (*pparams == NULL) {
7112 reply_nterror(req, NT_STATUS_NO_MEMORY);
7117 SSVAL(params,0,fnf_handle);
7118 SSVAL(params,2,0); /* No changes */
7119 SSVAL(params,4,0); /* No EA errors */
7126 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7131 /****************************************************************************
7132 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7133 changes). Currently this does nothing.
7134 ****************************************************************************/
7136 static void call_trans2findnotifynext(connection_struct *conn,
7137 struct smb_request *req,
7138 char **pparams, int total_params,
7139 char **ppdata, int total_data,
7140 unsigned int max_data_bytes)
7142 char *params = *pparams;
7144 DEBUG(3,("call_trans2findnotifynext\n"));
7146 /* Realloc the parameter and data sizes */
7147 *pparams = (char *)SMB_REALLOC(*pparams,4);
7148 if (*pparams == NULL) {
7149 reply_nterror(req, NT_STATUS_NO_MEMORY);
7154 SSVAL(params,0,0); /* No changes */
7155 SSVAL(params,2,0); /* No EA errors */
7157 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7162 /****************************************************************************
7163 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7164 ****************************************************************************/
7166 static void call_trans2getdfsreferral(connection_struct *conn,
7167 struct smb_request *req,
7168 char **pparams, int total_params,
7169 char **ppdata, int total_data,
7170 unsigned int max_data_bytes)
7172 char *params = *pparams;
7173 char *pathname = NULL;
7175 int max_referral_level;
7176 NTSTATUS status = NT_STATUS_OK;
7177 TALLOC_CTX *ctx = talloc_tos();
7179 DEBUG(10,("call_trans2getdfsreferral\n"));
7181 if (total_params < 3) {
7182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7186 max_referral_level = SVAL(params,0);
7188 if(!lp_host_msdfs()) {
7189 reply_doserror(req, ERRDOS, ERRbadfunc);
7193 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7194 total_params - 2, STR_TERMINATE);
7196 reply_nterror(req, NT_STATUS_NOT_FOUND);
7199 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7200 ppdata,&status)) < 0) {
7201 reply_nterror(req, status);
7205 SSVAL(req->inbuf, smb_flg2,
7206 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7207 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7212 #define LMCAT_SPL 0x53
7213 #define LMFUNC_GETJOBID 0x60
7215 /****************************************************************************
7216 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7217 ****************************************************************************/
7219 static void call_trans2ioctl(connection_struct *conn,
7220 struct smb_request *req,
7221 char **pparams, int total_params,
7222 char **ppdata, int total_data,
7223 unsigned int max_data_bytes)
7225 char *pdata = *ppdata;
7226 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7228 /* check for an invalid fid before proceeding */
7231 reply_doserror(req, ERRDOS, ERRbadfid);
7235 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7236 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7237 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7238 if (*ppdata == NULL) {
7239 reply_nterror(req, NT_STATUS_NO_MEMORY);
7244 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7245 CAN ACCEPT THIS IN UNICODE. JRA. */
7247 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7248 srvstr_push(pdata, req->flags2, pdata + 2,
7249 global_myname(), 15,
7250 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7251 srvstr_push(pdata, req->flags2, pdata+18,
7252 lp_servicename(SNUM(conn)), 13,
7253 STR_ASCII|STR_TERMINATE); /* Service name */
7254 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7259 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7260 reply_doserror(req, ERRSRV, ERRerror);
7263 /****************************************************************************
7264 Reply to a SMBfindclose (stop trans2 directory search).
7265 ****************************************************************************/
7267 void reply_findclose(struct smb_request *req)
7271 START_PROFILE(SMBfindclose);
7274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7275 END_PROFILE(SMBfindclose);
7279 dptr_num = SVALS(req->inbuf,smb_vwv0);
7281 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7283 dptr_close(&dptr_num);
7285 reply_outbuf(req, 0, 0);
7287 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7289 END_PROFILE(SMBfindclose);
7293 /****************************************************************************
7294 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7295 ****************************************************************************/
7297 void reply_findnclose(struct smb_request *req)
7301 START_PROFILE(SMBfindnclose);
7304 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7305 END_PROFILE(SMBfindnclose);
7309 dptr_num = SVAL(req->inbuf,smb_vwv0);
7311 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7313 /* We never give out valid handles for a
7314 findnotifyfirst - so any dptr_num is ok here.
7317 reply_outbuf(req, 0, 0);
7319 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7321 END_PROFILE(SMBfindnclose);
7325 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7326 struct trans_state *state)
7328 if (Protocol >= PROTOCOL_NT1) {
7329 req->flags2 |= 0x40; /* IS_LONG_NAME */
7330 SSVAL(req->inbuf,smb_flg2,req->flags2);
7333 if (conn->encrypt_level == Required && !req->encrypted) {
7334 if (state->call != TRANSACT2_QFSINFO &&
7335 state->call != TRANSACT2_SETFSINFO) {
7336 DEBUG(0,("handle_trans2: encryption required "
7338 (unsigned int)state->call));
7339 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7344 /* Now we must call the relevant TRANS2 function */
7345 switch(state->call) {
7346 case TRANSACT2_OPEN:
7348 START_PROFILE(Trans2_open);
7349 call_trans2open(conn, req,
7350 &state->param, state->total_param,
7351 &state->data, state->total_data,
7352 state->max_data_return);
7353 END_PROFILE(Trans2_open);
7357 case TRANSACT2_FINDFIRST:
7359 START_PROFILE(Trans2_findfirst);
7360 call_trans2findfirst(conn, req,
7361 &state->param, state->total_param,
7362 &state->data, state->total_data,
7363 state->max_data_return);
7364 END_PROFILE(Trans2_findfirst);
7368 case TRANSACT2_FINDNEXT:
7370 START_PROFILE(Trans2_findnext);
7371 call_trans2findnext(conn, req,
7372 &state->param, state->total_param,
7373 &state->data, state->total_data,
7374 state->max_data_return);
7375 END_PROFILE(Trans2_findnext);
7379 case TRANSACT2_QFSINFO:
7381 START_PROFILE(Trans2_qfsinfo);
7382 call_trans2qfsinfo(conn, req,
7383 &state->param, state->total_param,
7384 &state->data, state->total_data,
7385 state->max_data_return);
7386 END_PROFILE(Trans2_qfsinfo);
7390 case TRANSACT2_SETFSINFO:
7392 START_PROFILE(Trans2_setfsinfo);
7393 call_trans2setfsinfo(conn, req,
7394 &state->param, state->total_param,
7395 &state->data, state->total_data,
7396 state->max_data_return);
7397 END_PROFILE(Trans2_setfsinfo);
7401 case TRANSACT2_QPATHINFO:
7402 case TRANSACT2_QFILEINFO:
7404 START_PROFILE(Trans2_qpathinfo);
7405 call_trans2qfilepathinfo(conn, req, state->call,
7406 &state->param, state->total_param,
7407 &state->data, state->total_data,
7408 state->max_data_return);
7409 END_PROFILE(Trans2_qpathinfo);
7413 case TRANSACT2_SETPATHINFO:
7414 case TRANSACT2_SETFILEINFO:
7416 START_PROFILE(Trans2_setpathinfo);
7417 call_trans2setfilepathinfo(conn, req, state->call,
7418 &state->param, state->total_param,
7419 &state->data, state->total_data,
7420 state->max_data_return);
7421 END_PROFILE(Trans2_setpathinfo);
7425 case TRANSACT2_FINDNOTIFYFIRST:
7427 START_PROFILE(Trans2_findnotifyfirst);
7428 call_trans2findnotifyfirst(conn, req,
7429 &state->param, state->total_param,
7430 &state->data, state->total_data,
7431 state->max_data_return);
7432 END_PROFILE(Trans2_findnotifyfirst);
7436 case TRANSACT2_FINDNOTIFYNEXT:
7438 START_PROFILE(Trans2_findnotifynext);
7439 call_trans2findnotifynext(conn, req,
7440 &state->param, state->total_param,
7441 &state->data, state->total_data,
7442 state->max_data_return);
7443 END_PROFILE(Trans2_findnotifynext);
7447 case TRANSACT2_MKDIR:
7449 START_PROFILE(Trans2_mkdir);
7450 call_trans2mkdir(conn, req,
7451 &state->param, state->total_param,
7452 &state->data, state->total_data,
7453 state->max_data_return);
7454 END_PROFILE(Trans2_mkdir);
7458 case TRANSACT2_GET_DFS_REFERRAL:
7460 START_PROFILE(Trans2_get_dfs_referral);
7461 call_trans2getdfsreferral(conn, req,
7462 &state->param, state->total_param,
7463 &state->data, state->total_data,
7464 state->max_data_return);
7465 END_PROFILE(Trans2_get_dfs_referral);
7469 case TRANSACT2_IOCTL:
7471 START_PROFILE(Trans2_ioctl);
7472 call_trans2ioctl(conn, req,
7473 &state->param, state->total_param,
7474 &state->data, state->total_data,
7475 state->max_data_return);
7476 END_PROFILE(Trans2_ioctl);
7481 /* Error in request */
7482 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7483 reply_doserror(req, ERRSRV,ERRerror);
7487 /****************************************************************************
7488 Reply to a SMBtrans2.
7489 ****************************************************************************/
7491 void reply_trans2(struct smb_request *req)
7493 connection_struct *conn = req->conn;
7498 unsigned int tran_call;
7500 unsigned int av_size;
7501 struct trans_state *state;
7504 START_PROFILE(SMBtrans2);
7506 if (req->wct < 14) {
7507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7508 END_PROFILE(SMBtrans2);
7512 dsoff = SVAL(req->inbuf, smb_dsoff);
7513 dscnt = SVAL(req->inbuf, smb_dscnt);
7514 psoff = SVAL(req->inbuf, smb_psoff);
7515 pscnt = SVAL(req->inbuf, smb_pscnt);
7516 tran_call = SVAL(req->inbuf, smb_setup0);
7517 size = smb_len(req->inbuf) + 4;
7518 av_size = smb_len(req->inbuf);
7520 result = allow_new_trans(conn->pending_trans, req->mid);
7521 if (!NT_STATUS_IS_OK(result)) {
7522 DEBUG(2, ("Got invalid trans2 request: %s\n",
7523 nt_errstr(result)));
7524 reply_nterror(req, result);
7525 END_PROFILE(SMBtrans2);
7530 switch (tran_call) {
7531 /* List the allowed trans2 calls on IPC$ */
7532 case TRANSACT2_OPEN:
7533 case TRANSACT2_GET_DFS_REFERRAL:
7534 case TRANSACT2_QFILEINFO:
7535 case TRANSACT2_QFSINFO:
7536 case TRANSACT2_SETFSINFO:
7539 reply_doserror(req, ERRSRV, ERRaccess);
7540 END_PROFILE(SMBtrans2);
7545 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7546 DEBUG(0, ("talloc failed\n"));
7547 reply_nterror(req, NT_STATUS_NO_MEMORY);
7548 END_PROFILE(SMBtrans2);
7552 state->cmd = SMBtrans2;
7554 state->mid = req->mid;
7555 state->vuid = req->vuid;
7556 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7557 state->setup = NULL;
7558 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7559 state->param = NULL;
7560 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7562 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7563 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7564 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7565 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7566 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7568 state->call = tran_call;
7570 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7571 is so as a sanity check */
7572 if (state->setup_count != 1) {
7574 * Need to have rc=0 for ioctl to get job id for OS/2.
7575 * Network printing will fail if function is not successful.
7576 * Similar function in reply.c will be used if protocol
7577 * is LANMAN1.0 instead of LM1.2X002.
7578 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7579 * outbuf doesn't have to be set(only job id is used).
7581 if ( (state->setup_count == 4)
7582 && (tran_call == TRANSACT2_IOCTL)
7583 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7584 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7585 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7587 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7588 DEBUG(2,("Transaction is %d\n",tran_call));
7590 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7591 END_PROFILE(SMBtrans2);
7596 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7599 if (state->total_data) {
7600 /* Can't use talloc here, the core routines do realloc on the
7601 * params and data. */
7602 state->data = (char *)SMB_MALLOC(state->total_data);
7603 if (state->data == NULL) {
7604 DEBUG(0,("reply_trans2: data malloc fail for %u "
7605 "bytes !\n", (unsigned int)state->total_data));
7607 reply_nterror(req, NT_STATUS_NO_MEMORY);
7608 END_PROFILE(SMBtrans2);
7612 if (dscnt > state->total_data ||
7613 dsoff+dscnt < dsoff) {
7617 if (dsoff > av_size ||
7619 dsoff+dscnt > av_size) {
7623 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7626 if (state->total_param) {
7627 /* Can't use talloc here, the core routines do realloc on the
7628 * params and data. */
7629 state->param = (char *)SMB_MALLOC(state->total_param);
7630 if (state->param == NULL) {
7631 DEBUG(0,("reply_trans: param malloc fail for %u "
7632 "bytes !\n", (unsigned int)state->total_param));
7633 SAFE_FREE(state->data);
7635 reply_nterror(req, NT_STATUS_NO_MEMORY);
7636 END_PROFILE(SMBtrans2);
7640 if (pscnt > state->total_param ||
7641 psoff+pscnt < psoff) {
7645 if (psoff > av_size ||
7647 psoff+pscnt > av_size) {
7651 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7654 state->received_data = dscnt;
7655 state->received_param = pscnt;
7657 if ((state->received_param == state->total_param) &&
7658 (state->received_data == state->total_data)) {
7660 handle_trans2(conn, req, state);
7662 SAFE_FREE(state->data);
7663 SAFE_FREE(state->param);
7665 END_PROFILE(SMBtrans2);
7669 DLIST_ADD(conn->pending_trans, state);
7671 /* We need to send an interim response then receive the rest
7672 of the parameter/data bytes */
7673 reply_outbuf(req, 0, 0);
7674 show_msg((char *)req->outbuf);
7675 END_PROFILE(SMBtrans2);
7680 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7681 SAFE_FREE(state->data);
7682 SAFE_FREE(state->param);
7684 END_PROFILE(SMBtrans2);
7685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7689 /****************************************************************************
7690 Reply to a SMBtranss2
7691 ****************************************************************************/
7693 void reply_transs2(struct smb_request *req)
7695 connection_struct *conn = req->conn;
7696 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7697 struct trans_state *state;
7699 unsigned int av_size;
7701 START_PROFILE(SMBtranss2);
7703 show_msg((char *)req->inbuf);
7706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7707 END_PROFILE(SMBtranss2);
7711 size = smb_len(req->inbuf)+4;
7712 av_size = smb_len(req->inbuf);
7714 for (state = conn->pending_trans; state != NULL;
7715 state = state->next) {
7716 if (state->mid == req->mid) {
7721 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7722 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7723 END_PROFILE(SMBtranss2);
7727 /* Revise state->total_param and state->total_data in case they have
7728 changed downwards */
7730 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7731 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7732 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7733 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7735 pcnt = SVAL(req->inbuf, smb_spscnt);
7736 poff = SVAL(req->inbuf, smb_spsoff);
7737 pdisp = SVAL(req->inbuf, smb_spsdisp);
7739 dcnt = SVAL(req->inbuf, smb_sdscnt);
7740 doff = SVAL(req->inbuf, smb_sdsoff);
7741 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7743 state->received_param += pcnt;
7744 state->received_data += dcnt;
7746 if ((state->received_data > state->total_data) ||
7747 (state->received_param > state->total_param))
7751 if (pdisp > state->total_param ||
7752 pcnt > state->total_param ||
7753 pdisp+pcnt > state->total_param ||
7754 pdisp+pcnt < pdisp) {
7758 if (poff > av_size ||
7760 poff+pcnt > av_size ||
7765 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7770 if (ddisp > state->total_data ||
7771 dcnt > state->total_data ||
7772 ddisp+dcnt > state->total_data ||
7773 ddisp+dcnt < ddisp) {
7777 if (ddisp > av_size ||
7779 ddisp+dcnt > av_size ||
7780 ddisp+dcnt < ddisp) {
7784 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7788 if ((state->received_param < state->total_param) ||
7789 (state->received_data < state->total_data)) {
7790 END_PROFILE(SMBtranss2);
7795 * construct_reply_common will copy smb_com from inbuf to
7796 * outbuf. SMBtranss2 is wrong here.
7798 SCVAL(req->inbuf,smb_com,SMBtrans2);
7800 handle_trans2(conn, req, state);
7802 DLIST_REMOVE(conn->pending_trans, state);
7803 SAFE_FREE(state->data);
7804 SAFE_FREE(state->param);
7807 END_PROFILE(SMBtranss2);
7812 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7813 DLIST_REMOVE(conn->pending_trans, state);
7814 SAFE_FREE(state->data);
7815 SAFE_FREE(state->param);
7817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7818 END_PROFILE(SMBtranss2);